blob: 3e5cdd2a139f9edff611418877096338453b2be3 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* zebra client
2 Copyright (C) 1997, 98, 99 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
18Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, 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
40/* All information about zebra. */
41static struct zclient *zclient = NULL;
42
43/* Update default router id. */
44int
45bgp_if_update (struct interface *ifp)
46{
47 struct bgp *bgp;
48 listnode cn;
49 struct listnode *nn;
50 struct listnode *nm;
51 struct peer *peer;
52
53 for (cn = listhead (ifp->connected); cn; nextnode (cn))
54 {
55 struct connected *co;
56 struct in_addr addr;
57
58 co = getdata (cn);
59
60 if (co->address->family == AF_INET)
61 {
62 addr = co->address->u.prefix4;
63
64 /* Ignore NET127. */
65 if (IPV4_NET127 (ntohl (addr.s_addr)))
66 continue;
67
68 LIST_LOOP (bm->bgp, bgp, nn)
69 {
70 /* Respect configured router id */
71 if (! (bgp->config & BGP_CONFIG_ROUTER_ID))
72 if (ntohl (bgp->router_id.s_addr) < ntohl (addr.s_addr))
73 {
74 bgp->router_id = addr;
75 LIST_LOOP (bgp->peer, peer, nm)
76 {
77 peer->local_id = addr;
78 }
79 }
80 }
81 }
82 }
83 return 0;
84}
85
86int
87bgp_if_update_all ()
88{
89 listnode node;
90 struct interface *ifp;
91
92 for (node = listhead (iflist); node; node = nextnode (node))
93 {
94 ifp = getdata (node);
95 bgp_if_update (ifp);
96 }
97 return 0;
98}
99
100/* Inteface addition message from zebra. */
101int
102bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
103{
104 struct interface *ifp;
105
106 ifp = zebra_interface_add_read (zclient->ibuf);
107 bgp_if_update (ifp);
108
109 return 0;
110}
111
112int
113bgp_interface_delete (int command, struct zclient *zclient,
114 zebra_size_t length)
115{
116 struct stream *s;
117 struct interface *ifp;
118
119 s = zclient->ibuf;
120 ifp = zebra_interface_state_read (s);
121
122 return 0;
123}
124
125int
126bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
127{
128 struct stream *s;
129 struct interface *ifp;
130 struct connected *c;
131 listnode node;
132
133 s = zclient->ibuf;
134 ifp = zebra_interface_state_read (s);
135
136 if (! ifp)
137 return 0;
138
139 for (node = listhead (ifp->connected); node; nextnode (node))
140 {
141 c = getdata (node);
142 bgp_connected_add (c);
143 }
144
145 return 0;
146}
147
148int
149bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
150{
151 struct stream *s;
152 struct interface *ifp;
153 struct connected *c;
154 listnode node;
155
156 s = zclient->ibuf;
157 ifp = zebra_interface_state_read (s);
158 if (! ifp)
159 return 0;
160
161 for (node = listhead (ifp->connected); node; nextnode (node))
162 {
163 c = getdata (node);
164 bgp_connected_delete (c);
165 }
166
167 /* Fast external-failover (Currently IPv4 only) */
168 {
169 struct listnode *nn, *nm;
170 struct bgp *bgp;
171 struct peer *peer;
172 struct interface *peer_if;
173
174 LIST_LOOP (bm->bgp, bgp, nn)
175 {
176 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
177 continue;
178
179 LIST_LOOP (bgp->peer, peer, nm)
180 {
181 if (peer->ttl != 1)
182 continue;
183
184 if (peer->su.sa.sa_family == AF_INET)
185 peer_if = if_lookup_by_ipv4 (&peer->su.sin.sin_addr);
186 else
187 continue;
188
189 if (ifp == peer_if)
190 BGP_EVENT_ADD (peer, BGP_Stop);
191 }
192 }
193 }
194
195 return 0;
196}
197
198int
199bgp_interface_address_add (int command, struct zclient *zclient,
200 zebra_size_t length)
201{
202 struct connected *ifc;
203
204 ifc = zebra_interface_address_add_read (zclient->ibuf);
205
206 if (ifc == NULL)
207 return 0;
208
209 bgp_if_update (ifc->ifp);
210
211 if (if_is_up (ifc->ifp))
212 bgp_connected_add (ifc);
213
214 return 0;
215}
216
217int
218bgp_interface_address_delete (int command, struct zclient *zclient,
219 zebra_size_t length)
220{
221 struct connected *ifc;
222
223 ifc = zebra_interface_address_delete_read (zclient->ibuf);
224
225 if (ifc == NULL)
226 return 0;
227
228 bgp_if_update (ifc->ifp);
229
230 if (if_is_up (ifc->ifp))
231 bgp_connected_delete (ifc);
232
233 connected_free (ifc);
234
235 return 0;
236}
237
238/* Zebra route add and delete treatment. */
239int
240zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
241{
242 struct stream *s;
243 struct zapi_ipv4 api;
244 unsigned long ifindex;
245 struct in_addr nexthop;
246 struct prefix_ipv4 p;
247
248 s = zclient->ibuf;
249 ifindex = 0;
250 nexthop.s_addr = 0;
251
252 /* Type, flags, message. */
253 api.type = stream_getc (s);
254 api.flags = stream_getc (s);
255 api.message = stream_getc (s);
256
257 /* IPv4 prefix. */
258 memset (&p, 0, sizeof (struct prefix_ipv4));
259 p.family = AF_INET;
260 p.prefixlen = stream_getc (s);
261 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
262
263 /* Nexthop, ifindex, distance, metric. */
264 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
265 {
266 api.nexthop_num = stream_getc (s);
267 nexthop.s_addr = stream_get_ipv4 (s);
268 }
269 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
270 {
271 api.ifindex_num = stream_getc (s);
272 ifindex = stream_getl (s);
273 }
274 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
275 api.distance = stream_getc (s);
276 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
277 api.metric = stream_getl (s);
278 else
279 api.metric = 0;
280
281 if (command == ZEBRA_IPV4_ROUTE_ADD)
282 bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type);
283 else
284 bgp_redistribute_delete ((struct prefix *)&p, api.type);
285
286 return 0;
287}
288
289#ifdef HAVE_IPV6
290/* Zebra route add and delete treatment. */
291int
292zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
293{
294 struct stream *s;
295 struct zapi_ipv6 api;
296 unsigned long ifindex;
297 struct in6_addr nexthop;
298 struct prefix_ipv6 p;
299
300 s = zclient->ibuf;
301 ifindex = 0;
302 memset (&nexthop, 0, sizeof (struct in6_addr));
303
304 /* Type, flags, message. */
305 api.type = stream_getc (s);
306 api.flags = stream_getc (s);
307 api.message = stream_getc (s);
308
309 /* IPv6 prefix. */
310 memset (&p, 0, sizeof (struct prefix_ipv6));
311 p.family = AF_INET6;
312 p.prefixlen = stream_getc (s);
313 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
314
315 /* Nexthop, ifindex, distance, metric. */
316 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
317 {
318 api.nexthop_num = stream_getc (s);
319 stream_get (&nexthop, s, 16);
320 }
321 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
322 {
323 api.ifindex_num = stream_getc (s);
324 ifindex = stream_getl (s);
325 }
326 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
327 api.distance = stream_getc (s);
328 else
329 api.distance = 0;
330 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
331 api.metric = stream_getl (s);
332 else
333 api.metric = 0;
334
335 /* Simply ignore link-local address. */
336 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
337 return 0;
338
339 if (command == ZEBRA_IPV6_ROUTE_ADD)
340 bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
341 else
342 bgp_redistribute_delete ((struct prefix *) &p, api.type);
343
344 return 0;
345}
346#endif /* HAVE_IPV6 */
347
348struct interface *
349if_lookup_by_ipv4 (struct in_addr *addr)
350{
351 listnode ifnode;
352 listnode cnode;
353 struct interface *ifp;
354 struct connected *connected;
355 struct prefix_ipv4 p;
356 struct prefix *cp;
357
358 p.family = AF_INET;
359 p.prefix = *addr;
360 p.prefixlen = IPV4_MAX_BITLEN;
361
362 for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
363 {
364 ifp = getdata (ifnode);
365
366 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
367 {
368 connected = getdata (cnode);
369 cp = connected->address;
370
371 if (cp->family == AF_INET)
372 if (prefix_match (cp, (struct prefix *)&p))
373 return ifp;
374 }
375 }
376 return NULL;
377}
378
379struct interface *
380if_lookup_by_ipv4_exact (struct in_addr *addr)
381{
382 listnode ifnode;
383 listnode cnode;
384 struct interface *ifp;
385 struct connected *connected;
386 struct prefix *cp;
387
388 for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
389 {
390 ifp = getdata (ifnode);
391
392 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
393 {
394 connected = getdata (cnode);
395 cp = connected->address;
396
397 if (cp->family == AF_INET)
398 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
399 return ifp;
400 }
401 }
402 return NULL;
403}
404
405#ifdef HAVE_IPV6
406struct interface *
407if_lookup_by_ipv6 (struct in6_addr *addr)
408{
409 listnode ifnode;
410 listnode cnode;
411 struct interface *ifp;
412 struct connected *connected;
413 struct prefix_ipv6 p;
414 struct prefix *cp;
415
416 p.family = AF_INET6;
417 p.prefix = *addr;
418 p.prefixlen = IPV6_MAX_BITLEN;
419
420 for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
421 {
422 ifp = getdata (ifnode);
423
424 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
425 {
426 connected = getdata (cnode);
427 cp = connected->address;
428
429 if (cp->family == AF_INET6)
430 if (prefix_match (cp, (struct prefix *)&p))
431 return ifp;
432 }
433 }
434 return NULL;
435}
436
437struct interface *
438if_lookup_by_ipv6_exact (struct in6_addr *addr)
439{
440 listnode ifnode;
441 listnode cnode;
442 struct interface *ifp;
443 struct connected *connected;
444 struct prefix *cp;
445
446 for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
447 {
448 ifp = getdata (ifnode);
449
450 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
451 {
452 connected = getdata (cnode);
453 cp = connected->address;
454
455 if (cp->family == AF_INET6)
456 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
457 return ifp;
458 }
459 }
460 return NULL;
461}
462
463int
464if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
465{
466 listnode cnode;
467 struct connected *connected;
468 struct prefix *cp;
469
470 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
471 {
472 connected = getdata (cnode);
473 cp = connected->address;
474
475 if (cp->family == AF_INET6)
476 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
477 {
478 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
479 return 1;
480 }
481 }
482 return 0;
483}
484
485int
486if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
487{
488 listnode cnode;
489 struct connected *connected;
490 struct prefix *cp;
491
492 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
493 {
494 connected = getdata (cnode);
495 cp = connected->address;
496
497 if (cp->family == AF_INET6)
498 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
499 {
500 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
501 return 1;
502 }
503 }
504 return 0;
505}
506#endif /* HAVE_IPV6 */
507
508int
509bgp_nexthop_set (union sockunion *local, union sockunion *remote,
510 struct bgp_nexthop *nexthop, struct peer *peer)
511{
512 int ret = 0;
513 struct interface *ifp = NULL;
514
515 memset (nexthop, 0, sizeof (struct bgp_nexthop));
516
517 if (!local)
518 return -1;
519 if (!remote)
520 return -1;
521
522 if (local->sa.sa_family == AF_INET)
523 {
524 nexthop->v4 = local->sin.sin_addr;
525 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
526 }
527#ifdef HAVE_IPV6
528 if (local->sa.sa_family == AF_INET6)
529 {
530 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
531 {
532 if (peer->ifname)
533 ifp = if_lookup_by_index (if_nametoindex (peer->ifname));
534 }
535 else
536 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
537 }
538#endif /* HAVE_IPV6 */
539
540 if (!ifp)
541 return -1;
542
543 nexthop->ifp = ifp;
544
545 /* IPv4 connection. */
546 if (local->sa.sa_family == AF_INET)
547 {
548#ifdef HAVE_IPV6
549 /* IPv6 nexthop*/
550 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
551
552 /* There is no global nexthop. */
553 if (!ret)
554 if_get_ipv6_local (ifp, &nexthop->v6_global);
555 else
556 if_get_ipv6_local (ifp, &nexthop->v6_local);
557#endif /* HAVE_IPV6 */
558 }
559
560#ifdef HAVE_IPV6
561 /* IPv6 connection. */
562 if (local->sa.sa_family == AF_INET6)
563 {
564 struct interface *direct = NULL;
565
566 /* IPv4 nexthop. I don't care about it. */
567 if (peer->local_id.s_addr)
568 nexthop->v4 = peer->local_id;
569
570 /* Global address*/
571 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
572 {
573 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
574 IPV6_MAX_BYTELEN);
575
576 /* If directory connected set link-local address. */
577 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
578 if (direct)
579 if_get_ipv6_local (ifp, &nexthop->v6_local);
580 }
581 else
582 /* Link-local address. */
583 {
584 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
585
586 /* If there is no global address. Set link-local address as
587 global. I know this break RFC specification... */
588 if (!ret)
589 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
590 IPV6_MAX_BYTELEN);
591 else
592 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
593 IPV6_MAX_BYTELEN);
594 }
595 }
596
597 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
598 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
599 peer->shared_network = 1;
600 else
601 peer->shared_network = 0;
602
603 /* KAME stack specific treatment. */
604#ifdef KAME
605 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
606 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
607 {
608 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
609 }
610 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
611 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
612 {
613 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
614 }
615#endif /* KAME */
616#endif /* HAVE_IPV6 */
617 return ret;
618}
619
620#ifdef HAVE_IPV6
621unsigned int
622bgp_ifindex_by_nexthop (struct in6_addr *addr)
623{
624 listnode ifnode;
625 listnode cnode;
626 struct interface *ifp;
627 struct connected *connected;
628 struct prefix_ipv6 p;
629
630 p.family = AF_INET6;
631 p.prefix = *addr;
632 p.prefixlen = IPV6_MAX_BITLEN;
633
634 for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
635 {
636 ifp = getdata (ifnode);
637
638 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
639 {
640 struct prefix *cp;
641
642 connected = getdata (cnode);
643 cp = connected->address;
644
645 if (cp->family == AF_INET6)
646 {
647 if (prefix_match (cp, (struct prefix *)&p))
648 return ifp->ifindex;
649 }
650 }
651 }
652 return 0;
653}
654#endif /* HAVE_IPV6 */
655
656void
657bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
658{
659 int flags;
660 u_char distance;
661 struct peer *peer;
662
663 if (zclient->sock < 0)
664 return;
665
666 if (! zclient->redist[ZEBRA_ROUTE_BGP])
667 return;
668
669 flags = 0;
670 peer = info->peer;
671
672 if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED)
673 {
674 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
675 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
676 }
677
678 if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
679 || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
680 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
681
682 if (p->family == AF_INET)
683 {
684 struct zapi_ipv4 api;
685 struct in_addr *nexthop;
686
687 api.flags = flags;
688 nexthop = &info->attr->nexthop;
689
690 api.type = ZEBRA_ROUTE_BGP;
691 api.message = 0;
692 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
693 api.nexthop_num = 1;
694 api.nexthop = &nexthop;
695 api.ifindex_num = 0;
696 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
697 api.metric = info->attr->med;
698
699 distance = bgp_distance_apply (p, info, bgp);
700
701 if (distance)
702 {
703 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
704 api.distance = distance;
705 }
706 zapi_ipv4_add (zclient, (struct prefix_ipv4 *) p, &api);
707 }
708#ifdef HAVE_IPV6
709 /* We have to think about a IPv6 link-local address curse. */
710 if (p->family == AF_INET6)
711 {
712 unsigned int ifindex;
713 struct in6_addr *nexthop;
714 struct zapi_ipv6 api;
715
716 ifindex = 0;
717 nexthop = NULL;
718
719 /* Only global address nexthop exists. */
720 if (info->attr->mp_nexthop_len == 16)
721 nexthop = &info->attr->mp_nexthop_global;
722
723 /* If both global and link-local address present. */
724 if (info->attr->mp_nexthop_len == 32)
725 {
726 /* Workaround for Cisco's nexthop bug. */
727 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global)
728 && peer->su_remote->sa.sa_family == AF_INET6)
729 nexthop = &peer->su_remote->sin6.sin6_addr;
730 else
731 nexthop = &info->attr->mp_nexthop_local;
732
733 if (info->peer->nexthop.ifp)
734 ifindex = info->peer->nexthop.ifp->ifindex;
735 }
736
737 if (nexthop == NULL)
738 return;
739
740 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
741 {
742 if (info->peer->ifname)
743 ifindex = if_nametoindex (info->peer->ifname);
744 else if (info->peer->nexthop.ifp)
745 ifindex = info->peer->nexthop.ifp->ifindex;
746 }
747
748 /* Make Zebra API structure. */
749 api.flags = flags;
750 api.type = ZEBRA_ROUTE_BGP;
751 api.message = 0;
752 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
753 api.nexthop_num = 1;
754 api.nexthop = &nexthop;
755 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
756 api.ifindex_num = 1;
757 api.ifindex = &ifindex;
758 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
759 api.metric = info->attr->med;
760
761 zapi_ipv6_add (zclient, (struct prefix_ipv6 *) p, &api);
762 }
763#endif /* HAVE_IPV6 */
764}
765
766void
767bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
768{
769 int flags;
770 struct peer *peer;
771
772 if (zclient->sock < 0)
773 return;
774
775 if (! zclient->redist[ZEBRA_ROUTE_BGP])
776 return;
777
778 peer = info->peer;
779 flags = 0;
780
781 if (peer_sort (peer) == BGP_PEER_IBGP)
782 {
783 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
784 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
785 }
786
787 if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
788 || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
789 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
790
791 if (p->family == AF_INET)
792 {
793 struct zapi_ipv4 api;
794 struct in_addr *nexthop;
795
796 api.flags = flags;
797 nexthop = &info->attr->nexthop;
798
799 api.type = ZEBRA_ROUTE_BGP;
800 api.message = 0;
801 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
802 api.nexthop_num = 1;
803 api.nexthop = &nexthop;
804 api.ifindex_num = 0;
805 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
806 api.metric = info->attr->med;
807
808 zapi_ipv4_delete (zclient, (struct prefix_ipv4 *) p, &api);
809 }
810#ifdef HAVE_IPV6
811 /* We have to think about a IPv6 link-local address curse. */
812 if (p->family == AF_INET6)
813 {
814 struct zapi_ipv6 api;
815 unsigned int ifindex;
816 struct in6_addr *nexthop;
817
818 ifindex = 0;
819 nexthop = NULL;
820
821 /* Only global address nexthop exists. */
822 if (info->attr->mp_nexthop_len == 16)
823 nexthop = &info->attr->mp_nexthop_global;
824
825 /* If both global and link-local address present. */
826 if (info->attr->mp_nexthop_len == 32)
827 {
828 nexthop = &info->attr->mp_nexthop_local;
829 if (info->peer->nexthop.ifp)
830 ifindex = info->peer->nexthop.ifp->ifindex;
831 }
832
833 if (nexthop == NULL)
834 return;
835
836 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
837 if (info->peer->ifname)
838 ifindex = if_nametoindex (info->peer->ifname);
839
840 api.flags = flags;
841 api.type = ZEBRA_ROUTE_BGP;
842 api.message = 0;
843 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
844 api.nexthop_num = 1;
845 api.nexthop = &nexthop;
846 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
847 api.ifindex_num = 1;
848 api.ifindex = &ifindex;
849 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
850 api.metric = info->attr->med;
851
852 zapi_ipv6_delete (zclient, (struct prefix_ipv6 *) p, &api);
853 }
854#endif /* HAVE_IPV6 */
855}
856
857/* Other routes redistribution into BGP. */
858int
859bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
860{
861 /* Set flag to BGP instance. */
862 bgp->redist[afi][type] = 1;
863
864 /* Return if already redistribute flag is set. */
865 if (zclient->redist[type])
866 return CMD_WARNING;
867
868 zclient->redist[type] = 1;
869
870 /* Return if zebra connection is not established. */
871 if (zclient->sock < 0)
872 return CMD_WARNING;
873
874 /* Send distribute add message to zebra. */
875 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
876
877 return CMD_SUCCESS;
878}
879
880/* Redistribute with route-map specification. */
881int
882bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type, char *name)
883{
884 if (bgp->rmap[afi][type].name
885 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
886 return 0;
887
888 if (bgp->rmap[afi][type].name)
889 free (bgp->rmap[afi][type].name);
890 bgp->rmap[afi][type].name = strdup (name);
891 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
892
893 return 1;
894}
895
896/* Redistribute with metric specification. */
897int
898bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
899 u_int32_t metric)
900{
901 if (bgp->redist_metric_flag[afi][type]
902 && bgp->redist_metric[afi][type] == metric)
903 return 0;
904
905 bgp->redist_metric_flag[afi][type] = 1;
906 bgp->redist_metric[afi][type] = metric;
907
908 return 1;
909}
910
911/* Unset redistribution. */
912int
913bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
914{
915 /* Unset flag from BGP instance. */
916 bgp->redist[afi][type] = 0;
917
918 /* Unset route-map. */
919 if (bgp->rmap[afi][type].name)
920 free (bgp->rmap[afi][type].name);
921 bgp->rmap[afi][type].name = NULL;
922 bgp->rmap[afi][type].map = NULL;
923
924 /* Unset metric. */
925 bgp->redist_metric_flag[afi][type] = 0;
926 bgp->redist_metric[afi][type] = 0;
927
928 /* Return if zebra connection is disabled. */
929 if (! zclient->redist[type])
930 return CMD_WARNING;
931 zclient->redist[type] = 0;
932
933 if (bgp->redist[AFI_IP][type] == 0
934 && bgp->redist[AFI_IP6][type] == 0
935 && zclient->sock >= 0)
936 /* Send distribute delete message to zebra. */
937 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
938
939 /* Withdraw redistributed routes from current BGP's routing table. */
940 bgp_redistribute_withdraw (bgp, afi, type);
941
942 return CMD_SUCCESS;
943}
944
945/* Unset redistribution route-map configuration. */
946int
947bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
948{
949 if (! bgp->rmap[afi][type].name)
950 return 0;
951
952 /* Unset route-map. */
953 free (bgp->rmap[afi][type].name);
954 bgp->rmap[afi][type].name = NULL;
955 bgp->rmap[afi][type].map = NULL;
956
957 return 1;
958}
959
960/* Unset redistribution metric configuration. */
961int
962bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
963{
964 if (! bgp->redist_metric_flag[afi][type])
965 return 0;
966
967 /* Unset metric. */
968 bgp->redist_metric_flag[afi][type] = 0;
969 bgp->redist_metric[afi][type] = 0;
970
971 return 1;
972}
973
974void
975bgp_zclient_reset ()
976{
977 zclient_reset (zclient);
978}
979
980void
981bgp_zebra_init (int enable)
982{
983 /* Set default values. */
984 zclient = zclient_new ();
985 zclient_init (zclient, ZEBRA_ROUTE_BGP);
986 zclient->interface_add = bgp_interface_add;
987 zclient->interface_delete = bgp_interface_delete;
988 zclient->interface_address_add = bgp_interface_address_add;
989 zclient->interface_address_delete = bgp_interface_address_delete;
990 zclient->ipv4_route_add = zebra_read_ipv4;
991 zclient->ipv4_route_delete = zebra_read_ipv4;
992 zclient->interface_up = bgp_interface_up;
993 zclient->interface_down = bgp_interface_down;
994#ifdef HAVE_IPV6
995 zclient->ipv6_route_add = zebra_read_ipv6;
996 zclient->ipv6_route_delete = zebra_read_ipv6;
997#endif /* HAVE_IPV6 */
998
999 /* Interface related init. */
1000 if_init ();
1001}