]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_zebra.c
'neighbor <if-name> interface' config support in BGP including RA/Zebra changes.
[mirror_frr.git] / bgpd / bgp_zebra.c
1 /* zebra client
2 Copyright (C) 1997, 98, 99 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
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "stream.h"
25 #include "network.h"
26 #include "prefix.h"
27 #include "log.h"
28 #include "sockunion.h"
29 #include "zclient.h"
30 #include "routemap.h"
31 #include "thread.h"
32
33 #include "bgpd/bgpd.h"
34 #include "bgpd/bgp_route.h"
35 #include "bgpd/bgp_attr.h"
36 #include "bgpd/bgp_nexthop.h"
37 #include "bgpd/bgp_zebra.h"
38 #include "bgpd/bgp_fsm.h"
39 #include "bgpd/bgp_debug.h"
40 #include "bgpd/bgp_mpath.h"
41 #include "bgpd/bgp_nexthop.h"
42
43 /* All information about zebra. */
44 struct zclient *zclient = NULL;
45 struct in_addr router_id_zebra;
46
47 /* Growable buffer for nexthops sent to zebra */
48 struct stream *bgp_nexthop_buf = NULL;
49 struct stream *bgp_ifindices_buf = NULL;
50
51 /* These array buffers are used in making a copy of the attributes for
52 route-map apply. Arrays are being used here to minimize mallocs and
53 frees for the temporary copy of the attributes.
54 Given the zapi api expects the nexthop buffer to contain pointer to
55 pointers for nexthops, we couldnt have used a single nexthop variable
56 on the stack, hence we had two options:
57 1. maintain a linked-list and free it after zapi_*_route call
58 2. use an array to avoid number of mallocs.
59 Number of supported next-hops are finite, use of arrays should be ok. */
60 struct attr attr_cp[BGP_MAXIMUM_MAXPATHS];
61 struct attr_extra attr_extra_cp[BGP_MAXIMUM_MAXPATHS];
62 int attr_index = 0;
63
64 /* Once per address-family initialization of the attribute array */
65 #define BGP_INFO_ATTR_BUF_INIT()\
66 do {\
67 memset(attr_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr));\
68 memset(attr_extra_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr_extra));\
69 attr_index = 0;\
70 } while (0)
71
72 #define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\
73 do { \
74 *info_dst = *info_src; \
75 assert(attr_index != BGP_MAXIMUM_MAXPATHS);\
76 attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \
77 bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \
78 bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \
79 info_dst->attr = &attr_cp[attr_index]; \
80 attr_index++;\
81 } while (0)
82
83 #define BGP_INFO_ATTR_BUF_FREE(info) \
84 do { \
85 bgp_attr_deep_free(info->attr); \
86 } while (0)
87
88 /* Router-id update message from zebra. */
89 static int
90 bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
91 {
92 struct prefix router_id;
93 struct listnode *node, *nnode;
94 struct bgp *bgp;
95
96 zebra_router_id_update_read(zclient->ibuf,&router_id);
97
98 if (BGP_DEBUG(zebra, ZEBRA))
99 {
100 char buf[128];
101 prefix2str(&router_id, buf, sizeof(buf));
102 zlog_debug("Zebra rcvd: router id update %s", buf);
103 }
104
105 router_id_zebra = router_id.u.prefix4;
106
107 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
108 {
109 if (!bgp->router_id_static.s_addr)
110 bgp_router_id_set (bgp, &router_id.u.prefix4);
111 }
112
113 return 0;
114 }
115
116 /* Nexthop update message from zebra. */
117 static int
118 bgp_read_nexthop_update (int command, struct zclient *zclient,
119 zebra_size_t length)
120 {
121 bgp_parse_nexthop_update();
122 return 0;
123 }
124
125 static void
126 bgp_nbr_connected_add (struct nbr_connected *ifc)
127 {
128 struct listnode *node, *nnode, *mnode;
129 struct bgp *bgp;
130 struct peer *peer;
131
132 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
133 {
134 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
135 {
136 if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
137 {
138 if (peer_active(peer))
139 BGP_EVENT_ADD (peer, BGP_Stop);
140 BGP_EVENT_ADD (peer, BGP_Start);
141 }
142 }
143 }
144 }
145
146 static void
147 bgp_nbr_connected_delete (struct nbr_connected *ifc)
148 {
149 struct listnode *node, *nnode, *mnode;
150 struct bgp *bgp;
151 struct peer *peer;
152
153 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
154 {
155 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
156 {
157 if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
158 {
159 BGP_EVENT_ADD (peer, BGP_Stop);
160 }
161 }
162 }
163 }
164
165 /* Inteface addition message from zebra. */
166 static int
167 bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
168 {
169 struct interface *ifp;
170
171 ifp = zebra_interface_add_read (zclient->ibuf);
172
173 if (BGP_DEBUG(zebra, ZEBRA) && ifp)
174 zlog_debug("Zebra rcvd: interface add %s", ifp->name);
175
176 return 0;
177 }
178
179 static int
180 bgp_interface_delete (int command, struct zclient *zclient,
181 zebra_size_t length)
182 {
183 struct stream *s;
184 struct interface *ifp;
185
186 s = zclient->ibuf;
187 ifp = zebra_interface_state_read (s);
188 ifp->ifindex = IFINDEX_INTERNAL;
189
190 if (BGP_DEBUG(zebra, ZEBRA))
191 zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
192
193 return 0;
194 }
195
196 static int
197 bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
198 {
199 struct stream *s;
200 struct interface *ifp;
201 struct connected *c;
202 struct nbr_connected *nc;
203 struct listnode *node, *nnode;
204
205 s = zclient->ibuf;
206 ifp = zebra_interface_state_read (s);
207
208 if (! ifp)
209 return 0;
210
211 if (BGP_DEBUG(zebra, ZEBRA))
212 zlog_debug("Zebra rcvd: interface %s up", ifp->name);
213
214 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
215 bgp_connected_add (c);
216
217 for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc))
218 bgp_nbr_connected_add (nc);
219
220 return 0;
221 }
222
223 static int
224 bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
225 {
226 struct stream *s;
227 struct interface *ifp;
228 struct connected *c;
229 struct nbr_connected *nc;
230 struct listnode *node, *nnode;
231
232 s = zclient->ibuf;
233 ifp = zebra_interface_state_read (s);
234 if (! ifp)
235 return 0;
236
237 if (BGP_DEBUG(zebra, ZEBRA))
238 zlog_debug("Zebra rcvd: interface %s down", ifp->name);
239
240 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
241 bgp_connected_delete (c);
242
243 for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc))
244 bgp_nbr_connected_delete (nc);
245
246 /* Fast external-failover */
247 {
248 struct listnode *mnode;
249 struct bgp *bgp;
250 struct peer *peer;
251
252 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
253 {
254 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
255 continue;
256
257 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
258 {
259 if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
260 continue;
261
262 if (ifp == peer->nexthop.ifp)
263 BGP_EVENT_ADD (peer, BGP_Stop);
264 }
265 }
266 }
267
268 return 0;
269 }
270
271 static int
272 bgp_interface_address_add (int command, struct zclient *zclient,
273 zebra_size_t length)
274 {
275 struct connected *ifc;
276
277 ifc = zebra_interface_address_read (command, zclient->ibuf);
278
279 if (ifc == NULL)
280 return 0;
281
282 if (BGP_DEBUG(zebra, ZEBRA))
283 {
284 char buf[128];
285 prefix2str(ifc->address, buf, sizeof(buf));
286 zlog_debug("Zebra rcvd: interface %s address add %s",
287 ifc->ifp->name, buf);
288 }
289
290 if (if_is_operative (ifc->ifp))
291 bgp_connected_add (ifc);
292
293 return 0;
294 }
295
296 static int
297 bgp_interface_address_delete (int command, struct zclient *zclient,
298 zebra_size_t length)
299 {
300 struct connected *ifc;
301
302 ifc = zebra_interface_address_read (command, zclient->ibuf);
303
304 if (ifc == NULL)
305 return 0;
306
307 if (BGP_DEBUG(zebra, ZEBRA))
308 {
309 char buf[128];
310 prefix2str(ifc->address, buf, sizeof(buf));
311 zlog_debug("Zebra rcvd: interface %s address delete %s",
312 ifc->ifp->name, buf);
313 }
314
315 if (if_is_operative (ifc->ifp))
316 bgp_connected_delete (ifc);
317
318 connected_free (ifc);
319
320 return 0;
321 }
322
323 static int
324 bgp_interface_nbr_address_add (int command, struct zclient *zclient,
325 zebra_size_t length)
326 {
327 struct nbr_connected *ifc = NULL;
328
329 ifc = zebra_interface_nbr_address_read (command, zclient->ibuf);
330
331 if (ifc == NULL)
332 return 0;
333
334 if (BGP_DEBUG(zebra, ZEBRA))
335 {
336 char buf[128];
337 prefix2str(ifc->address, buf, sizeof(buf));
338 zlog_debug("Zebra rcvd: interface %s nbr address add %s",
339 ifc->ifp->name, buf);
340 }
341
342 if (if_is_operative (ifc->ifp))
343 bgp_nbr_connected_add (ifc);
344
345 return 0;
346 }
347
348 static int
349 bgp_interface_nbr_address_delete (int command, struct zclient *zclient,
350 zebra_size_t length)
351 {
352 struct nbr_connected *ifc = NULL;
353
354 ifc = zebra_interface_nbr_address_read (command, zclient->ibuf);
355
356 if (ifc == NULL)
357 return 0;
358
359 if (BGP_DEBUG(zebra, ZEBRA))
360 {
361 char buf[128];
362 prefix2str(ifc->address, buf, sizeof(buf));
363 zlog_debug("Zebra rcvd: interface %s nbr address delete %s",
364 ifc->ifp->name, buf);
365 }
366
367 if (if_is_operative (ifc->ifp))
368 bgp_nbr_connected_delete (ifc);
369
370 nbr_connected_free (ifc);
371
372 return 0;
373 }
374
375 /* Zebra route add and delete treatment. */
376 static int
377 zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
378 {
379 struct stream *s;
380 struct zapi_ipv4 api;
381 struct in_addr nexthop;
382 struct prefix_ipv4 p;
383
384 s = zclient->ibuf;
385 nexthop.s_addr = 0;
386
387 /* Type, flags, message. */
388 api.type = stream_getc (s);
389 api.flags = stream_getc (s);
390 api.message = stream_getc (s);
391
392 /* IPv4 prefix. */
393 memset (&p, 0, sizeof (struct prefix_ipv4));
394 p.family = AF_INET;
395 p.prefixlen = stream_getc (s);
396 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
397
398 /* Nexthop, ifindex, distance, metric. */
399 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
400 {
401 api.nexthop_num = stream_getc (s);
402 nexthop.s_addr = stream_get_ipv4 (s);
403 }
404 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
405 {
406 api.ifindex_num = stream_getc (s);
407 stream_getl (s); /* ifindex, unused */
408 }
409 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
410 api.distance = stream_getc (s);
411 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
412 api.metric = stream_getl (s);
413 else
414 api.metric = 0;
415
416 if (command == ZEBRA_IPV4_ROUTE_ADD)
417 {
418 if (BGP_DEBUG(zebra, ZEBRA))
419 {
420 char buf[2][INET_ADDRSTRLEN];
421 zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
422 zebra_route_string(api.type),
423 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
424 p.prefixlen,
425 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
426 api.metric);
427 }
428 bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
429 api.metric, api.type);
430 }
431 else
432 {
433 if (BGP_DEBUG(zebra, ZEBRA))
434 {
435 char buf[2][INET_ADDRSTRLEN];
436 zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
437 "nexthop %s metric %u",
438 zebra_route_string(api.type),
439 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
440 p.prefixlen,
441 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
442 api.metric);
443 }
444 bgp_redistribute_delete((struct prefix *)&p, api.type);
445 }
446
447 return 0;
448 }
449
450 #ifdef HAVE_IPV6
451 /* Zebra route add and delete treatment. */
452 static int
453 zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
454 {
455 struct stream *s;
456 struct zapi_ipv6 api;
457 struct in6_addr nexthop;
458 struct prefix_ipv6 p;
459
460 s = zclient->ibuf;
461 memset (&nexthop, 0, sizeof (struct in6_addr));
462
463 /* Type, flags, message. */
464 api.type = stream_getc (s);
465 api.flags = stream_getc (s);
466 api.message = stream_getc (s);
467
468 /* IPv6 prefix. */
469 memset (&p, 0, sizeof (struct prefix_ipv6));
470 p.family = AF_INET6;
471 p.prefixlen = stream_getc (s);
472 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
473
474 /* Nexthop, ifindex, distance, metric. */
475 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
476 {
477 api.nexthop_num = stream_getc (s);
478 stream_get (&nexthop, s, 16);
479 }
480 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
481 {
482 api.ifindex_num = stream_getc (s);
483 stream_getl (s); /* ifindex, unused */
484 }
485 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
486 api.distance = stream_getc (s);
487 else
488 api.distance = 0;
489 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
490 api.metric = stream_getl (s);
491 else
492 api.metric = 0;
493
494 /* Simply ignore link-local address. */
495 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
496 return 0;
497
498 if (command == ZEBRA_IPV6_ROUTE_ADD)
499 {
500 if (BGP_DEBUG(zebra, ZEBRA))
501 {
502 char buf[2][INET6_ADDRSTRLEN];
503 zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
504 zebra_route_string(api.type),
505 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
506 p.prefixlen,
507 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
508 api.metric);
509 }
510 bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
511 api.metric, api.type);
512 }
513 else
514 {
515 if (BGP_DEBUG(zebra, ZEBRA))
516 {
517 char buf[2][INET6_ADDRSTRLEN];
518 zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
519 "nexthop %s metric %u",
520 zebra_route_string(api.type),
521 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
522 p.prefixlen,
523 inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
524 api.metric);
525 }
526 bgp_redistribute_delete ((struct prefix *) &p, api.type);
527 }
528
529 return 0;
530 }
531 #endif /* HAVE_IPV6 */
532
533 struct interface *
534 if_lookup_by_ipv4 (struct in_addr *addr)
535 {
536 struct listnode *ifnode;
537 struct listnode *cnode;
538 struct interface *ifp;
539 struct connected *connected;
540 struct prefix_ipv4 p;
541 struct prefix *cp;
542
543 p.family = AF_INET;
544 p.prefix = *addr;
545 p.prefixlen = IPV4_MAX_BITLEN;
546
547 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
548 {
549 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
550 {
551 cp = connected->address;
552
553 if (cp->family == AF_INET)
554 if (prefix_match (cp, (struct prefix *)&p))
555 return ifp;
556 }
557 }
558 return NULL;
559 }
560
561 struct interface *
562 if_lookup_by_ipv4_exact (struct in_addr *addr)
563 {
564 struct listnode *ifnode;
565 struct listnode *cnode;
566 struct interface *ifp;
567 struct connected *connected;
568 struct prefix *cp;
569
570 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
571 {
572 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
573 {
574 cp = connected->address;
575
576 if (cp->family == AF_INET)
577 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
578 return ifp;
579 }
580 }
581 return NULL;
582 }
583
584 #ifdef HAVE_IPV6
585 struct interface *
586 if_lookup_by_ipv6 (struct in6_addr *addr)
587 {
588 struct listnode *ifnode;
589 struct listnode *cnode;
590 struct interface *ifp;
591 struct connected *connected;
592 struct prefix_ipv6 p;
593 struct prefix *cp;
594
595 p.family = AF_INET6;
596 p.prefix = *addr;
597 p.prefixlen = IPV6_MAX_BITLEN;
598
599 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
600 {
601 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
602 {
603 cp = connected->address;
604
605 if (cp->family == AF_INET6)
606 if (prefix_match (cp, (struct prefix *)&p))
607 return ifp;
608 }
609 }
610 return NULL;
611 }
612
613 struct interface *
614 if_lookup_by_ipv6_exact (struct in6_addr *addr)
615 {
616 struct listnode *ifnode;
617 struct listnode *cnode;
618 struct interface *ifp;
619 struct connected *connected;
620 struct prefix *cp;
621
622 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
623 {
624 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
625 {
626 cp = connected->address;
627
628 if (cp->family == AF_INET6)
629 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
630 return ifp;
631 }
632 }
633 return NULL;
634 }
635
636 static int
637 if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
638 {
639 struct listnode *cnode;
640 struct connected *connected;
641 struct prefix *cp;
642
643 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
644 {
645 cp = connected->address;
646
647 if (cp->family == AF_INET6)
648 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
649 {
650 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
651 return 1;
652 }
653 }
654 return 0;
655 }
656
657 static int
658 if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
659 {
660 struct listnode *cnode;
661 struct connected *connected;
662 struct prefix *cp;
663
664 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
665 {
666 cp = connected->address;
667
668 if (cp->family == AF_INET6)
669 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
670 {
671 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
672 return 1;
673 }
674 }
675 return 0;
676 }
677 #endif /* HAVE_IPV6 */
678
679 static int
680 if_get_ipv4_address (struct interface *ifp, struct in_addr *addr)
681 {
682 struct listnode *cnode;
683 struct connected *connected;
684 struct prefix *cp;
685
686 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
687 {
688 cp = connected->address;
689 if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4)))
690 {
691 *addr = cp->u.prefix4;
692 return 1;
693 }
694 }
695 return 0;
696 }
697
698 int
699 bgp_nexthop_set (union sockunion *local, union sockunion *remote,
700 struct bgp_nexthop *nexthop, struct peer *peer)
701 {
702 int ret = 0;
703 struct interface *ifp = NULL;
704
705 memset (nexthop, 0, sizeof (struct bgp_nexthop));
706
707 if (!local)
708 return -1;
709 if (!remote)
710 return -1;
711
712 if (local->sa.sa_family == AF_INET)
713 {
714 nexthop->v4 = local->sin.sin_addr;
715 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
716 }
717 #ifdef HAVE_IPV6
718 if (local->sa.sa_family == AF_INET6)
719 {
720 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
721 {
722 if (peer->conf_if || peer->ifname)
723 ifp = if_lookup_by_index (if_nametoindex (peer->conf_if ? peer->conf_if : peer->ifname));
724 }
725 else
726 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
727 }
728 #endif /* HAVE_IPV6 */
729
730 if (!ifp)
731 return -1;
732
733 nexthop->ifp = ifp;
734
735 /* IPv4 connection. */
736 if (local->sa.sa_family == AF_INET)
737 {
738 #ifdef HAVE_IPV6
739 /* IPv6 nexthop*/
740 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
741
742 /* There is no global nexthop. */
743 if (!ret)
744 if_get_ipv6_local (ifp, &nexthop->v6_global);
745 else
746 if_get_ipv6_local (ifp, &nexthop->v6_local);
747 #endif /* HAVE_IPV6 */
748 }
749
750 #ifdef HAVE_IPV6
751 /* IPv6 connection. */
752 if (local->sa.sa_family == AF_INET6)
753 {
754 struct interface *direct = NULL;
755
756 /* IPv4 nexthop. */
757 ret = if_get_ipv4_address(ifp, &nexthop->v4);
758 if (!ret && peer->local_id.s_addr)
759 nexthop->v4 = peer->local_id;
760
761 /* Global address*/
762 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
763 {
764 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
765 IPV6_MAX_BYTELEN);
766
767 /* If directory connected set link-local address. */
768 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
769 if (direct)
770 if_get_ipv6_local (ifp, &nexthop->v6_local);
771 }
772 else
773 /* Link-local address. */
774 {
775 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
776
777 /* If there is no global address. Set link-local address as
778 global. I know this break RFC specification... */
779 if (!ret)
780 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
781 IPV6_MAX_BYTELEN);
782 else
783 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
784 IPV6_MAX_BYTELEN);
785 }
786 }
787
788 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
789 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
790 peer->shared_network = 1;
791 else
792 peer->shared_network = 0;
793
794 /* KAME stack specific treatment. */
795 #ifdef KAME
796 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
797 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
798 {
799 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
800 }
801 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
802 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
803 {
804 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
805 }
806 #endif /* KAME */
807 #endif /* HAVE_IPV6 */
808 return ret;
809 }
810
811 static struct in6_addr *
812 bgp_info_to_ipv6_nexthop (struct bgp_info *info)
813 {
814 struct in6_addr *nexthop = NULL;
815
816 /* Only global address nexthop exists. */
817 if (info->attr->extra->mp_nexthop_len == 16)
818 nexthop = &info->attr->extra->mp_nexthop_global;
819
820 /* If both global and link-local address present. */
821 if (info->attr->extra->mp_nexthop_len == 32)
822 {
823 /* Workaround for Cisco's nexthop bug. */
824 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
825 && info->peer->su_remote->sa.sa_family == AF_INET6)
826 nexthop = &info->peer->su_remote->sin6.sin6_addr;
827 else
828 nexthop = &info->attr->extra->mp_nexthop_local;
829 }
830
831 return nexthop;
832 }
833
834 static int
835 bgp_table_map_apply (struct route_map *map, struct prefix *p,
836 struct bgp_info *info)
837 {
838 if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH)
839 return 1;
840
841 if (BGP_DEBUG(zebra, ZEBRA))
842 {
843 if (p->family == AF_INET)
844 {
845 char buf[2][INET_ADDRSTRLEN];
846 zlog_debug("Zebra rmap deny: IPv4 route %s/%d nexthop %s",
847 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
848 p->prefixlen,
849 inet_ntop(AF_INET, &info->attr->nexthop, buf[1],
850 sizeof(buf[1])));
851 }
852 if (p->family == AF_INET6)
853 {
854 char buf[2][INET6_ADDRSTRLEN];
855 zlog_debug("Zebra rmap deny: IPv6 route %s/%d nexthop %s",
856 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
857 p->prefixlen,
858 inet_ntop(AF_INET6, bgp_info_to_ipv6_nexthop(info), buf[1],
859 sizeof(buf[1])));
860 }
861 }
862 return 0;
863 }
864
865 void
866 bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
867 afi_t afi, safi_t safi)
868 {
869 int flags;
870 u_char distance;
871 struct peer *peer;
872 struct bgp_info *mpinfo;
873 size_t oldsize, newsize;
874 u_int32_t nhcount, metric;
875 struct bgp_info local_info;
876 struct bgp_info *info_cp = &local_info;
877
878 if (zclient->sock < 0)
879 return;
880
881 if (! zclient->redist[ZEBRA_ROUTE_BGP])
882 return;
883
884 flags = 0;
885 peer = info->peer;
886
887 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
888 {
889 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
890 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
891 }
892
893 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
894 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
895 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
896
897 nhcount = 1 + bgp_info_mpath_count (info);
898
899 if (p->family == AF_INET)
900 {
901 struct zapi_ipv4 api;
902 struct in_addr *nexthop;
903 char buf[2][INET_ADDRSTRLEN];
904 int valid_nh_count = 0;
905
906 /* resize nexthop buffer size if necessary */
907 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
908 (sizeof (struct in_addr *) * nhcount))
909 {
910 newsize = (sizeof (struct in_addr *) * nhcount);
911 newsize = stream_resize (bgp_nexthop_buf, newsize);
912 if (newsize == oldsize)
913 {
914 zlog_err ("can't resize nexthop buffer");
915 return;
916 }
917 }
918 stream_reset (bgp_nexthop_buf);
919 nexthop = NULL;
920
921 /* Metric is currently based on the best-path only. */
922 metric = info->attr->med;
923
924 if (bgp->table_map[afi][safi].name)
925 {
926 BGP_INFO_ATTR_BUF_INIT();
927
928 /* Copy info and attributes, so the route-map apply doesn't modify the
929 BGP route info. */
930 BGP_INFO_ATTR_BUF_COPY(info, info_cp);
931 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
932 {
933 metric = info_cp->attr->med;
934 nexthop = &info_cp->attr->nexthop;
935 }
936 BGP_INFO_ATTR_BUF_FREE(info_cp);
937 }
938 else
939 {
940 nexthop = &info->attr->nexthop;
941 }
942
943 if (nexthop)
944 {
945 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
946 valid_nh_count++;
947 }
948
949 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
950 mpinfo = bgp_info_mpath_next (mpinfo))
951 {
952 nexthop = NULL;
953
954 if (bgp->table_map[afi][safi].name)
955 {
956 /* Copy info and attributes, so the route-map apply doesn't modify the
957 BGP route info. */
958 BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
959 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
960 nexthop = &info_cp->attr->nexthop;
961 BGP_INFO_ATTR_BUF_FREE(info_cp);
962 }
963 else
964 {
965 nexthop = &mpinfo->attr->nexthop;
966 }
967
968 if (nexthop == NULL)
969 continue;
970
971 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
972 valid_nh_count++;
973 }
974
975 api.flags = flags;
976 api.type = ZEBRA_ROUTE_BGP;
977 api.message = 0;
978 api.safi = safi;
979 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
980 api.nexthop_num = valid_nh_count;
981 api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
982 api.ifindex_num = 0;
983 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
984 api.metric = metric;
985
986 distance = bgp_distance_apply (p, info, bgp);
987
988 if (distance)
989 {
990 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
991 api.distance = distance;
992 }
993
994 if (BGP_DEBUG(zebra, ZEBRA))
995 {
996 int i;
997 zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u"
998 " count %d", (valid_nh_count ? "add":"delete"),
999 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
1000 p->prefixlen, api.metric, api.nexthop_num);
1001 for (i = 0; i < api.nexthop_num; i++)
1002 zlog_debug(" IPv4 [nexthop %d] %s", i+1,
1003 inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1])));
1004 }
1005
1006 zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE,
1007 zclient, (struct prefix_ipv4 *) p, &api);
1008 }
1009 #ifdef HAVE_IPV6
1010
1011 /* We have to think about a IPv6 link-local address curse. */
1012 if (p->family == AF_INET6)
1013 {
1014 unsigned int ifindex;
1015 struct in6_addr *nexthop;
1016 struct zapi_ipv6 api;
1017 int valid_nh_count = 0;
1018 char buf[2][INET6_ADDRSTRLEN];
1019
1020 /* resize nexthop buffer size if necessary */
1021 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
1022 (sizeof (struct in6_addr *) * nhcount))
1023 {
1024 newsize = (sizeof (struct in6_addr *) * nhcount);
1025 newsize = stream_resize (bgp_nexthop_buf, newsize);
1026 if (newsize == oldsize)
1027 {
1028 zlog_err ("can't resize nexthop buffer");
1029 return;
1030 }
1031 }
1032 stream_reset (bgp_nexthop_buf);
1033
1034 /* resize ifindices buffer size if necessary */
1035 if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
1036 (sizeof (unsigned int) * nhcount))
1037 {
1038 newsize = (sizeof (unsigned int) * nhcount);
1039 newsize = stream_resize (bgp_ifindices_buf, newsize);
1040 if (newsize == oldsize)
1041 {
1042 zlog_err ("can't resize nexthop buffer");
1043 return;
1044 }
1045 }
1046 stream_reset (bgp_ifindices_buf);
1047
1048 ifindex = 0;
1049 nexthop = NULL;
1050
1051 assert (info->attr->extra);
1052
1053 /* Metric is currently based on the best-path only. */
1054 metric = info->attr->med;
1055
1056 if (bgp->table_map[afi][safi].name)
1057 {
1058 BGP_INFO_ATTR_BUF_INIT();
1059
1060 /* Copy info and attributes, so the route-map apply doesn't modify the
1061 BGP route info. */
1062 BGP_INFO_ATTR_BUF_COPY(info, info_cp);
1063 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
1064 {
1065 metric = info_cp->attr->med;
1066 nexthop = bgp_info_to_ipv6_nexthop(info_cp);
1067 }
1068 BGP_INFO_ATTR_BUF_FREE(info_cp);
1069 }
1070 else
1071 {
1072 nexthop = bgp_info_to_ipv6_nexthop(info);
1073 }
1074
1075 if (nexthop)
1076 {
1077 if (info->attr->extra->mp_nexthop_len == 32)
1078 if (info->peer->nexthop.ifp)
1079 ifindex = info->peer->nexthop.ifp->ifindex;
1080
1081 if (!ifindex)
1082 if (info->peer->conf_if || info->peer->ifname)
1083 ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname);
1084 else if (info->peer->nexthop.ifp)
1085 ifindex = info->peer->nexthop.ifp->ifindex;
1086
1087 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
1088 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
1089 valid_nh_count++;
1090 }
1091
1092 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
1093 mpinfo = bgp_info_mpath_next (mpinfo))
1094 {
1095 ifindex = 0;
1096 nexthop = NULL;
1097
1098 if (bgp->table_map[afi][safi].name)
1099 {
1100 /* Copy info and attributes, so the route-map apply doesn't modify the
1101 BGP route info. */
1102 BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
1103 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
1104 nexthop = bgp_info_to_ipv6_nexthop(info_cp);
1105 BGP_INFO_ATTR_BUF_FREE(info_cp);
1106 }
1107 else
1108 {
1109 nexthop = bgp_info_to_ipv6_nexthop(mpinfo);
1110 }
1111
1112 if (nexthop == NULL)
1113 continue;
1114
1115 if (mpinfo->attr->extra->mp_nexthop_len == 32)
1116 if (mpinfo->peer->nexthop.ifp)
1117 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
1118
1119 if (!ifindex)
1120 if (mpinfo->peer->conf_if || mpinfo->peer->ifname)
1121 ifindex = if_nametoindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname);
1122 else if (mpinfo->peer->nexthop.ifp)
1123 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
1124
1125 if (ifindex == 0)
1126 continue;
1127
1128 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
1129 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
1130 valid_nh_count++;
1131 }
1132
1133 /* Make Zebra API structure. */
1134 api.flags = flags;
1135 api.type = ZEBRA_ROUTE_BGP;
1136 api.message = 0;
1137 api.safi = safi;
1138 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
1139 api.nexthop_num = valid_nh_count;
1140 api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
1141 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
1142 api.ifindex_num = valid_nh_count;
1143 api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf);
1144 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1145 api.metric = metric;
1146
1147 if (BGP_DEBUG(zebra, ZEBRA))
1148 {
1149 int i;
1150 zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u",
1151 valid_nh_count ? "add" : "delete",
1152 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
1153 p->prefixlen, api.metric);
1154 for (i = 0; i < api.nexthop_num; i++)
1155 zlog_debug(" IPv6 [nexthop %d] %s", i+1,
1156 inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])));
1157 }
1158
1159 zapi_ipv6_route (valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE,
1160 zclient, (struct prefix_ipv6 *) p, &api);
1161 }
1162 #endif /* HAVE_IPV6 */
1163 }
1164
1165 /* Announce all routes of a table to zebra */
1166 void
1167 bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi)
1168 {
1169 struct bgp_node *rn;
1170 struct bgp_table *table;
1171 struct bgp_info *ri;
1172
1173 table = bgp->rib[afi][safi];
1174
1175 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
1176 for (ri = rn->info; ri; ri = ri->next)
1177 if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
1178 && ri->type == ZEBRA_ROUTE_BGP
1179 && ri->sub_type == BGP_ROUTE_NORMAL)
1180 bgp_zebra_announce (&rn->p, ri, bgp, afi, safi);
1181 }
1182
1183 void
1184 bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
1185 {
1186 int flags;
1187 struct peer *peer;
1188
1189 if (zclient->sock < 0)
1190 return;
1191
1192 if (! zclient->redist[ZEBRA_ROUTE_BGP])
1193 return;
1194
1195 peer = info->peer;
1196 flags = 0;
1197
1198 if (peer->sort == BGP_PEER_IBGP)
1199 {
1200 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
1201 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
1202 }
1203
1204 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
1205 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
1206 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
1207
1208 if (p->family == AF_INET)
1209 {
1210 struct zapi_ipv4 api;
1211 struct in_addr *nexthop;
1212
1213 api.flags = flags;
1214 nexthop = &info->attr->nexthop;
1215
1216 api.type = ZEBRA_ROUTE_BGP;
1217 api.message = 0;
1218 api.safi = safi;
1219 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
1220 api.nexthop_num = 1;
1221 api.nexthop = &nexthop;
1222 api.ifindex_num = 0;
1223 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1224 api.metric = info->attr->med;
1225
1226 if (BGP_DEBUG(zebra, ZEBRA))
1227 {
1228 char buf[2][INET_ADDRSTRLEN];
1229 zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u",
1230 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
1231 p->prefixlen,
1232 inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
1233 api.metric);
1234 }
1235
1236 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
1237 (struct prefix_ipv4 *) p, &api);
1238 }
1239 #ifdef HAVE_IPV6
1240 /* We have to think about a IPv6 link-local address curse. */
1241 if (p->family == AF_INET6)
1242 {
1243 struct zapi_ipv6 api;
1244 unsigned int ifindex;
1245 struct in6_addr *nexthop;
1246
1247 assert (info->attr->extra);
1248
1249 ifindex = 0;
1250 nexthop = NULL;
1251
1252 /* Only global address nexthop exists. */
1253 if (info->attr->extra->mp_nexthop_len == 16)
1254 nexthop = &info->attr->extra->mp_nexthop_global;
1255
1256 /* If both global and link-local address present. */
1257 if (info->attr->extra->mp_nexthop_len == 32)
1258 {
1259 nexthop = &info->attr->extra->mp_nexthop_local;
1260 if (info->peer->nexthop.ifp)
1261 ifindex = info->peer->nexthop.ifp->ifindex;
1262 }
1263
1264 if (nexthop == NULL)
1265 return;
1266
1267 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
1268 if (info->peer->conf_if || info->peer->ifname)
1269 ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname);
1270
1271 api.flags = flags;
1272 api.type = ZEBRA_ROUTE_BGP;
1273 api.message = 0;
1274 api.safi = safi;
1275 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
1276 api.nexthop_num = 1;
1277 api.nexthop = &nexthop;
1278 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
1279 api.ifindex_num = 1;
1280 api.ifindex = &ifindex;
1281 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1282 api.metric = info->attr->med;
1283
1284 if (BGP_DEBUG(zebra, ZEBRA))
1285 {
1286 char buf[2][INET6_ADDRSTRLEN];
1287 zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u",
1288 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
1289 p->prefixlen,
1290 inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
1291 api.metric);
1292 }
1293
1294 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
1295 (struct prefix_ipv6 *) p, &api);
1296 }
1297 #endif /* HAVE_IPV6 */
1298 }
1299
1300 /* Other routes redistribution into BGP. */
1301 int
1302 bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
1303 {
1304 /* Set flag to BGP instance. */
1305 bgp->redist[afi][type] = 1;
1306
1307 /* Return if already redistribute flag is set. */
1308 if (zclient->redist[type])
1309 return CMD_WARNING;
1310
1311 zclient->redist[type] = 1;
1312
1313 /* Return if zebra connection is not established. */
1314 if (zclient->sock < 0)
1315 return CMD_WARNING;
1316
1317 if (BGP_DEBUG(zebra, ZEBRA))
1318 zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
1319
1320 /* Send distribute add message to zebra. */
1321 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
1322
1323 return CMD_SUCCESS;
1324 }
1325
1326 /* Redistribute with route-map specification. */
1327 int
1328 bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
1329 const char *name)
1330 {
1331 if (bgp->rmap[afi][type].name
1332 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
1333 return 0;
1334
1335 if (bgp->rmap[afi][type].name)
1336 free (bgp->rmap[afi][type].name);
1337 bgp->rmap[afi][type].name = strdup (name);
1338 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
1339
1340 return 1;
1341 }
1342
1343 /* Redistribute with metric specification. */
1344 int
1345 bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
1346 u_int32_t metric)
1347 {
1348 if (bgp->redist_metric_flag[afi][type]
1349 && bgp->redist_metric[afi][type] == metric)
1350 return 0;
1351
1352 bgp->redist_metric_flag[afi][type] = 1;
1353 bgp->redist_metric[afi][type] = metric;
1354
1355 return 1;
1356 }
1357
1358 /* Unset redistribution. */
1359 int
1360 bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
1361 {
1362 /* Unset flag from BGP instance. */
1363 bgp->redist[afi][type] = 0;
1364
1365 /* Unset route-map. */
1366 if (bgp->rmap[afi][type].name)
1367 free (bgp->rmap[afi][type].name);
1368 bgp->rmap[afi][type].name = NULL;
1369 bgp->rmap[afi][type].map = NULL;
1370
1371 /* Unset metric. */
1372 bgp->redist_metric_flag[afi][type] = 0;
1373 bgp->redist_metric[afi][type] = 0;
1374
1375 /* Return if zebra connection is disabled. */
1376 if (! zclient->redist[type])
1377 return CMD_WARNING;
1378 zclient->redist[type] = 0;
1379
1380 if (bgp->redist[AFI_IP][type] == 0
1381 && bgp->redist[AFI_IP6][type] == 0
1382 && zclient->sock >= 0)
1383 {
1384 /* Send distribute delete message to zebra. */
1385 if (BGP_DEBUG(zebra, ZEBRA))
1386 zlog_debug("Zebra send: redistribute delete %s",
1387 zebra_route_string(type));
1388 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
1389 }
1390
1391 /* Withdraw redistributed routes from current BGP's routing table. */
1392 bgp_redistribute_withdraw (bgp, afi, type);
1393
1394 return CMD_SUCCESS;
1395 }
1396
1397 /* Unset redistribution route-map configuration. */
1398 int
1399 bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
1400 {
1401 if (! bgp->rmap[afi][type].name)
1402 return 0;
1403
1404 /* Unset route-map. */
1405 free (bgp->rmap[afi][type].name);
1406 bgp->rmap[afi][type].name = NULL;
1407 bgp->rmap[afi][type].map = NULL;
1408
1409 return 1;
1410 }
1411
1412 /* Unset redistribution metric configuration. */
1413 int
1414 bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
1415 {
1416 if (! bgp->redist_metric_flag[afi][type])
1417 return 0;
1418
1419 /* Unset metric. */
1420 bgp->redist_metric_flag[afi][type] = 0;
1421 bgp->redist_metric[afi][type] = 0;
1422
1423 return 1;
1424 }
1425
1426 void
1427 bgp_zclient_reset (void)
1428 {
1429 zclient_reset (zclient);
1430 }
1431
1432 void
1433 bgp_zebra_init (void)
1434 {
1435 /* Set default values. */
1436 zclient = zclient_new ();
1437 zclient_init (zclient, ZEBRA_ROUTE_BGP);
1438 zclient->router_id_update = bgp_router_id_update;
1439 zclient->interface_add = bgp_interface_add;
1440 zclient->interface_delete = bgp_interface_delete;
1441 zclient->interface_address_add = bgp_interface_address_add;
1442 zclient->interface_address_delete = bgp_interface_address_delete;
1443 zclient->interface_nbr_address_add = bgp_interface_nbr_address_add;
1444 zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete;
1445 zclient->ipv4_route_add = zebra_read_ipv4;
1446 zclient->ipv4_route_delete = zebra_read_ipv4;
1447 zclient->interface_up = bgp_interface_up;
1448 zclient->interface_down = bgp_interface_down;
1449 #ifdef HAVE_IPV6
1450 zclient->ipv6_route_add = zebra_read_ipv6;
1451 zclient->ipv6_route_delete = zebra_read_ipv6;
1452 #endif /* HAVE_IPV6 */
1453 zclient->nexthop_update = bgp_read_nexthop_update;
1454
1455 /* Interface related init. */
1456 if_init ();
1457
1458 bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
1459 bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
1460 }