]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
bgpd: Prevent IPv6 routes received via a ibgp session with own ip as nexthop
[mirror_frr.git] / bgpd / bgp_nexthop.c
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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
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 #include "nexthop.h"
34 #include "queue.h"
35 #include "filter.h"
36
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_table.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_attr.h"
41 #include "bgpd/bgp_nexthop.h"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_debug.h"
44 #include "bgpd/bgp_damp.h"
45 #include "bgpd/bgp_fsm.h"
46 #include "bgpd/bgp_vty.h"
47
48 DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
49
50 static void bgp_ipv6_address_add(struct bgp *bgp, struct connected *ifc,
51 struct prefix *p);
52 static void bgp_ipv6_address_del(struct bgp *bgp, struct connected *ifc,
53 struct prefix *p);
54
55 char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
56 {
57 prefix2str(&(bnc->node->p), buf, size);
58 return buf;
59 }
60
61 void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
62 {
63 nexthops_free(bnc->nexthop);
64 }
65
66 struct bgp_nexthop_cache *bnc_new(void)
67 {
68 struct bgp_nexthop_cache *bnc;
69
70 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
71 sizeof(struct bgp_nexthop_cache));
72 LIST_INIT(&(bnc->paths));
73 return bnc;
74 }
75
76 void bnc_free(struct bgp_nexthop_cache *bnc)
77 {
78 bnc_nexthop_free(bnc);
79 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
80 }
81
82 /* Reset and free all BGP nexthop cache. */
83 static void bgp_nexthop_cache_reset(struct bgp_table *table)
84 {
85 struct bgp_node *rn;
86 struct bgp_nexthop_cache *bnc;
87
88 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
89 bnc = bgp_node_get_bgp_nexthop_info(rn);
90 if (!bnc)
91 continue;
92
93 while (!LIST_EMPTY(&(bnc->paths))) {
94 struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
95
96 path_nh_map(path, bnc, false);
97 }
98
99 bnc_free(bnc);
100 bgp_node_set_bgp_nexthop_info(rn, NULL);
101 bgp_unlock_node(rn);
102 }
103 }
104
105 static void *bgp_tip_hash_alloc(void *p)
106 {
107 const struct in_addr *val = (const struct in_addr *)p;
108 struct tip_addr *addr;
109
110 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
111 addr->refcnt = 0;
112 addr->addr.s_addr = val->s_addr;
113
114 return addr;
115 }
116
117 static void bgp_tip_hash_free(void *addr)
118 {
119 XFREE(MTYPE_TIP_ADDR, addr);
120 }
121
122 static unsigned int bgp_tip_hash_key_make(void *p)
123 {
124 const struct tip_addr *addr = p;
125
126 return jhash_1word(addr->addr.s_addr, 0);
127 }
128
129 static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
130 {
131 const struct tip_addr *addr1 = p1;
132 const struct tip_addr *addr2 = p2;
133
134 return addr1->addr.s_addr == addr2->addr.s_addr;
135 }
136
137 void bgp_tip_hash_init(struct bgp *bgp)
138 {
139 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
140 "BGP TIP hash");
141 }
142
143 void bgp_tip_hash_destroy(struct bgp *bgp)
144 {
145 if (bgp->tip_hash == NULL)
146 return;
147 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
148 hash_free(bgp->tip_hash);
149 bgp->tip_hash = NULL;
150 }
151
152 void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
153 {
154 struct tip_addr tmp;
155 struct tip_addr *addr;
156
157 tmp.addr = *tip;
158
159 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
160 if (!addr)
161 return;
162
163 addr->refcnt++;
164 }
165
166 void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
167 {
168 struct tip_addr tmp;
169 struct tip_addr *addr;
170
171 tmp.addr = *tip;
172
173 addr = hash_lookup(bgp->tip_hash, &tmp);
174 /* may have been deleted earlier by bgp_interface_down() */
175 if (addr == NULL)
176 return;
177
178 addr->refcnt--;
179
180 if (addr->refcnt == 0) {
181 hash_release(bgp->tip_hash, addr);
182 XFREE(MTYPE_TIP_ADDR, addr);
183 }
184 }
185
186 /* BGP own address structure */
187 struct bgp_addr {
188 struct in_addr addr;
189 struct list *ifp_name_list;
190 };
191
192 static void show_address_entry(struct hash_bucket *bucket, void *args)
193 {
194 struct vty *vty = (struct vty *)args;
195 struct bgp_addr *addr = (struct bgp_addr *)bucket->data;
196 char *name;
197 struct listnode *node;
198
199 vty_out(vty, "addr: %s, count: %d : ", inet_ntoa(addr->addr),
200 addr->ifp_name_list->count);
201
202 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
203 vty_out(vty, " %s,", name);
204 }
205
206 vty_out(vty, "\n");
207 }
208
209 void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
210 {
211 hash_iterate(bgp->address_hash,
212 (void (*)(struct hash_bucket *, void *))show_address_entry,
213 vty);
214 }
215
216 static void bgp_address_hash_string_del(void *val)
217 {
218 char *data = val;
219
220 XFREE(MTYPE_MARTIAN_STRING, data);
221 }
222
223 static void *bgp_address_hash_alloc(void *p)
224 {
225 const struct in_addr *val = (const struct in_addr *)p;
226 struct bgp_addr *addr;
227
228 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
229 addr->addr.s_addr = val->s_addr;
230
231 addr->ifp_name_list = list_new();
232 addr->ifp_name_list->del = bgp_address_hash_string_del;
233
234 return addr;
235 }
236
237 static void bgp_address_hash_free(void *data)
238 {
239 struct bgp_addr *addr = data;
240
241 list_delete(&addr->ifp_name_list);
242 XFREE(MTYPE_BGP_ADDR, addr);
243 }
244
245 static unsigned int bgp_address_hash_key_make(void *p)
246 {
247 const struct bgp_addr *addr = p;
248
249 return jhash_1word(addr->addr.s_addr, 0);
250 }
251
252 static bool bgp_address_hash_cmp(const void *p1, const void *p2)
253 {
254 const struct bgp_addr *addr1 = p1;
255 const struct bgp_addr *addr2 = p2;
256
257 return addr1->addr.s_addr == addr2->addr.s_addr;
258 }
259
260 void bgp_address_init(struct bgp *bgp)
261 {
262 bgp->address_hash =
263 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
264 "BGP Address Hash");
265 }
266
267 void bgp_address_destroy(struct bgp *bgp)
268 {
269 if (bgp->address_hash == NULL)
270 return;
271 hash_clean(bgp->address_hash, bgp_address_hash_free);
272 hash_free(bgp->address_hash);
273 bgp->address_hash = NULL;
274 }
275
276 static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
277 struct prefix *p)
278 {
279 struct bgp_addr tmp;
280 struct bgp_addr *addr;
281 struct listnode *node;
282 char *name;
283
284 tmp.addr = p->u.prefix4;
285
286 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
287
288 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
289 if (strcmp(ifc->ifp->name, name) == 0)
290 break;
291 }
292 if (!node) {
293 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
294 listnode_add(addr->ifp_name_list, name);
295 }
296 }
297
298 static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
299 struct prefix *p)
300 {
301 struct bgp_addr tmp;
302 struct bgp_addr *addr;
303 struct listnode *node;
304 char *name;
305
306 tmp.addr = p->u.prefix4;
307
308 addr = hash_lookup(bgp->address_hash, &tmp);
309 /* may have been deleted earlier by bgp_interface_down() */
310 if (addr == NULL)
311 return;
312
313 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
314 if (strcmp(ifc->ifp->name, name) == 0)
315 break;
316 }
317
318 if (node) {
319 list_delete_node(addr->ifp_name_list, node);
320 XFREE(MTYPE_MARTIAN_STRING, name);
321 }
322
323 if (addr->ifp_name_list->count == 0) {
324 hash_release(bgp->address_hash, addr);
325 list_delete(&addr->ifp_name_list);
326 XFREE(MTYPE_BGP_ADDR, addr);
327 }
328 }
329
330
331 struct bgp_connected_ref {
332 unsigned int refcnt;
333 };
334
335 void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
336 {
337 struct prefix p;
338 struct prefix *addr;
339 struct bgp_node *rn;
340 struct bgp_connected_ref *bc;
341 struct listnode *node, *nnode;
342 struct peer *peer;
343
344 addr = ifc->address;
345
346 p = *(CONNECTED_PREFIX(ifc));
347 if (addr->family == AF_INET) {
348 apply_mask_ipv4((struct prefix_ipv4 *)&p);
349
350 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
351 return;
352
353 bgp_address_add(bgp, ifc, addr);
354
355 rn = bgp_node_get(bgp->connected_table[AFI_IP],
356 (struct prefix *)&p);
357 bc = bgp_node_get_bgp_connected_ref_info(rn);
358 if (bc)
359 bc->refcnt++;
360 else {
361 bc = XCALLOC(MTYPE_BGP_CONN,
362 sizeof(struct bgp_connected_ref));
363 bc->refcnt = 1;
364 bgp_node_set_bgp_connected_ref_info(rn, bc);
365 }
366
367 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
368 if (peer->conf_if
369 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
370 && peer->status != Established
371 && !CHECK_FLAG(peer->flags,
372 PEER_FLAG_IFPEER_V6ONLY)) {
373 if (peer_active(peer))
374 BGP_EVENT_ADD(peer, BGP_Stop);
375 BGP_EVENT_ADD(peer, BGP_Start);
376 }
377 }
378 } else if (addr->family == AF_INET6) {
379 apply_mask_ipv6((struct prefix_ipv6 *)&p);
380
381 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
382 return;
383
384 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
385 return;
386
387 bgp_ipv6_address_add(bgp, ifc, addr);
388
389 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
390 (struct prefix *)&p);
391
392 bc = bgp_node_get_bgp_connected_ref_info(rn);
393 if (bc)
394 bc->refcnt++;
395 else {
396 bc = XCALLOC(MTYPE_BGP_CONN,
397 sizeof(struct bgp_connected_ref));
398 bc->refcnt = 1;
399 bgp_node_set_bgp_connected_ref_info(rn, bc);
400 }
401 }
402 }
403
404 void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
405 {
406 struct prefix p;
407 struct prefix *addr;
408 struct bgp_node *rn = NULL;
409 struct bgp_connected_ref *bc;
410
411 addr = ifc->address;
412
413 p = *(CONNECTED_PREFIX(ifc));
414 apply_mask(&p);
415 if (addr->family == AF_INET) {
416 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
417 return;
418
419 bgp_address_del(bgp, ifc, addr);
420
421 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
422 } else if (addr->family == AF_INET6) {
423 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
424 return;
425
426 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
427 return;
428
429 bgp_ipv6_address_del(bgp, ifc, addr);
430
431 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
432 (struct prefix *)&p);
433 }
434
435 if (!rn)
436 return;
437
438 bc = bgp_node_get_bgp_connected_ref_info(rn);
439 bc->refcnt--;
440 if (bc->refcnt == 0) {
441 XFREE(MTYPE_BGP_CONN, bc);
442 bgp_node_set_bgp_connected_ref_info(rn, NULL);
443 }
444 bgp_unlock_node(rn);
445 bgp_unlock_node(rn);
446 }
447
448 static void bgp_connected_cleanup(struct route_table *table,
449 struct route_node *rn)
450 {
451 struct bgp_connected_ref *bc;
452 struct bgp_node *bn = bgp_node_from_rnode(rn);
453
454 bc = bgp_node_get_bgp_connected_ref_info(bn);
455 if (!bc)
456 return;
457
458 bc->refcnt--;
459 if (bc->refcnt == 0) {
460 XFREE(MTYPE_BGP_CONN, bc);
461 bgp_node_set_bgp_connected_ref_info(bn, NULL);
462 }
463 }
464
465 int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
466 {
467 struct bgp_addr tmp, *addr;
468 struct tip_addr tmp_tip, *tip;
469
470 tmp.addr = nh_addr;
471
472 addr = hash_lookup(bgp->address_hash, &tmp);
473 if (addr)
474 return 1;
475
476 tmp_tip.addr = nh_addr;
477 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
478 if (tip)
479 return 1;
480
481 return 0;
482 }
483
484 int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
485 {
486 struct bgp_node *rn1;
487 struct bgp_node *rn2;
488 struct prefix p;
489 int ret;
490
491 p.family = AF_INET;
492 p.prefixlen = IPV4_MAX_BITLEN;
493 p.u.prefix4 = nexthop;
494
495 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
496 if (!rn1)
497 return 0;
498
499 p.family = AF_INET;
500 p.prefixlen = IPV4_MAX_BITLEN;
501 p.u.prefix4 = peer->su.sin.sin_addr;
502
503 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
504 if (!rn2) {
505 bgp_unlock_node(rn1);
506 return 0;
507 }
508
509 ret = (rn1 == rn2) ? 1 : 0;
510
511 bgp_unlock_node(rn1);
512 bgp_unlock_node(rn2);
513
514 return (ret);
515 }
516
517 int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
518 struct update_subgroup *subgrp)
519 {
520 struct bgp_node *rn1, *rn2;
521 struct peer_af *paf;
522 struct prefix p, np;
523 struct bgp *bgp;
524
525 np.family = AF_INET;
526 np.prefixlen = IPV4_MAX_BITLEN;
527 np.u.prefix4 = nexthop;
528
529 p.family = AF_INET;
530 p.prefixlen = IPV4_MAX_BITLEN;
531
532 bgp = SUBGRP_INST(subgrp);
533 rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
534 if (!rn1)
535 return 0;
536
537 SUBGRP_FOREACH_PEER (subgrp, paf) {
538 p.u.prefix4 = paf->peer->su.sin.sin_addr;
539
540 rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
541 if (rn1 == rn2) {
542 bgp_unlock_node(rn1);
543 bgp_unlock_node(rn2);
544 return 1;
545 }
546
547 if (rn2)
548 bgp_unlock_node(rn2);
549 }
550
551 bgp_unlock_node(rn1);
552 return 0;
553 }
554
555 static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
556 struct bgp_nexthop_cache *bnc)
557 {
558 char buf[PREFIX2STR_BUFFER];
559 struct nexthop *nexthop;
560
561 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
562 switch (nexthop->type) {
563 case NEXTHOP_TYPE_IPV6:
564 vty_out(vty, " gate %s\n",
565 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
566 sizeof(buf)));
567 break;
568 case NEXTHOP_TYPE_IPV6_IFINDEX:
569 vty_out(vty, " gate %s, if %s\n",
570 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
571 sizeof(buf)),
572 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
573 break;
574 case NEXTHOP_TYPE_IPV4:
575 vty_out(vty, " gate %s\n",
576 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
577 sizeof(buf)));
578 break;
579 case NEXTHOP_TYPE_IFINDEX:
580 vty_out(vty, " if %s\n",
581 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
582 break;
583 case NEXTHOP_TYPE_IPV4_IFINDEX:
584 vty_out(vty, " gate %s, if %s\n",
585 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
586 sizeof(buf)),
587 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
588 break;
589 case NEXTHOP_TYPE_BLACKHOLE:
590 vty_out(vty, " blackhole\n");
591 break;
592 default:
593 vty_out(vty, " invalid nexthop type %u\n",
594 nexthop->type);
595 }
596 }
597
598 static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
599 bool import_table)
600 {
601 struct bgp_node *rn;
602 struct bgp_nexthop_cache *bnc;
603 char buf[PREFIX2STR_BUFFER];
604 time_t tbuf;
605 afi_t afi;
606 struct bgp_table **table;
607
608 if (import_table)
609 vty_out(vty, "Current BGP import check cache:\n");
610 else
611 vty_out(vty, "Current BGP nexthop cache:\n");
612 if (import_table)
613 table = bgp->import_check_table;
614 else
615 table = bgp->nexthop_cache_table;
616 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
617 if (!table || !table[afi])
618 continue;
619 for (rn = bgp_table_top(table[afi]); rn;
620 rn = bgp_route_next(rn)) {
621 bnc = bgp_node_get_bgp_nexthop_info(rn);
622 if (!bnc)
623 continue;
624
625 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
626 vty_out(vty,
627 " %s valid [IGP metric %d], #paths %d\n",
628 inet_ntop(rn->p.family,
629 &rn->p.u.prefix, buf,
630 sizeof(buf)),
631 bnc->metric, bnc->path_count);
632
633 if (!detail)
634 continue;
635
636 bgp_show_nexthops_detail(vty, bgp, bnc);
637
638 } else {
639 vty_out(vty, " %s invalid\n",
640 inet_ntop(rn->p.family,
641 &rn->p.u.prefix, buf,
642 sizeof(buf)));
643 if (CHECK_FLAG(bnc->flags,
644 BGP_NEXTHOP_CONNECTED))
645 vty_out(vty, " Must be Connected\n");
646 if (!CHECK_FLAG(bnc->flags,
647 BGP_NEXTHOP_REGISTERED))
648 vty_out(vty, " Is not Registered\n");
649 }
650 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
651 vty_out(vty, " Last update: %s", ctime(&tbuf));
652 vty_out(vty, "\n");
653 }
654 }
655 }
656
657 static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
658 int detail, bool import_table)
659 {
660 struct bgp *bgp;
661
662 if (name)
663 bgp = bgp_lookup_by_name(name);
664 else
665 bgp = bgp_get_default();
666 if (!bgp) {
667 vty_out(vty, "%% No such BGP instance exist\n");
668 return CMD_WARNING;
669 }
670
671 bgp_show_nexthops(vty, bgp, detail, import_table);
672
673 return CMD_SUCCESS;
674 }
675
676 static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
677 {
678 struct listnode *node, *nnode;
679 struct bgp *bgp;
680
681 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
682 vty_out(vty, "\nInstance %s:\n",
683 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
684 ? VRF_DEFAULT_NAME
685 : bgp->name);
686 bgp_show_nexthops(vty, bgp, 0, false);
687 }
688 }
689
690 DEFUN (show_ip_bgp_nexthop,
691 show_ip_bgp_nexthop_cmd,
692 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
693 SHOW_STR
694 IP_STR
695 BGP_STR
696 BGP_INSTANCE_HELP_STR
697 "BGP nexthop table\n"
698 "Show detailed information\n")
699 {
700 int idx = 0;
701 char *vrf = NULL;
702
703 if (argv_find(argv, argc, "view", &idx)
704 || argv_find(argv, argc, "vrf", &idx))
705 vrf = argv[++idx]->arg;
706 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
707
708 return show_ip_bgp_nexthop_table(vty, vrf, detail, false);
709 }
710
711 DEFUN (show_ip_bgp_import_check,
712 show_ip_bgp_import_check_cmd,
713 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
714 SHOW_STR
715 IP_STR
716 BGP_STR
717 BGP_INSTANCE_HELP_STR
718 "BGP import check table\n"
719 "Show detailed information\n")
720 {
721 int idx = 0;
722 char *vrf = NULL;
723
724 if (argv_find(argv, argc, "view", &idx)
725 || argv_find(argv, argc, "vrf", &idx))
726 vrf = argv[++idx]->arg;
727 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
728 return show_ip_bgp_nexthop_table(vty, vrf, detail, true);
729 }
730
731 DEFUN (show_ip_bgp_instance_all_nexthop,
732 show_ip_bgp_instance_all_nexthop_cmd,
733 "show [ip] bgp <view|vrf> all nexthop",
734 SHOW_STR
735 IP_STR
736 BGP_STR
737 BGP_INSTANCE_ALL_HELP_STR
738 "BGP nexthop table\n")
739 {
740 bgp_show_all_instances_nexthops_vty(vty);
741 return CMD_SUCCESS;
742 }
743
744 void bgp_scan_init(struct bgp *bgp)
745 {
746 afi_t afi;
747
748 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
749 bgp->nexthop_cache_table[afi] =
750 bgp_table_init(bgp, afi, SAFI_UNICAST);
751 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
752 SAFI_UNICAST);
753 bgp->import_check_table[afi] =
754 bgp_table_init(bgp, afi, SAFI_UNICAST);
755 }
756 }
757
758 void bgp_scan_vty_init(void)
759 {
760 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
761 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
762 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
763 }
764
765 void bgp_scan_finish(struct bgp *bgp)
766 {
767 afi_t afi;
768
769 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
770 /* Only the current one needs to be reset. */
771 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
772 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
773 bgp->nexthop_cache_table[afi] = NULL;
774
775 bgp->connected_table[afi]->route_table->cleanup =
776 bgp_connected_cleanup;
777 bgp_table_unlock(bgp->connected_table[afi]);
778 bgp->connected_table[afi] = NULL;
779
780 bgp_table_unlock(bgp->import_check_table[afi]);
781 bgp->import_check_table[afi] = NULL;
782 }
783 }
784
785 static void *bgp_ipv6_address_hash_alloc(void *p)
786 {
787 const struct in6_addr *v6addr = (const struct in6_addr *)p;
788 struct bgp_addrv6 *addr;
789
790 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addrv6));
791 addr->addrv6 = *v6addr;
792
793 addr->ifp_name_list = list_new();
794 addr->ifp_name_list->del = bgp_address_hash_string_del;
795
796 return addr;
797 }
798
799 static void bgp_ipv6_address_hash_free(void *data)
800 {
801 struct bgp_addrv6 *v6addr = data;
802
803 list_delete(&v6addr->ifp_name_list);
804 XFREE(MTYPE_BGP_ADDR, v6addr);
805 }
806
807 static unsigned int bgp_ipv6_address_hash_key_make(void *p)
808 {
809 const struct bgp_addrv6 *v6 = p;
810
811 return __ipv6_addr_jhash(&v6->addrv6, 0);
812 }
813
814 static bool bgp_ipv6_address_hash_cmp(const void *p1,
815 const void *p2)
816 {
817 const struct bgp_addrv6 *addr1 = p1;
818 const struct bgp_addrv6 *addr2 = p2;
819
820 return(!memcmp(&addr1->addrv6, &addr2->addrv6,
821 sizeof(struct in6_addr)));
822 }
823
824 void bgp_ipv6_address_init(struct bgp *bgp)
825 {
826 bgp->ipv6_address_hash = hash_create(bgp_ipv6_address_hash_key_make,
827 bgp_ipv6_address_hash_cmp,
828 "BGP IPV6 Address Hash");
829 }
830
831 void bgp_ipv6_address_destroy(struct bgp *bgp)
832 {
833 if (bgp->ipv6_address_hash == NULL)
834 return;
835 hash_clean(bgp->ipv6_address_hash,
836 bgp_ipv6_address_hash_free);
837
838 hash_free(bgp->ipv6_address_hash);
839 bgp->ipv6_address_hash = NULL;
840 }
841
842 static void bgp_ipv6_address_add(struct bgp *bgp, struct connected *ifc,
843 struct prefix *p)
844 {
845 struct bgp_addrv6 tmp = {0};
846 struct bgp_addrv6 *addr = NULL;
847 struct listnode *node = NULL;
848 char *name = 0;
849
850 tmp.addrv6 = p->u.prefix6;
851
852 addr = hash_get(bgp->ipv6_address_hash, &tmp,
853 bgp_ipv6_address_hash_alloc);
854 if (!addr)
855 return;
856
857 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
858 if (strcmp(ifc->ifp->name, name) == 0)
859 break;
860 }
861
862 if (!node) {
863 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
864 listnode_add(addr->ifp_name_list, name);
865 }
866 }
867
868
869 static void bgp_ipv6_address_del(struct bgp *bgp, struct connected *ifc,
870 struct prefix *p)
871 {
872 struct bgp_addrv6 tmp;
873 struct bgp_addrv6 *addr;
874 struct listnode *node;
875 char *name;
876
877
878 tmp.addrv6 = p->u.prefix6;
879
880 addr = hash_lookup(bgp->ipv6_address_hash, &tmp);
881 /* may have been deleted earlier by bgp_interface_down() */
882 if (addr == NULL)
883 return;
884
885 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
886 if (strcmp(ifc->ifp->name, name) == 0)
887 break;
888 }
889
890 if (node) {
891 list_delete_node(addr->ifp_name_list, node);
892 XFREE(MTYPE_MARTIAN_STRING, name);
893 }
894
895 if (addr->ifp_name_list->count == 0) {
896 hash_release(bgp->ipv6_address_hash, addr);
897 list_delete(&addr->ifp_name_list);
898 XFREE(MTYPE_BGP_ADDR, addr);
899 }
900 }
901 int bgp_nexthop_self_ipv6(struct bgp *bgp, struct in6_addr *addr)
902 {
903 struct bgp_addrv6 tmp;
904
905 tmp.addrv6 = *addr;
906 return (!!hash_lookup(bgp->ipv6_address_hash, &tmp));
907 }