[git administrivia] remove auto-built quagga.info, add to gitignore.
[jleu-quagga.git] / bgpd / bgp_zebra.c
blob0cb9e0e2ecfaf3d942dfb8bf6b065133ea3090b0
1 /* zebra client
2 Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
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.
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.
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. */
21 #include <zebra.h>
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"
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"
40 /* All information about zebra. */
41 static struct zclient *zclient = NULL;
42 struct in_addr router_id_zebra;
44 /* Router-id update message from zebra. */
45 static int
46 bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
48 struct prefix router_id;
49 struct listnode *node, *nnode;
50 struct bgp *bgp;
52 zebra_router_id_update_read(zclient->ibuf,&router_id);
53 router_id_zebra = router_id.u.prefix4;
55 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
57 if (!bgp->router_id_static.s_addr)
58 bgp_router_id_set (bgp, &router_id.u.prefix4);
61 return 0;
64 /* Inteface addition message from zebra. */
65 static int
66 bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
68 struct interface *ifp;
70 ifp = zebra_interface_add_read (zclient->ibuf);
72 return 0;
75 static int
76 bgp_interface_delete (int command, struct zclient *zclient,
77 zebra_size_t length)
79 struct stream *s;
80 struct interface *ifp;
82 s = zclient->ibuf;
83 ifp = zebra_interface_state_read (s);
84 ifp->ifindex = IFINDEX_INTERNAL;
86 return 0;
89 static int
90 bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
92 struct stream *s;
93 struct interface *ifp;
94 struct connected *c;
95 struct listnode *node, *nnode;
97 s = zclient->ibuf;
98 ifp = zebra_interface_state_read (s);
100 if (! ifp)
101 return 0;
103 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
104 bgp_connected_add (c);
106 return 0;
109 static int
110 bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
112 struct stream *s;
113 struct interface *ifp;
114 struct connected *c;
115 struct listnode *node, *nnode;
117 s = zclient->ibuf;
118 ifp = zebra_interface_state_read (s);
119 if (! ifp)
120 return 0;
122 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
123 bgp_connected_delete (c);
125 /* Fast external-failover (Currently IPv4 only) */
127 struct listnode *mnode;
128 struct bgp *bgp;
129 struct peer *peer;
130 struct interface *peer_if;
132 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
134 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
135 continue;
137 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
139 if (peer->ttl != 1)
140 continue;
142 if (peer->su.sa.sa_family == AF_INET)
143 peer_if = if_lookup_by_ipv4 (&peer->su.sin.sin_addr);
144 else
145 continue;
147 if (ifp == peer_if)
148 BGP_EVENT_ADD (peer, BGP_Stop);
153 return 0;
156 static int
157 bgp_interface_address_add (int command, struct zclient *zclient,
158 zebra_size_t length)
160 struct connected *ifc;
162 ifc = zebra_interface_address_read (command, zclient->ibuf);
164 if (ifc == NULL)
165 return 0;
167 if (if_is_operative (ifc->ifp))
168 bgp_connected_add (ifc);
170 return 0;
173 static int
174 bgp_interface_address_delete (int command, struct zclient *zclient,
175 zebra_size_t length)
177 struct connected *ifc;
179 ifc = zebra_interface_address_read (command, zclient->ibuf);
181 if (ifc == NULL)
182 return 0;
184 if (if_is_operative (ifc->ifp))
185 bgp_connected_delete (ifc);
187 connected_free (ifc);
189 return 0;
192 /* Zebra route add and delete treatment. */
193 static int
194 zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
196 struct stream *s;
197 struct zapi_ipv4 api;
198 unsigned long ifindex;
199 struct in_addr nexthop;
200 struct prefix_ipv4 p;
202 s = zclient->ibuf;
203 ifindex = 0;
204 nexthop.s_addr = 0;
206 /* Type, flags, message. */
207 api.type = stream_getc (s);
208 api.flags = stream_getc (s);
209 api.message = stream_getc (s);
211 /* IPv4 prefix. */
212 memset (&p, 0, sizeof (struct prefix_ipv4));
213 p.family = AF_INET;
214 p.prefixlen = stream_getc (s);
215 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
217 /* Nexthop, ifindex, distance, metric. */
218 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
220 api.nexthop_num = stream_getc (s);
221 nexthop.s_addr = stream_get_ipv4 (s);
223 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
225 api.ifindex_num = stream_getc (s);
226 ifindex = stream_getl (s);
228 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
229 api.distance = stream_getc (s);
230 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
231 api.metric = stream_getl (s);
232 else
233 api.metric = 0;
235 if (command == ZEBRA_IPV4_ROUTE_ADD)
236 bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type);
237 else
238 bgp_redistribute_delete ((struct prefix *)&p, api.type);
240 return 0;
243 #ifdef HAVE_IPV6
244 /* Zebra route add and delete treatment. */
245 static int
246 zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
248 struct stream *s;
249 struct zapi_ipv6 api;
250 unsigned long ifindex;
251 struct in6_addr nexthop;
252 struct prefix_ipv6 p;
254 s = zclient->ibuf;
255 ifindex = 0;
256 memset (&nexthop, 0, sizeof (struct in6_addr));
258 /* Type, flags, message. */
259 api.type = stream_getc (s);
260 api.flags = stream_getc (s);
261 api.message = stream_getc (s);
263 /* IPv6 prefix. */
264 memset (&p, 0, sizeof (struct prefix_ipv6));
265 p.family = AF_INET6;
266 p.prefixlen = stream_getc (s);
267 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
269 /* Nexthop, ifindex, distance, metric. */
270 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
272 api.nexthop_num = stream_getc (s);
273 stream_get (&nexthop, s, 16);
275 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
277 api.ifindex_num = stream_getc (s);
278 ifindex = stream_getl (s);
280 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
281 api.distance = stream_getc (s);
282 else
283 api.distance = 0;
284 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
285 api.metric = stream_getl (s);
286 else
287 api.metric = 0;
289 /* Simply ignore link-local address. */
290 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
291 return 0;
293 if (command == ZEBRA_IPV6_ROUTE_ADD)
294 bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
295 else
296 bgp_redistribute_delete ((struct prefix *) &p, api.type);
298 return 0;
300 #endif /* HAVE_IPV6 */
302 struct interface *
303 if_lookup_by_ipv4 (struct in_addr *addr)
305 struct listnode *ifnode;
306 struct listnode *cnode;
307 struct interface *ifp;
308 struct connected *connected;
309 struct prefix_ipv4 p;
310 struct prefix *cp;
312 p.family = AF_INET;
313 p.prefix = *addr;
314 p.prefixlen = IPV4_MAX_BITLEN;
316 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
318 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
320 cp = connected->address;
322 if (cp->family == AF_INET)
323 if (prefix_match (cp, (struct prefix *)&p))
324 return ifp;
327 return NULL;
330 struct interface *
331 if_lookup_by_ipv4_exact (struct in_addr *addr)
333 struct listnode *ifnode;
334 struct listnode *cnode;
335 struct interface *ifp;
336 struct connected *connected;
337 struct prefix *cp;
339 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
341 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
343 cp = connected->address;
345 if (cp->family == AF_INET)
346 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
347 return ifp;
350 return NULL;
353 #ifdef HAVE_IPV6
354 struct interface *
355 if_lookup_by_ipv6 (struct in6_addr *addr)
357 struct listnode *ifnode;
358 struct listnode *cnode;
359 struct interface *ifp;
360 struct connected *connected;
361 struct prefix_ipv6 p;
362 struct prefix *cp;
364 p.family = AF_INET6;
365 p.prefix = *addr;
366 p.prefixlen = IPV6_MAX_BITLEN;
368 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
370 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
372 cp = connected->address;
374 if (cp->family == AF_INET6)
375 if (prefix_match (cp, (struct prefix *)&p))
376 return ifp;
379 return NULL;
382 struct interface *
383 if_lookup_by_ipv6_exact (struct in6_addr *addr)
385 struct listnode *ifnode;
386 struct listnode *cnode;
387 struct interface *ifp;
388 struct connected *connected;
389 struct prefix *cp;
391 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
393 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
395 cp = connected->address;
397 if (cp->family == AF_INET6)
398 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
399 return ifp;
402 return NULL;
405 static int
406 if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
408 struct listnode *cnode;
409 struct connected *connected;
410 struct prefix *cp;
412 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
414 cp = connected->address;
416 if (cp->family == AF_INET6)
417 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
419 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
420 return 1;
423 return 0;
426 static int
427 if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
429 struct listnode *cnode;
430 struct connected *connected;
431 struct prefix *cp;
433 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
435 cp = connected->address;
437 if (cp->family == AF_INET6)
438 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
440 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
441 return 1;
444 return 0;
446 #endif /* HAVE_IPV6 */
449 bgp_nexthop_set (union sockunion *local, union sockunion *remote,
450 struct bgp_nexthop *nexthop, struct peer *peer)
452 int ret = 0;
453 struct interface *ifp = NULL;
455 memset (nexthop, 0, sizeof (struct bgp_nexthop));
457 if (!local)
458 return -1;
459 if (!remote)
460 return -1;
462 if (local->sa.sa_family == AF_INET)
464 nexthop->v4 = local->sin.sin_addr;
465 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
467 #ifdef HAVE_IPV6
468 if (local->sa.sa_family == AF_INET6)
470 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
472 if (peer->ifname)
473 ifp = if_lookup_by_index (if_nametoindex (peer->ifname));
475 else
476 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
478 #endif /* HAVE_IPV6 */
480 if (!ifp)
481 return -1;
483 nexthop->ifp = ifp;
485 /* IPv4 connection. */
486 if (local->sa.sa_family == AF_INET)
488 #ifdef HAVE_IPV6
489 /* IPv6 nexthop*/
490 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
492 /* There is no global nexthop. */
493 if (!ret)
494 if_get_ipv6_local (ifp, &nexthop->v6_global);
495 else
496 if_get_ipv6_local (ifp, &nexthop->v6_local);
497 #endif /* HAVE_IPV6 */
500 #ifdef HAVE_IPV6
501 /* IPv6 connection. */
502 if (local->sa.sa_family == AF_INET6)
504 struct interface *direct = NULL;
506 /* IPv4 nexthop. I don't care about it. */
507 if (peer->local_id.s_addr)
508 nexthop->v4 = peer->local_id;
510 /* Global address*/
511 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
513 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
514 IPV6_MAX_BYTELEN);
516 /* If directory connected set link-local address. */
517 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
518 if (direct)
519 if_get_ipv6_local (ifp, &nexthop->v6_local);
521 else
522 /* Link-local address. */
524 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
526 /* If there is no global address. Set link-local address as
527 global. I know this break RFC specification... */
528 if (!ret)
529 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
530 IPV6_MAX_BYTELEN);
531 else
532 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
533 IPV6_MAX_BYTELEN);
537 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
538 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
539 peer->shared_network = 1;
540 else
541 peer->shared_network = 0;
543 /* KAME stack specific treatment. */
544 #ifdef KAME
545 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
546 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
548 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
550 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
551 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
553 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
555 #endif /* KAME */
556 #endif /* HAVE_IPV6 */
557 return ret;
560 #ifdef HAVE_IPV6
561 static unsigned int
562 bgp_ifindex_by_nexthop (struct in6_addr *addr)
564 struct listnode *ifnode;
565 struct listnode *cnode;
566 struct interface *ifp;
567 struct connected *connected;
568 struct prefix_ipv6 p;
570 p.family = AF_INET6;
571 p.prefix = *addr;
572 p.prefixlen = IPV6_MAX_BITLEN;
574 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
576 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
578 struct prefix *cp;
580 cp = connected->address;
582 if (cp->family == AF_INET6)
584 if (prefix_match (cp, (struct prefix *)&p))
585 return ifp->ifindex;
589 return 0;
591 #endif /* HAVE_IPV6 */
593 void
594 bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
596 int flags;
597 u_char distance;
598 struct peer *peer;
600 if (zclient->sock < 0)
601 return;
603 if (! zclient->redist[ZEBRA_ROUTE_BGP])
604 return;
606 flags = 0;
607 peer = info->peer;
609 if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED)
611 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
612 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
615 if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
616 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
617 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
619 if (p->family == AF_INET)
621 struct zapi_ipv4 api;
622 struct in_addr *nexthop;
624 api.flags = flags;
625 nexthop = &info->attr->nexthop;
627 api.type = ZEBRA_ROUTE_BGP;
628 api.message = 0;
629 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
630 api.nexthop_num = 1;
631 api.nexthop = &nexthop;
632 api.ifindex_num = 0;
633 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
634 api.metric = info->attr->med;
636 distance = bgp_distance_apply (p, info, bgp);
638 if (distance)
640 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
641 api.distance = distance;
643 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
644 (struct prefix_ipv4 *) p, &api);
646 #ifdef HAVE_IPV6
647 /* We have to think about a IPv6 link-local address curse. */
648 if (p->family == AF_INET6)
650 unsigned int ifindex;
651 struct in6_addr *nexthop;
652 struct zapi_ipv6 api;
654 ifindex = 0;
655 nexthop = NULL;
657 /* Only global address nexthop exists. */
658 if (info->attr->mp_nexthop_len == 16)
659 nexthop = &info->attr->mp_nexthop_global;
661 /* If both global and link-local address present. */
662 if (info->attr->mp_nexthop_len == 32)
664 /* Workaround for Cisco's nexthop bug. */
665 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global)
666 && peer->su_remote->sa.sa_family == AF_INET6)
667 nexthop = &peer->su_remote->sin6.sin6_addr;
668 else
669 nexthop = &info->attr->mp_nexthop_local;
671 if (info->peer->nexthop.ifp)
672 ifindex = info->peer->nexthop.ifp->ifindex;
675 if (nexthop == NULL)
676 return;
678 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
680 if (info->peer->ifname)
681 ifindex = if_nametoindex (info->peer->ifname);
682 else if (info->peer->nexthop.ifp)
683 ifindex = info->peer->nexthop.ifp->ifindex;
686 /* Make Zebra API structure. */
687 api.flags = flags;
688 api.type = ZEBRA_ROUTE_BGP;
689 api.message = 0;
690 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
691 api.nexthop_num = 1;
692 api.nexthop = &nexthop;
693 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
694 api.ifindex_num = 1;
695 api.ifindex = &ifindex;
696 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
697 api.metric = info->attr->med;
699 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
700 (struct prefix_ipv6 *) p, &api);
702 #endif /* HAVE_IPV6 */
705 void
706 bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
708 int flags;
709 struct peer *peer;
711 if (zclient->sock < 0)
712 return;
714 if (! zclient->redist[ZEBRA_ROUTE_BGP])
715 return;
717 peer = info->peer;
718 flags = 0;
720 if (peer_sort (peer) == BGP_PEER_IBGP)
722 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
723 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
726 if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
727 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
728 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
730 if (p->family == AF_INET)
732 struct zapi_ipv4 api;
733 struct in_addr *nexthop;
735 api.flags = flags;
736 nexthop = &info->attr->nexthop;
738 api.type = ZEBRA_ROUTE_BGP;
739 api.message = 0;
740 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
741 api.nexthop_num = 1;
742 api.nexthop = &nexthop;
743 api.ifindex_num = 0;
744 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
745 api.metric = info->attr->med;
747 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
748 (struct prefix_ipv4 *) p, &api);
750 #ifdef HAVE_IPV6
751 /* We have to think about a IPv6 link-local address curse. */
752 if (p->family == AF_INET6)
754 struct zapi_ipv6 api;
755 unsigned int ifindex;
756 struct in6_addr *nexthop;
758 ifindex = 0;
759 nexthop = NULL;
761 /* Only global address nexthop exists. */
762 if (info->attr->mp_nexthop_len == 16)
763 nexthop = &info->attr->mp_nexthop_global;
765 /* If both global and link-local address present. */
766 if (info->attr->mp_nexthop_len == 32)
768 nexthop = &info->attr->mp_nexthop_local;
769 if (info->peer->nexthop.ifp)
770 ifindex = info->peer->nexthop.ifp->ifindex;
773 if (nexthop == NULL)
774 return;
776 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
777 if (info->peer->ifname)
778 ifindex = if_nametoindex (info->peer->ifname);
780 api.flags = flags;
781 api.type = ZEBRA_ROUTE_BGP;
782 api.message = 0;
783 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
784 api.nexthop_num = 1;
785 api.nexthop = &nexthop;
786 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
787 api.ifindex_num = 1;
788 api.ifindex = &ifindex;
789 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
790 api.metric = info->attr->med;
792 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
793 (struct prefix_ipv6 *) p, &api);
795 #endif /* HAVE_IPV6 */
798 /* Other routes redistribution into BGP. */
800 bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
802 /* Set flag to BGP instance. */
803 bgp->redist[afi][type] = 1;
805 /* Return if already redistribute flag is set. */
806 if (zclient->redist[type])
807 return CMD_WARNING;
809 zclient->redist[type] = 1;
811 /* Return if zebra connection is not established. */
812 if (zclient->sock < 0)
813 return CMD_WARNING;
815 /* Send distribute add message to zebra. */
816 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
818 return CMD_SUCCESS;
821 /* Redistribute with route-map specification. */
823 bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
824 const char *name)
826 if (bgp->rmap[afi][type].name
827 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
828 return 0;
830 if (bgp->rmap[afi][type].name)
831 free (bgp->rmap[afi][type].name);
832 bgp->rmap[afi][type].name = strdup (name);
833 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
835 return 1;
838 /* Redistribute with metric specification. */
840 bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
841 u_int32_t metric)
843 if (bgp->redist_metric_flag[afi][type]
844 && bgp->redist_metric[afi][type] == metric)
845 return 0;
847 bgp->redist_metric_flag[afi][type] = 1;
848 bgp->redist_metric[afi][type] = metric;
850 return 1;
853 /* Unset redistribution. */
855 bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
857 /* Unset flag from BGP instance. */
858 bgp->redist[afi][type] = 0;
860 /* Unset route-map. */
861 if (bgp->rmap[afi][type].name)
862 free (bgp->rmap[afi][type].name);
863 bgp->rmap[afi][type].name = NULL;
864 bgp->rmap[afi][type].map = NULL;
866 /* Unset metric. */
867 bgp->redist_metric_flag[afi][type] = 0;
868 bgp->redist_metric[afi][type] = 0;
870 /* Return if zebra connection is disabled. */
871 if (! zclient->redist[type])
872 return CMD_WARNING;
873 zclient->redist[type] = 0;
875 if (bgp->redist[AFI_IP][type] == 0
876 && bgp->redist[AFI_IP6][type] == 0
877 && zclient->sock >= 0)
878 /* Send distribute delete message to zebra. */
879 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
881 /* Withdraw redistributed routes from current BGP's routing table. */
882 bgp_redistribute_withdraw (bgp, afi, type);
884 return CMD_SUCCESS;
887 /* Unset redistribution route-map configuration. */
889 bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
891 if (! bgp->rmap[afi][type].name)
892 return 0;
894 /* Unset route-map. */
895 free (bgp->rmap[afi][type].name);
896 bgp->rmap[afi][type].name = NULL;
897 bgp->rmap[afi][type].map = NULL;
899 return 1;
902 /* Unset redistribution metric configuration. */
904 bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
906 if (! bgp->redist_metric_flag[afi][type])
907 return 0;
909 /* Unset metric. */
910 bgp->redist_metric_flag[afi][type] = 0;
911 bgp->redist_metric[afi][type] = 0;
913 return 1;
916 void
917 bgp_zclient_reset (void)
919 zclient_reset (zclient);
922 void
923 bgp_zebra_init (void)
925 /* Set default values. */
926 zclient = zclient_new ();
927 zclient_init (zclient, ZEBRA_ROUTE_BGP);
928 zclient->router_id_update = bgp_router_id_update;
929 zclient->interface_add = bgp_interface_add;
930 zclient->interface_delete = bgp_interface_delete;
931 zclient->interface_address_add = bgp_interface_address_add;
932 zclient->interface_address_delete = bgp_interface_address_delete;
933 zclient->ipv4_route_add = zebra_read_ipv4;
934 zclient->ipv4_route_delete = zebra_read_ipv4;
935 zclient->interface_up = bgp_interface_up;
936 zclient->interface_down = bgp_interface_down;
937 #ifdef HAVE_IPV6
938 zclient->ipv6_route_add = zebra_read_ipv6;
939 zclient->ipv6_route_delete = zebra_read_ipv6;
940 #endif /* HAVE_IPV6 */
942 /* Interface related init. */
943 if_init ();