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