Line data Source code
1 : /* BGP nexthop scan
2 : Copyright (C) 2000 Kunihiro Ishiguro
3 :
4 : This file is part of GNU Zebra.
5 :
6 : GNU Zebra is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU General Public License as published by the
8 : Free Software Foundation; either version 2, or (at your option) any
9 : later version.
10 :
11 : GNU Zebra is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GNU Zebra; see the file COPYING. If not, write to the Free
18 : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 : 02111-1307, USA. */
20 :
21 : #include <zebra.h>
22 :
23 : #include "command.h"
24 : #include "thread.h"
25 : #include "prefix.h"
26 : #include "zclient.h"
27 : #include "stream.h"
28 : #include "network.h"
29 : #include "log.h"
30 : #include "memory.h"
31 : #include "hash.h"
32 : #include "jhash.h"
33 :
34 : #include "bgpd/bgpd.h"
35 : #include "bgpd/bgp_table.h"
36 : #include "bgpd/bgp_route.h"
37 : #include "bgpd/bgp_attr.h"
38 : #include "bgpd/bgp_nexthop.h"
39 : #include "bgpd/bgp_debug.h"
40 : #include "bgpd/bgp_damp.h"
41 : #include "zebra/rib.h"
42 : #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
43 :
44 : struct bgp_nexthop_cache *zlookup_query (struct in_addr);
45 : #ifdef HAVE_IPV6
46 : struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
47 : #endif /* HAVE_IPV6 */
48 :
49 : /* Only one BGP scan thread are activated at the same time. */
50 : static struct thread *bgp_scan_thread = NULL;
51 :
52 : /* BGP import thread */
53 : static struct thread *bgp_import_thread = NULL;
54 :
55 : /* BGP scan interval. */
56 : static int bgp_scan_interval;
57 :
58 : /* BGP import interval. */
59 : static int bgp_import_interval;
60 :
61 : /* Route table for next-hop lookup cache. */
62 : static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
63 : static struct bgp_table *cache1_table[AFI_MAX];
64 : static struct bgp_table *cache2_table[AFI_MAX];
65 :
66 : /* Route table for connected route. */
67 : static struct bgp_table *bgp_connected_table[AFI_MAX];
68 :
69 : /* BGP nexthop lookup query client. */
70 : struct zclient *zlookup = NULL;
71 :
72 : /* Add nexthop to the end of the list. */
73 : static void
74 0 : bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
75 : {
76 : struct nexthop *last;
77 :
78 0 : for (last = bnc->nexthop; last && last->next; last = last->next)
79 : ;
80 0 : if (last)
81 0 : last->next = nexthop;
82 : else
83 0 : bnc->nexthop = nexthop;
84 0 : nexthop->prev = last;
85 0 : }
86 :
87 : static void
88 0 : bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
89 : {
90 : struct nexthop *nexthop;
91 0 : struct nexthop *next = NULL;
92 :
93 0 : for (nexthop = bnc->nexthop; nexthop; nexthop = next)
94 : {
95 0 : next = nexthop->next;
96 0 : XFREE (MTYPE_NEXTHOP, nexthop);
97 : }
98 0 : }
99 :
100 : static struct bgp_nexthop_cache *
101 0 : bnc_new (void)
102 : {
103 0 : return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
104 : }
105 :
106 : static void
107 0 : bnc_free (struct bgp_nexthop_cache *bnc)
108 : {
109 0 : bnc_nexthop_free (bnc);
110 0 : XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
111 0 : }
112 :
113 : static int
114 0 : bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
115 : {
116 0 : if (next1->type != next2->type)
117 0 : return 0;
118 :
119 0 : switch (next1->type)
120 : {
121 : case ZEBRA_NEXTHOP_IPV4:
122 0 : if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
123 0 : return 0;
124 0 : break;
125 : case ZEBRA_NEXTHOP_IPV4_IFINDEX:
126 0 : if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)
127 0 : || next1->ifindex != next2->ifindex)
128 0 : return 0;
129 0 : break;
130 : case ZEBRA_NEXTHOP_IFINDEX:
131 : case ZEBRA_NEXTHOP_IFNAME:
132 0 : if (next1->ifindex != next2->ifindex)
133 0 : return 0;
134 0 : break;
135 : #ifdef HAVE_IPV6
136 : case ZEBRA_NEXTHOP_IPV6:
137 0 : if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
138 0 : return 0;
139 0 : break;
140 : case ZEBRA_NEXTHOP_IPV6_IFINDEX:
141 : case ZEBRA_NEXTHOP_IPV6_IFNAME:
142 0 : if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
143 0 : return 0;
144 0 : if (next1->ifindex != next2->ifindex)
145 0 : return 0;
146 0 : break;
147 : #endif /* HAVE_IPV6 */
148 : default:
149 : /* do nothing */
150 0 : break;
151 : }
152 0 : return 1;
153 : }
154 :
155 : static int
156 0 : bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
157 : struct bgp_nexthop_cache *bnc2)
158 : {
159 : int i;
160 : struct nexthop *next1, *next2;
161 :
162 0 : if (bnc1->nexthop_num != bnc2->nexthop_num)
163 0 : return 1;
164 :
165 0 : next1 = bnc1->nexthop;
166 0 : next2 = bnc2->nexthop;
167 :
168 0 : for (i = 0; i < bnc1->nexthop_num; i++)
169 : {
170 0 : if (! bgp_nexthop_same (next1, next2))
171 0 : return 1;
172 :
173 0 : next1 = next1->next;
174 0 : next2 = next2->next;
175 : }
176 0 : return 0;
177 : }
178 :
179 : /* If nexthop exists on connected network return 1. */
180 : int
181 0 : bgp_nexthop_onlink (afi_t afi, struct attr *attr)
182 : {
183 : struct bgp_node *rn;
184 :
185 : /* If zebra is not enabled return */
186 0 : if (zlookup->sock < 0)
187 0 : return 1;
188 :
189 : /* Lookup the address is onlink or not. */
190 0 : if (afi == AFI_IP)
191 : {
192 0 : rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
193 0 : if (rn)
194 : {
195 0 : bgp_unlock_node (rn);
196 0 : return 1;
197 : }
198 : }
199 : #ifdef HAVE_IPV6
200 0 : else if (afi == AFI_IP6)
201 : {
202 0 : if (attr->extra->mp_nexthop_len == 32)
203 0 : return 1;
204 0 : else if (attr->extra->mp_nexthop_len == 16)
205 : {
206 0 : if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
207 0 : return 1;
208 :
209 0 : rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
210 0 : &attr->extra->mp_nexthop_global);
211 0 : if (rn)
212 : {
213 0 : bgp_unlock_node (rn);
214 0 : return 1;
215 : }
216 : }
217 : }
218 : #endif /* HAVE_IPV6 */
219 0 : return 0;
220 : }
221 :
222 : #ifdef HAVE_IPV6
223 : /* Check specified next-hop is reachable or not. */
224 : static int
225 0 : bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
226 : int *metricchanged)
227 : {
228 : struct bgp_node *rn;
229 : struct prefix p;
230 : struct bgp_nexthop_cache *bnc;
231 : struct attr *attr;
232 :
233 : /* If lookup is not enabled, return valid. */
234 0 : if (zlookup->sock < 0)
235 : {
236 0 : if (ri->extra)
237 0 : ri->extra->igpmetric = 0;
238 0 : return 1;
239 : }
240 :
241 : /* Only check IPv6 global address only nexthop. */
242 0 : attr = ri->attr;
243 :
244 0 : if (attr->extra->mp_nexthop_len != 16
245 0 : || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
246 0 : return 1;
247 :
248 0 : memset (&p, 0, sizeof (struct prefix));
249 0 : p.family = AF_INET6;
250 0 : p.prefixlen = IPV6_MAX_BITLEN;
251 0 : p.u.prefix6 = attr->extra->mp_nexthop_global;
252 :
253 : /* IBGP or ebgp-multihop */
254 0 : rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
255 :
256 0 : if (rn->info)
257 : {
258 0 : bnc = rn->info;
259 0 : bgp_unlock_node (rn);
260 : }
261 : else
262 : {
263 0 : if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
264 0 : bnc = bnc_new ();
265 : else
266 : {
267 0 : if (changed)
268 : {
269 : struct bgp_table *old;
270 : struct bgp_node *oldrn;
271 :
272 0 : if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
273 0 : old = cache2_table[AFI_IP6];
274 : else
275 0 : old = cache1_table[AFI_IP6];
276 :
277 0 : oldrn = bgp_node_lookup (old, &p);
278 0 : if (oldrn)
279 : {
280 0 : struct bgp_nexthop_cache *oldbnc = oldrn->info;
281 :
282 0 : bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
283 :
284 0 : if (bnc->metric != oldbnc->metric)
285 0 : bnc->metricchanged = 1;
286 :
287 0 : bgp_unlock_node (oldrn);
288 : }
289 : }
290 : }
291 0 : rn->info = bnc;
292 : }
293 :
294 0 : if (changed)
295 0 : *changed = bnc->changed;
296 :
297 0 : if (metricchanged)
298 0 : *metricchanged = bnc->metricchanged;
299 :
300 0 : if (bnc->valid && bnc->metric)
301 0 : (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
302 0 : else if (ri->extra)
303 0 : ri->extra->igpmetric = 0;
304 :
305 0 : return bnc->valid;
306 : }
307 : #endif /* HAVE_IPV6 */
308 :
309 : /* Check specified next-hop is reachable or not. */
310 : int
311 0 : bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
312 : int *changed, int *metricchanged)
313 : {
314 : struct bgp_node *rn;
315 : struct prefix p;
316 : struct bgp_nexthop_cache *bnc;
317 : struct in_addr addr;
318 :
319 : /* If lookup is not enabled, return valid. */
320 0 : if (zlookup->sock < 0)
321 : {
322 0 : if (ri->extra)
323 0 : ri->extra->igpmetric = 0;
324 0 : return 1;
325 : }
326 :
327 : #ifdef HAVE_IPV6
328 0 : if (afi == AFI_IP6)
329 0 : return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
330 : #endif /* HAVE_IPV6 */
331 :
332 0 : addr = ri->attr->nexthop;
333 :
334 0 : memset (&p, 0, sizeof (struct prefix));
335 0 : p.family = AF_INET;
336 0 : p.prefixlen = IPV4_MAX_BITLEN;
337 0 : p.u.prefix4 = addr;
338 :
339 : /* IBGP or ebgp-multihop */
340 0 : rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
341 :
342 0 : if (rn->info)
343 : {
344 0 : bnc = rn->info;
345 0 : bgp_unlock_node (rn);
346 : }
347 : else
348 : {
349 0 : if (NULL == (bnc = zlookup_query (addr)))
350 0 : bnc = bnc_new ();
351 : else
352 : {
353 0 : if (changed)
354 : {
355 : struct bgp_table *old;
356 : struct bgp_node *oldrn;
357 :
358 0 : if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
359 0 : old = cache2_table[AFI_IP];
360 : else
361 0 : old = cache1_table[AFI_IP];
362 :
363 0 : oldrn = bgp_node_lookup (old, &p);
364 0 : if (oldrn)
365 : {
366 0 : struct bgp_nexthop_cache *oldbnc = oldrn->info;
367 :
368 0 : bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
369 :
370 0 : if (bnc->metric != oldbnc->metric)
371 0 : bnc->metricchanged = 1;
372 :
373 0 : bgp_unlock_node (oldrn);
374 : }
375 : }
376 : }
377 0 : rn->info = bnc;
378 : }
379 :
380 0 : if (changed)
381 0 : *changed = bnc->changed;
382 :
383 0 : if (metricchanged)
384 0 : *metricchanged = bnc->metricchanged;
385 :
386 0 : if (bnc->valid && bnc->metric)
387 0 : (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
388 0 : else if (ri->extra)
389 0 : ri->extra->igpmetric = 0;
390 :
391 0 : return bnc->valid;
392 : }
393 :
394 : /* Reset and free all BGP nexthop cache. */
395 : static void
396 0 : bgp_nexthop_cache_reset (struct bgp_table *table)
397 : {
398 : struct bgp_node *rn;
399 : struct bgp_nexthop_cache *bnc;
400 :
401 0 : for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
402 0 : if ((bnc = rn->info) != NULL)
403 : {
404 0 : bnc_free (bnc);
405 0 : rn->info = NULL;
406 0 : bgp_unlock_node (rn);
407 : }
408 0 : }
409 :
410 : static void
411 0 : bgp_scan (afi_t afi, safi_t safi)
412 : {
413 : struct bgp_node *rn;
414 : struct bgp *bgp;
415 : struct bgp_info *bi;
416 : struct bgp_info *next;
417 : struct peer *peer;
418 : struct listnode *node, *nnode;
419 : int valid;
420 : int current;
421 : int changed;
422 : int metricchanged;
423 :
424 : /* Change cache. */
425 0 : if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
426 0 : bgp_nexthop_cache_table[afi] = cache2_table[afi];
427 : else
428 0 : bgp_nexthop_cache_table[afi] = cache1_table[afi];
429 :
430 : /* Get default bgp. */
431 0 : bgp = bgp_get_default ();
432 0 : if (bgp == NULL)
433 0 : return;
434 :
435 : /* Maximum prefix check */
436 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
437 : {
438 0 : if (peer->status != Established)
439 0 : continue;
440 :
441 0 : if (peer->afc[afi][SAFI_UNICAST])
442 0 : bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
443 0 : if (peer->afc[afi][SAFI_MULTICAST])
444 0 : bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
445 0 : if (peer->afc[afi][SAFI_MPLS_VPN])
446 0 : bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
447 : }
448 :
449 0 : for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
450 0 : rn = bgp_route_next (rn))
451 : {
452 0 : for (bi = rn->info; bi; bi = next)
453 : {
454 0 : next = bi->next;
455 :
456 0 : if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
457 : {
458 0 : changed = 0;
459 0 : metricchanged = 0;
460 :
461 0 : if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1
462 0 : && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
463 0 : valid = bgp_nexthop_onlink (afi, bi->attr);
464 : else
465 0 : valid = bgp_nexthop_lookup (afi, bi->peer, bi,
466 : &changed, &metricchanged);
467 :
468 0 : current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
469 :
470 0 : if (changed)
471 0 : SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
472 : else
473 0 : UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
474 :
475 0 : if (valid != current)
476 : {
477 0 : if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
478 : {
479 0 : bgp_aggregate_decrement (bgp, &rn->p, bi,
480 : afi, SAFI_UNICAST);
481 0 : bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
482 : }
483 : else
484 : {
485 0 : bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
486 0 : bgp_aggregate_increment (bgp, &rn->p, bi,
487 : afi, SAFI_UNICAST);
488 : }
489 : }
490 :
491 0 : if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
492 : BGP_CONFIG_DAMPENING)
493 0 : && bi->extra && bi->extra->damp_info )
494 0 : if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
495 0 : bgp_aggregate_increment (bgp, &rn->p, bi,
496 : afi, SAFI_UNICAST);
497 : }
498 : }
499 0 : bgp_process (bgp, rn, afi, SAFI_UNICAST);
500 : }
501 :
502 : /* Flash old cache. */
503 0 : if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
504 0 : bgp_nexthop_cache_reset (cache2_table[afi]);
505 : else
506 0 : bgp_nexthop_cache_reset (cache1_table[afi]);
507 :
508 0 : if (BGP_DEBUG (events, EVENTS))
509 : {
510 0 : if (afi == AFI_IP)
511 0 : zlog_debug ("scanning IPv4 Unicast routing tables");
512 0 : else if (afi == AFI_IP6)
513 0 : zlog_debug ("scanning IPv6 Unicast routing tables");
514 : }
515 :
516 : /* Reevaluate default-originate route-maps and announce/withdraw
517 : * default route if neccesary. */
518 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
519 : {
520 0 : if (peer->status == Established
521 0 : && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
522 0 : && peer->default_rmap[afi][safi].name)
523 0 : bgp_default_originate (peer, afi, safi, 0);
524 : }
525 : }
526 :
527 : /* BGP scan thread. This thread check nexthop reachability. */
528 : static int
529 0 : bgp_scan_timer (struct thread *t)
530 : {
531 0 : bgp_scan_thread =
532 0 : thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
533 :
534 0 : if (BGP_DEBUG (events, EVENTS))
535 0 : zlog_debug ("Performing BGP general scanning");
536 :
537 0 : bgp_scan (AFI_IP, SAFI_UNICAST);
538 :
539 : #ifdef HAVE_IPV6
540 0 : bgp_scan (AFI_IP6, SAFI_UNICAST);
541 : #endif /* HAVE_IPV6 */
542 :
543 0 : return 0;
544 : }
545 :
546 : /* BGP own address structure */
547 : struct bgp_addr
548 : {
549 : struct in_addr addr;
550 : int refcnt;
551 : };
552 :
553 : static struct hash *bgp_address_hash;
554 :
555 : static void *
556 0 : bgp_address_hash_alloc (void *p)
557 : {
558 0 : struct in_addr *val = p;
559 : struct bgp_addr *addr;
560 :
561 0 : addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
562 0 : addr->refcnt = 0;
563 0 : addr->addr.s_addr = val->s_addr;
564 :
565 0 : return addr;
566 : }
567 :
568 : static unsigned int
569 0 : bgp_address_hash_key_make (void *p)
570 : {
571 0 : const struct bgp_addr *addr = p;
572 :
573 0 : return jhash_1word(addr->addr.s_addr, 0);
574 : }
575 :
576 : static int
577 0 : bgp_address_hash_cmp (const void *p1, const void *p2)
578 : {
579 0 : const struct bgp_addr *addr1 = p1;
580 0 : const struct bgp_addr *addr2 = p2;
581 :
582 0 : return addr1->addr.s_addr == addr2->addr.s_addr;
583 : }
584 :
585 : void
586 0 : bgp_address_init (void)
587 : {
588 0 : bgp_address_hash = hash_create (bgp_address_hash_key_make,
589 : bgp_address_hash_cmp);
590 0 : }
591 :
592 : static void
593 0 : bgp_address_add (struct prefix *p)
594 : {
595 : struct bgp_addr tmp;
596 : struct bgp_addr *addr;
597 :
598 0 : tmp.addr = p->u.prefix4;
599 :
600 0 : addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
601 0 : addr->refcnt++;
602 0 : }
603 :
604 : static void
605 0 : bgp_address_del (struct prefix *p)
606 : {
607 : struct bgp_addr tmp;
608 : struct bgp_addr *addr;
609 :
610 0 : tmp.addr = p->u.prefix4;
611 :
612 0 : addr = hash_lookup (bgp_address_hash, &tmp);
613 : /* may have been deleted earlier by bgp_interface_down() */
614 0 : if (addr == NULL)
615 0 : return;
616 :
617 0 : addr->refcnt--;
618 :
619 0 : if (addr->refcnt == 0)
620 : {
621 0 : hash_release (bgp_address_hash, addr);
622 0 : XFREE (MTYPE_BGP_ADDR, addr);
623 : }
624 : }
625 :
626 :
627 : struct bgp_connected_ref
628 : {
629 : unsigned int refcnt;
630 : };
631 :
632 : void
633 0 : bgp_connected_add (struct connected *ifc)
634 : {
635 : struct prefix p;
636 : struct prefix *addr;
637 : struct interface *ifp;
638 : struct bgp_node *rn;
639 : struct bgp_connected_ref *bc;
640 :
641 0 : ifp = ifc->ifp;
642 :
643 0 : if (! ifp)
644 0 : return;
645 :
646 0 : if (if_is_loopback (ifp))
647 0 : return;
648 :
649 0 : addr = ifc->address;
650 :
651 0 : if (addr->family == AF_INET)
652 : {
653 0 : PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
654 0 : apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
655 :
656 0 : if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
657 0 : return;
658 :
659 0 : bgp_address_add (addr);
660 :
661 0 : rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
662 0 : if (rn->info)
663 : {
664 0 : bc = rn->info;
665 0 : bc->refcnt++;
666 : }
667 : else
668 : {
669 0 : bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
670 0 : bc->refcnt = 1;
671 0 : rn->info = bc;
672 : }
673 : }
674 : #ifdef HAVE_IPV6
675 0 : else if (addr->family == AF_INET6)
676 : {
677 0 : PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
678 0 : apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
679 :
680 0 : if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
681 0 : return;
682 :
683 0 : if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
684 0 : return;
685 :
686 0 : rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
687 0 : if (rn->info)
688 : {
689 0 : bc = rn->info;
690 0 : bc->refcnt++;
691 : }
692 : else
693 : {
694 0 : bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
695 0 : bc->refcnt = 1;
696 0 : rn->info = bc;
697 : }
698 : }
699 : #endif /* HAVE_IPV6 */
700 : }
701 :
702 : void
703 0 : bgp_connected_delete (struct connected *ifc)
704 : {
705 : struct prefix p;
706 : struct prefix *addr;
707 : struct interface *ifp;
708 : struct bgp_node *rn;
709 : struct bgp_connected_ref *bc;
710 :
711 0 : ifp = ifc->ifp;
712 :
713 0 : if (if_is_loopback (ifp))
714 0 : return;
715 :
716 0 : addr = ifc->address;
717 :
718 0 : if (addr->family == AF_INET)
719 : {
720 0 : PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
721 0 : apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
722 :
723 0 : if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
724 0 : return;
725 :
726 0 : bgp_address_del (addr);
727 :
728 0 : rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
729 0 : if (! rn)
730 0 : return;
731 :
732 0 : bc = rn->info;
733 0 : bc->refcnt--;
734 0 : if (bc->refcnt == 0)
735 : {
736 0 : XFREE (MTYPE_BGP_CONN, bc);
737 0 : rn->info = NULL;
738 : }
739 0 : bgp_unlock_node (rn);
740 0 : bgp_unlock_node (rn);
741 : }
742 : #ifdef HAVE_IPV6
743 0 : else if (addr->family == AF_INET6)
744 : {
745 0 : PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
746 0 : apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
747 :
748 0 : if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
749 0 : return;
750 :
751 0 : if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
752 0 : return;
753 :
754 0 : rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
755 0 : if (! rn)
756 0 : return;
757 :
758 0 : bc = rn->info;
759 0 : bc->refcnt--;
760 0 : if (bc->refcnt == 0)
761 : {
762 0 : XFREE (MTYPE_BGP_CONN, bc);
763 0 : rn->info = NULL;
764 : }
765 0 : bgp_unlock_node (rn);
766 0 : bgp_unlock_node (rn);
767 : }
768 : #endif /* HAVE_IPV6 */
769 : }
770 :
771 : int
772 0 : bgp_nexthop_self (struct attr *attr)
773 : {
774 : struct bgp_addr tmp, *addr;
775 :
776 0 : tmp.addr = attr->nexthop;
777 :
778 0 : addr = hash_lookup (bgp_address_hash, &tmp);
779 0 : if (addr)
780 0 : return 1;
781 :
782 0 : return 0;
783 : }
784 :
785 : static struct bgp_nexthop_cache *
786 0 : zlookup_read (void)
787 : {
788 : struct stream *s;
789 : uint16_t length;
790 : u_char marker;
791 : u_char version;
792 : uint16_t command;
793 : int nbytes;
794 : struct in_addr raddr;
795 : uint32_t metric;
796 : int i;
797 : u_char nexthop_num;
798 : struct nexthop *nexthop;
799 : struct bgp_nexthop_cache *bnc;
800 :
801 0 : s = zlookup->ibuf;
802 0 : stream_reset (s);
803 :
804 0 : nbytes = stream_read (s, zlookup->sock, 2);
805 0 : length = stream_getw (s);
806 :
807 0 : nbytes = stream_read (s, zlookup->sock, length - 2);
808 0 : marker = stream_getc (s);
809 0 : version = stream_getc (s);
810 :
811 0 : if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
812 : {
813 0 : zlog_err("%s: socket %d version mismatch, marker %d, version %d",
814 0 : __func__, zlookup->sock, marker, version);
815 0 : return NULL;
816 : }
817 :
818 0 : command = stream_getw (s);
819 :
820 0 : raddr.s_addr = stream_get_ipv4 (s);
821 0 : metric = stream_getl (s);
822 0 : nexthop_num = stream_getc (s);
823 :
824 0 : if (nexthop_num)
825 : {
826 0 : bnc = bnc_new ();
827 0 : bnc->valid = 1;
828 0 : bnc->metric = metric;
829 0 : bnc->nexthop_num = nexthop_num;
830 :
831 0 : for (i = 0; i < nexthop_num; i++)
832 : {
833 0 : nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
834 0 : nexthop->type = stream_getc (s);
835 0 : switch (nexthop->type)
836 : {
837 : case ZEBRA_NEXTHOP_IPV4:
838 0 : nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
839 0 : break;
840 : case ZEBRA_NEXTHOP_IPV4_IFINDEX:
841 0 : nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
842 0 : nexthop->ifindex = stream_getl (s);
843 0 : break;
844 : case ZEBRA_NEXTHOP_IFINDEX:
845 : case ZEBRA_NEXTHOP_IFNAME:
846 0 : nexthop->ifindex = stream_getl (s);
847 0 : break;
848 : default:
849 : /* do nothing */
850 0 : break;
851 : }
852 0 : bnc_nexthop_add (bnc, nexthop);
853 : }
854 : }
855 : else
856 0 : return NULL;
857 :
858 0 : return bnc;
859 : }
860 :
861 : struct bgp_nexthop_cache *
862 0 : zlookup_query (struct in_addr addr)
863 : {
864 : int ret;
865 : struct stream *s;
866 :
867 : /* Check socket. */
868 0 : if (zlookup->sock < 0)
869 0 : return NULL;
870 :
871 0 : s = zlookup->obuf;
872 0 : stream_reset (s);
873 0 : zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
874 0 : stream_put_in_addr (s, &addr);
875 :
876 0 : stream_putw_at (s, 0, stream_get_endp (s));
877 :
878 0 : ret = writen (zlookup->sock, s->data, stream_get_endp (s));
879 0 : if (ret < 0)
880 : {
881 0 : zlog_err ("can't write to zlookup->sock");
882 0 : close (zlookup->sock);
883 0 : zlookup->sock = -1;
884 0 : return NULL;
885 : }
886 0 : if (ret == 0)
887 : {
888 0 : zlog_err ("zlookup->sock connection closed");
889 0 : close (zlookup->sock);
890 0 : zlookup->sock = -1;
891 0 : return NULL;
892 : }
893 :
894 0 : return zlookup_read ();
895 : }
896 :
897 : #ifdef HAVE_IPV6
898 : static struct bgp_nexthop_cache *
899 0 : zlookup_read_ipv6 (void)
900 : {
901 : struct stream *s;
902 : uint16_t length;
903 : u_char version, marker;
904 : uint16_t command;
905 : int nbytes;
906 : struct in6_addr raddr;
907 : uint32_t metric;
908 : int i;
909 : u_char nexthop_num;
910 : struct nexthop *nexthop;
911 : struct bgp_nexthop_cache *bnc;
912 :
913 0 : s = zlookup->ibuf;
914 0 : stream_reset (s);
915 :
916 0 : nbytes = stream_read (s, zlookup->sock, 2);
917 0 : length = stream_getw (s);
918 :
919 0 : nbytes = stream_read (s, zlookup->sock, length - 2);
920 0 : marker = stream_getc (s);
921 0 : version = stream_getc (s);
922 :
923 0 : if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
924 : {
925 0 : zlog_err("%s: socket %d version mismatch, marker %d, version %d",
926 0 : __func__, zlookup->sock, marker, version);
927 0 : return NULL;
928 : }
929 :
930 0 : command = stream_getw (s);
931 :
932 0 : stream_get (&raddr, s, 16);
933 :
934 0 : metric = stream_getl (s);
935 0 : nexthop_num = stream_getc (s);
936 :
937 0 : if (nexthop_num)
938 : {
939 0 : bnc = bnc_new ();
940 0 : bnc->valid = 1;
941 0 : bnc->metric = metric;
942 0 : bnc->nexthop_num = nexthop_num;
943 :
944 0 : for (i = 0; i < nexthop_num; i++)
945 : {
946 0 : nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
947 0 : nexthop->type = stream_getc (s);
948 0 : switch (nexthop->type)
949 : {
950 : case ZEBRA_NEXTHOP_IPV6:
951 0 : stream_get (&nexthop->gate.ipv6, s, 16);
952 0 : break;
953 : case ZEBRA_NEXTHOP_IPV6_IFINDEX:
954 : case ZEBRA_NEXTHOP_IPV6_IFNAME:
955 0 : stream_get (&nexthop->gate.ipv6, s, 16);
956 0 : nexthop->ifindex = stream_getl (s);
957 0 : break;
958 : case ZEBRA_NEXTHOP_IFINDEX:
959 : case ZEBRA_NEXTHOP_IFNAME:
960 0 : nexthop->ifindex = stream_getl (s);
961 0 : break;
962 : default:
963 : /* do nothing */
964 0 : break;
965 : }
966 0 : bnc_nexthop_add (bnc, nexthop);
967 : }
968 : }
969 : else
970 0 : return NULL;
971 :
972 0 : return bnc;
973 : }
974 :
975 : struct bgp_nexthop_cache *
976 0 : zlookup_query_ipv6 (struct in6_addr *addr)
977 : {
978 : int ret;
979 : struct stream *s;
980 :
981 : /* Check socket. */
982 0 : if (zlookup->sock < 0)
983 0 : return NULL;
984 :
985 0 : s = zlookup->obuf;
986 0 : stream_reset (s);
987 0 : zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
988 0 : stream_put (s, addr, 16);
989 0 : stream_putw_at (s, 0, stream_get_endp (s));
990 :
991 0 : ret = writen (zlookup->sock, s->data, stream_get_endp (s));
992 0 : if (ret < 0)
993 : {
994 0 : zlog_err ("can't write to zlookup->sock");
995 0 : close (zlookup->sock);
996 0 : zlookup->sock = -1;
997 0 : return NULL;
998 : }
999 0 : if (ret == 0)
1000 : {
1001 0 : zlog_err ("zlookup->sock connection closed");
1002 0 : close (zlookup->sock);
1003 0 : zlookup->sock = -1;
1004 0 : return NULL;
1005 : }
1006 :
1007 0 : return zlookup_read_ipv6 ();
1008 : }
1009 : #endif /* HAVE_IPV6 */
1010 :
1011 : static int
1012 0 : bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
1013 : struct in_addr *igpnexthop)
1014 : {
1015 : struct stream *s;
1016 : int ret;
1017 : u_int16_t length, command;
1018 : u_char version, marker;
1019 : int nbytes;
1020 : struct in_addr addr;
1021 : struct in_addr nexthop;
1022 0 : u_int32_t metric = 0;
1023 : u_char nexthop_num;
1024 : u_char nexthop_type;
1025 :
1026 : /* If lookup connection is not available return valid. */
1027 0 : if (zlookup->sock < 0)
1028 : {
1029 0 : if (igpmetric)
1030 0 : *igpmetric = 0;
1031 0 : return 1;
1032 : }
1033 :
1034 : /* Send query to the lookup connection */
1035 0 : s = zlookup->obuf;
1036 0 : stream_reset (s);
1037 0 : zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
1038 :
1039 0 : stream_putc (s, p->prefixlen);
1040 0 : stream_put_in_addr (s, &p->u.prefix4);
1041 :
1042 0 : stream_putw_at (s, 0, stream_get_endp (s));
1043 :
1044 : /* Write the packet. */
1045 0 : ret = writen (zlookup->sock, s->data, stream_get_endp (s));
1046 :
1047 0 : if (ret < 0)
1048 : {
1049 0 : zlog_err ("can't write to zlookup->sock");
1050 0 : close (zlookup->sock);
1051 0 : zlookup->sock = -1;
1052 0 : return 1;
1053 : }
1054 0 : if (ret == 0)
1055 : {
1056 0 : zlog_err ("zlookup->sock connection closed");
1057 0 : close (zlookup->sock);
1058 0 : zlookup->sock = -1;
1059 0 : return 1;
1060 : }
1061 :
1062 : /* Get result. */
1063 0 : stream_reset (s);
1064 :
1065 : /* Fetch length. */
1066 0 : nbytes = stream_read (s, zlookup->sock, 2);
1067 0 : length = stream_getw (s);
1068 :
1069 : /* Fetch whole data. */
1070 0 : nbytes = stream_read (s, zlookup->sock, length - 2);
1071 0 : marker = stream_getc (s);
1072 0 : version = stream_getc (s);
1073 :
1074 0 : if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
1075 : {
1076 0 : zlog_err("%s: socket %d version mismatch, marker %d, version %d",
1077 0 : __func__, zlookup->sock, marker, version);
1078 0 : return 0;
1079 : }
1080 :
1081 0 : command = stream_getw (s);
1082 :
1083 0 : addr.s_addr = stream_get_ipv4 (s);
1084 0 : metric = stream_getl (s);
1085 0 : nexthop_num = stream_getc (s);
1086 :
1087 : /* Set IGP metric value. */
1088 0 : if (igpmetric)
1089 0 : *igpmetric = metric;
1090 :
1091 : /* If there is nexthop then this is active route. */
1092 0 : if (nexthop_num)
1093 : {
1094 0 : nexthop.s_addr = 0;
1095 0 : nexthop_type = stream_getc (s);
1096 0 : switch (nexthop_type)
1097 : {
1098 : case ZEBRA_NEXTHOP_IPV4:
1099 0 : nexthop.s_addr = stream_get_ipv4 (s);
1100 0 : break;
1101 : case ZEBRA_NEXTHOP_IPV4_IFINDEX:
1102 0 : nexthop.s_addr = stream_get_ipv4 (s);
1103 0 : /* ifindex */ (void)stream_getl (s);
1104 0 : break;
1105 : default:
1106 : /* do nothing */
1107 0 : break;
1108 : }
1109 0 : *igpnexthop = nexthop;
1110 :
1111 0 : return 1;
1112 : }
1113 : else
1114 0 : return 0;
1115 : }
1116 :
1117 : /* Scan all configured BGP route then check the route exists in IGP or
1118 : not. */
1119 : static int
1120 0 : bgp_import (struct thread *t)
1121 : {
1122 : struct bgp *bgp;
1123 : struct bgp_node *rn;
1124 : struct bgp_static *bgp_static;
1125 : struct listnode *node, *nnode;
1126 : int valid;
1127 : u_int32_t metric;
1128 : struct in_addr nexthop;
1129 : afi_t afi;
1130 : safi_t safi;
1131 :
1132 0 : bgp_import_thread =
1133 0 : thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
1134 :
1135 0 : if (BGP_DEBUG (events, EVENTS))
1136 0 : zlog_debug ("Import timer expired.");
1137 :
1138 0 : for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
1139 : {
1140 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
1141 0 : for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
1142 0 : for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
1143 0 : rn = bgp_route_next (rn))
1144 0 : if ((bgp_static = rn->info) != NULL)
1145 : {
1146 0 : if (bgp_static->backdoor)
1147 0 : continue;
1148 :
1149 0 : valid = bgp_static->valid;
1150 0 : metric = bgp_static->igpmetric;
1151 0 : nexthop = bgp_static->igpnexthop;
1152 :
1153 0 : if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
1154 0 : && afi == AFI_IP && safi == SAFI_UNICAST)
1155 0 : bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
1156 : &bgp_static->igpnexthop);
1157 : else
1158 : {
1159 0 : bgp_static->valid = 1;
1160 0 : bgp_static->igpmetric = 0;
1161 0 : bgp_static->igpnexthop.s_addr = 0;
1162 : }
1163 :
1164 0 : if (bgp_static->valid != valid)
1165 : {
1166 0 : if (bgp_static->valid)
1167 0 : bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1168 : else
1169 0 : bgp_static_withdraw (bgp, &rn->p, afi, safi);
1170 : }
1171 0 : else if (bgp_static->valid)
1172 : {
1173 0 : if (bgp_static->igpmetric != metric
1174 0 : || bgp_static->igpnexthop.s_addr != nexthop.s_addr
1175 0 : || bgp_static->rmap.name)
1176 0 : bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1177 : }
1178 : }
1179 : }
1180 0 : return 0;
1181 : }
1182 :
1183 : /* Connect to zebra for nexthop lookup. */
1184 : static int
1185 0 : zlookup_connect (struct thread *t)
1186 : {
1187 : struct zclient *zlookup;
1188 :
1189 0 : zlookup = THREAD_ARG (t);
1190 0 : zlookup->t_connect = NULL;
1191 :
1192 0 : if (zlookup->sock != -1)
1193 0 : return 0;
1194 :
1195 0 : if (zclient_socket_connect (zlookup) < 0)
1196 0 : return -1;
1197 :
1198 0 : return 0;
1199 : }
1200 :
1201 : /* Check specified multiaccess next-hop. */
1202 : int
1203 0 : bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
1204 : {
1205 : struct bgp_node *rn1;
1206 : struct bgp_node *rn2;
1207 : struct prefix p1;
1208 : struct prefix p2;
1209 : struct in_addr addr;
1210 : int ret;
1211 :
1212 0 : ret = inet_aton (peer, &addr);
1213 0 : if (! ret)
1214 0 : return 0;
1215 :
1216 0 : memset (&p1, 0, sizeof (struct prefix));
1217 0 : p1.family = AF_INET;
1218 0 : p1.prefixlen = IPV4_MAX_BITLEN;
1219 0 : p1.u.prefix4 = nexthop;
1220 0 : memset (&p2, 0, sizeof (struct prefix));
1221 0 : p2.family = AF_INET;
1222 0 : p2.prefixlen = IPV4_MAX_BITLEN;
1223 0 : p2.u.prefix4 = addr;
1224 :
1225 : /* If bgp scan is not enabled, return invalid. */
1226 0 : if (zlookup->sock < 0)
1227 0 : return 0;
1228 :
1229 0 : rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
1230 0 : if (! rn1)
1231 0 : return 0;
1232 0 : bgp_unlock_node (rn1);
1233 :
1234 0 : rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
1235 0 : if (! rn2)
1236 0 : return 0;
1237 0 : bgp_unlock_node (rn2);
1238 :
1239 : /* This is safe, even with above unlocks, since we are just
1240 : comparing pointers to the objects, not the objects themselves. */
1241 0 : if (rn1 == rn2)
1242 0 : return 1;
1243 :
1244 0 : return 0;
1245 : }
1246 :
1247 0 : DEFUN (bgp_scan_time,
1248 : bgp_scan_time_cmd,
1249 : "bgp scan-time <5-60>",
1250 : "BGP specific commands\n"
1251 : "Configure background scanner interval\n"
1252 : "Scanner interval (seconds)\n")
1253 : {
1254 0 : bgp_scan_interval = atoi (argv[0]);
1255 :
1256 0 : if (bgp_scan_thread)
1257 : {
1258 0 : thread_cancel (bgp_scan_thread);
1259 0 : bgp_scan_thread =
1260 0 : thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
1261 : }
1262 :
1263 0 : return CMD_SUCCESS;
1264 : }
1265 :
1266 0 : DEFUN (no_bgp_scan_time,
1267 : no_bgp_scan_time_cmd,
1268 : "no bgp scan-time",
1269 : NO_STR
1270 : "BGP specific commands\n"
1271 : "Configure background scanner interval\n")
1272 : {
1273 0 : bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1274 :
1275 0 : if (bgp_scan_thread)
1276 : {
1277 0 : thread_cancel (bgp_scan_thread);
1278 0 : bgp_scan_thread =
1279 0 : thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
1280 : }
1281 :
1282 0 : return CMD_SUCCESS;
1283 : }
1284 :
1285 : ALIAS (no_bgp_scan_time,
1286 : no_bgp_scan_time_val_cmd,
1287 : "no bgp scan-time <5-60>",
1288 : NO_STR
1289 : "BGP specific commands\n"
1290 : "Configure background scanner interval\n"
1291 : "Scanner interval (seconds)\n")
1292 :
1293 : static int
1294 0 : show_ip_bgp_scan_tables (struct vty *vty, const char detail)
1295 : {
1296 : struct bgp_node *rn;
1297 : struct bgp_nexthop_cache *bnc;
1298 : char buf[INET6_ADDRSTRLEN];
1299 : u_char i;
1300 :
1301 0 : if (bgp_scan_thread)
1302 0 : vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
1303 : else
1304 0 : vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
1305 0 : vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
1306 :
1307 0 : vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
1308 0 : for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
1309 0 : if ((bnc = rn->info) != NULL)
1310 : {
1311 0 : if (bnc->valid)
1312 : {
1313 0 : vty_out (vty, " %s valid [IGP metric %d]%s",
1314 0 : inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
1315 0 : if (detail)
1316 0 : for (i = 0; i < bnc->nexthop_num; i++)
1317 0 : switch (bnc->nexthop[i].type)
1318 : {
1319 : case NEXTHOP_TYPE_IPV4:
1320 0 : vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1321 0 : break;
1322 : case NEXTHOP_TYPE_IPV4_IFINDEX:
1323 0 : vty_out (vty, " gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN));
1324 0 : vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1325 0 : break;
1326 : case NEXTHOP_TYPE_IFINDEX:
1327 0 : vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1328 0 : break;
1329 : default:
1330 0 : vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1331 : }
1332 : }
1333 : else
1334 0 : vty_out (vty, " %s invalid%s",
1335 0 : inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1336 : }
1337 :
1338 : #ifdef HAVE_IPV6
1339 : {
1340 0 : for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
1341 : rn;
1342 0 : rn = bgp_route_next (rn))
1343 0 : if ((bnc = rn->info) != NULL)
1344 : {
1345 0 : if (bnc->valid)
1346 : {
1347 0 : vty_out (vty, " %s valid [IGP metric %d]%s",
1348 0 : inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
1349 0 : bnc->metric, VTY_NEWLINE);
1350 0 : if (detail)
1351 0 : for (i = 0; i < bnc->nexthop_num; i++)
1352 0 : switch (bnc->nexthop[i].type)
1353 : {
1354 : case NEXTHOP_TYPE_IPV6:
1355 0 : vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1356 0 : break;
1357 : case NEXTHOP_TYPE_IFINDEX:
1358 0 : vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1359 0 : break;
1360 : default:
1361 0 : vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1362 : }
1363 : }
1364 : else
1365 0 : vty_out (vty, " %s invalid%s",
1366 0 : inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
1367 0 : VTY_NEWLINE);
1368 : }
1369 : }
1370 : #endif /* HAVE_IPV6 */
1371 :
1372 0 : vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
1373 0 : for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
1374 : rn;
1375 0 : rn = bgp_route_next (rn))
1376 0 : if (rn->info != NULL)
1377 0 : vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
1378 0 : VTY_NEWLINE);
1379 :
1380 : #ifdef HAVE_IPV6
1381 : {
1382 0 : for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
1383 : rn;
1384 0 : rn = bgp_route_next (rn))
1385 0 : if (rn->info != NULL)
1386 0 : vty_out (vty, " %s/%d%s",
1387 0 : inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
1388 0 : rn->p.prefixlen,
1389 0 : VTY_NEWLINE);
1390 : }
1391 : #endif /* HAVE_IPV6 */
1392 :
1393 0 : return CMD_SUCCESS;
1394 : }
1395 :
1396 0 : DEFUN (show_ip_bgp_scan,
1397 : show_ip_bgp_scan_cmd,
1398 : "show ip bgp scan",
1399 : SHOW_STR
1400 : IP_STR
1401 : BGP_STR
1402 : "BGP scan status\n")
1403 : {
1404 0 : return show_ip_bgp_scan_tables (vty, 0);
1405 : }
1406 :
1407 0 : DEFUN (show_ip_bgp_scan_detail,
1408 : show_ip_bgp_scan_detail_cmd,
1409 : "show ip bgp scan detail",
1410 : SHOW_STR
1411 : IP_STR
1412 : BGP_STR
1413 : "BGP scan status\n"
1414 : "More detailed output\n")
1415 : {
1416 0 : return show_ip_bgp_scan_tables (vty, 1);
1417 : }
1418 :
1419 : int
1420 0 : bgp_config_write_scan_time (struct vty *vty)
1421 : {
1422 0 : if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
1423 0 : vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
1424 0 : return CMD_SUCCESS;
1425 : }
1426 :
1427 : void
1428 0 : bgp_scan_init (void)
1429 : {
1430 0 : zlookup = zclient_new ();
1431 0 : zlookup->sock = -1;
1432 0 : zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
1433 :
1434 0 : bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1435 0 : bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
1436 :
1437 0 : cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1438 0 : cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1439 0 : bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
1440 :
1441 0 : bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1442 :
1443 : #ifdef HAVE_IPV6
1444 0 : cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1445 0 : cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1446 0 : bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
1447 0 : bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1448 : #endif /* HAVE_IPV6 */
1449 :
1450 : /* Make BGP scan thread. */
1451 0 : bgp_scan_thread = thread_add_timer (master, bgp_scan_timer,
1452 : NULL, bgp_scan_interval);
1453 : /* Make BGP import there. */
1454 0 : bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
1455 :
1456 0 : install_element (BGP_NODE, &bgp_scan_time_cmd);
1457 0 : install_element (BGP_NODE, &no_bgp_scan_time_cmd);
1458 0 : install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
1459 0 : install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
1460 0 : install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
1461 0 : install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
1462 0 : install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
1463 0 : install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
1464 0 : }
1465 :
1466 : void
1467 0 : bgp_scan_finish (void)
1468 : {
1469 : /* Only the current one needs to be reset. */
1470 0 : bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
1471 :
1472 0 : bgp_table_unlock (cache1_table[AFI_IP]);
1473 0 : cache1_table[AFI_IP] = NULL;
1474 :
1475 0 : bgp_table_unlock (cache2_table[AFI_IP]);
1476 0 : cache2_table[AFI_IP] = NULL;
1477 :
1478 0 : bgp_table_unlock (bgp_connected_table[AFI_IP]);
1479 0 : bgp_connected_table[AFI_IP] = NULL;
1480 :
1481 : #ifdef HAVE_IPV6
1482 : /* Only the current one needs to be reset. */
1483 0 : bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
1484 :
1485 0 : bgp_table_unlock (cache1_table[AFI_IP6]);
1486 0 : cache1_table[AFI_IP6] = NULL;
1487 :
1488 0 : bgp_table_unlock (cache2_table[AFI_IP6]);
1489 0 : cache2_table[AFI_IP6] = NULL;
1490 :
1491 0 : bgp_table_unlock (bgp_connected_table[AFI_IP6]);
1492 0 : bgp_connected_table[AFI_IP6] = NULL;
1493 : #endif /* HAVE_IPV6 */
1494 0 : }
|