blob: 394bde635ca351f72a1ad13607b218b20653c154 [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
paul0a589352004-05-08 11:48:26 +0000204 ifc = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000205
206 if (ifc == NULL)
207 return 0;
208
209 bgp_if_update (ifc->ifp);
210
paul2e3b2e42002-12-13 21:03:13 +0000211 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000212 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
paul0a589352004-05-08 11:48:26 +0000223 ifc = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000224
225 if (ifc == NULL)
226 return 0;
227
228 bgp_if_update (ifc->ifp);
229
paul2e3b2e42002-12-13 21:03:13 +0000230 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000231 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 }
paul0a589352004-05-08 11:48:26 +0000706 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
707 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000708 }
709#ifdef HAVE_IPV6
710 /* We have to think about a IPv6 link-local address curse. */
711 if (p->family == AF_INET6)
712 {
713 unsigned int ifindex;
714 struct in6_addr *nexthop;
715 struct zapi_ipv6 api;
716
717 ifindex = 0;
718 nexthop = NULL;
719
720 /* Only global address nexthop exists. */
721 if (info->attr->mp_nexthop_len == 16)
722 nexthop = &info->attr->mp_nexthop_global;
723
724 /* If both global and link-local address present. */
725 if (info->attr->mp_nexthop_len == 32)
726 {
727 /* Workaround for Cisco's nexthop bug. */
728 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global)
729 && peer->su_remote->sa.sa_family == AF_INET6)
730 nexthop = &peer->su_remote->sin6.sin6_addr;
731 else
732 nexthop = &info->attr->mp_nexthop_local;
733
734 if (info->peer->nexthop.ifp)
735 ifindex = info->peer->nexthop.ifp->ifindex;
736 }
737
738 if (nexthop == NULL)
739 return;
740
741 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
742 {
743 if (info->peer->ifname)
744 ifindex = if_nametoindex (info->peer->ifname);
745 else if (info->peer->nexthop.ifp)
746 ifindex = info->peer->nexthop.ifp->ifindex;
747 }
748
749 /* Make Zebra API structure. */
750 api.flags = flags;
751 api.type = ZEBRA_ROUTE_BGP;
752 api.message = 0;
753 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
754 api.nexthop_num = 1;
755 api.nexthop = &nexthop;
756 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
757 api.ifindex_num = 1;
758 api.ifindex = &ifindex;
759 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
760 api.metric = info->attr->med;
761
paul0a589352004-05-08 11:48:26 +0000762 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
763 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000764 }
765#endif /* HAVE_IPV6 */
766}
767
768void
769bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
770{
771 int flags;
772 struct peer *peer;
773
774 if (zclient->sock < 0)
775 return;
776
777 if (! zclient->redist[ZEBRA_ROUTE_BGP])
778 return;
779
780 peer = info->peer;
781 flags = 0;
782
783 if (peer_sort (peer) == BGP_PEER_IBGP)
784 {
785 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
786 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
787 }
788
789 if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
790 || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
791 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
792
793 if (p->family == AF_INET)
794 {
795 struct zapi_ipv4 api;
796 struct in_addr *nexthop;
797
798 api.flags = flags;
799 nexthop = &info->attr->nexthop;
800
801 api.type = ZEBRA_ROUTE_BGP;
802 api.message = 0;
803 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
804 api.nexthop_num = 1;
805 api.nexthop = &nexthop;
806 api.ifindex_num = 0;
807 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
808 api.metric = info->attr->med;
809
paul0a589352004-05-08 11:48:26 +0000810 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
811 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000812 }
813#ifdef HAVE_IPV6
814 /* We have to think about a IPv6 link-local address curse. */
815 if (p->family == AF_INET6)
816 {
817 struct zapi_ipv6 api;
818 unsigned int ifindex;
819 struct in6_addr *nexthop;
820
821 ifindex = 0;
822 nexthop = NULL;
823
824 /* Only global address nexthop exists. */
825 if (info->attr->mp_nexthop_len == 16)
826 nexthop = &info->attr->mp_nexthop_global;
827
828 /* If both global and link-local address present. */
829 if (info->attr->mp_nexthop_len == 32)
830 {
831 nexthop = &info->attr->mp_nexthop_local;
832 if (info->peer->nexthop.ifp)
833 ifindex = info->peer->nexthop.ifp->ifindex;
834 }
835
836 if (nexthop == NULL)
837 return;
838
839 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
840 if (info->peer->ifname)
841 ifindex = if_nametoindex (info->peer->ifname);
842
843 api.flags = flags;
844 api.type = ZEBRA_ROUTE_BGP;
845 api.message = 0;
846 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
847 api.nexthop_num = 1;
848 api.nexthop = &nexthop;
849 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
850 api.ifindex_num = 1;
851 api.ifindex = &ifindex;
852 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
853 api.metric = info->attr->med;
854
paul0a589352004-05-08 11:48:26 +0000855 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
856 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000857 }
858#endif /* HAVE_IPV6 */
859}
860
861/* Other routes redistribution into BGP. */
862int
863bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
864{
865 /* Set flag to BGP instance. */
866 bgp->redist[afi][type] = 1;
867
868 /* Return if already redistribute flag is set. */
869 if (zclient->redist[type])
870 return CMD_WARNING;
871
872 zclient->redist[type] = 1;
873
874 /* Return if zebra connection is not established. */
875 if (zclient->sock < 0)
876 return CMD_WARNING;
877
878 /* Send distribute add message to zebra. */
879 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
880
881 return CMD_SUCCESS;
882}
883
884/* Redistribute with route-map specification. */
885int
886bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type, char *name)
887{
888 if (bgp->rmap[afi][type].name
889 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
890 return 0;
891
892 if (bgp->rmap[afi][type].name)
893 free (bgp->rmap[afi][type].name);
894 bgp->rmap[afi][type].name = strdup (name);
895 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
896
897 return 1;
898}
899
900/* Redistribute with metric specification. */
901int
902bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
903 u_int32_t metric)
904{
905 if (bgp->redist_metric_flag[afi][type]
906 && bgp->redist_metric[afi][type] == metric)
907 return 0;
908
909 bgp->redist_metric_flag[afi][type] = 1;
910 bgp->redist_metric[afi][type] = metric;
911
912 return 1;
913}
914
915/* Unset redistribution. */
916int
917bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
918{
919 /* Unset flag from BGP instance. */
920 bgp->redist[afi][type] = 0;
921
922 /* Unset route-map. */
923 if (bgp->rmap[afi][type].name)
924 free (bgp->rmap[afi][type].name);
925 bgp->rmap[afi][type].name = NULL;
926 bgp->rmap[afi][type].map = NULL;
927
928 /* Unset metric. */
929 bgp->redist_metric_flag[afi][type] = 0;
930 bgp->redist_metric[afi][type] = 0;
931
932 /* Return if zebra connection is disabled. */
933 if (! zclient->redist[type])
934 return CMD_WARNING;
935 zclient->redist[type] = 0;
936
937 if (bgp->redist[AFI_IP][type] == 0
938 && bgp->redist[AFI_IP6][type] == 0
939 && zclient->sock >= 0)
940 /* Send distribute delete message to zebra. */
941 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
942
943 /* Withdraw redistributed routes from current BGP's routing table. */
944 bgp_redistribute_withdraw (bgp, afi, type);
945
946 return CMD_SUCCESS;
947}
948
949/* Unset redistribution route-map configuration. */
950int
951bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
952{
953 if (! bgp->rmap[afi][type].name)
954 return 0;
955
956 /* Unset route-map. */
957 free (bgp->rmap[afi][type].name);
958 bgp->rmap[afi][type].name = NULL;
959 bgp->rmap[afi][type].map = NULL;
960
961 return 1;
962}
963
964/* Unset redistribution metric configuration. */
965int
966bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
967{
968 if (! bgp->redist_metric_flag[afi][type])
969 return 0;
970
971 /* Unset metric. */
972 bgp->redist_metric_flag[afi][type] = 0;
973 bgp->redist_metric[afi][type] = 0;
974
975 return 1;
976}
977
978void
979bgp_zclient_reset ()
980{
981 zclient_reset (zclient);
982}
983
984void
985bgp_zebra_init (int enable)
986{
987 /* Set default values. */
988 zclient = zclient_new ();
989 zclient_init (zclient, ZEBRA_ROUTE_BGP);
990 zclient->interface_add = bgp_interface_add;
991 zclient->interface_delete = bgp_interface_delete;
992 zclient->interface_address_add = bgp_interface_address_add;
993 zclient->interface_address_delete = bgp_interface_address_delete;
994 zclient->ipv4_route_add = zebra_read_ipv4;
995 zclient->ipv4_route_delete = zebra_read_ipv4;
996 zclient->interface_up = bgp_interface_up;
997 zclient->interface_down = bgp_interface_down;
998#ifdef HAVE_IPV6
999 zclient->ipv6_route_add = zebra_read_ipv6;
1000 zclient->ipv6_route_delete = zebra_read_ipv6;
1001#endif /* HAVE_IPV6 */
1002
1003 /* Interface related init. */
1004 if_init ();
1005}