]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_zebra.c
2005-06-28 Paul Jakma <paul.jakma@sun.com>
[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 \f
40 /* All information about zebra. */
41 static struct zclient *zclient = NULL;
42 struct in_addr router_id_zebra;
43
44 /* Router-id update message from zebra. */
45 static int
46 bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
47 {
48 struct prefix router_id;
49 struct listnode *node, *nnode;
50 struct bgp *bgp;
51
52 zebra_router_id_update_read(zclient->ibuf,&router_id);
53 router_id_zebra = router_id.u.prefix4;
54
55 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
56 {
57 if (!bgp->router_id_static.s_addr)
58 bgp_router_id_set (bgp, &router_id.u.prefix4);
59 }
60
61 return 0;
62 }
63
64 /* Inteface addition message from zebra. */
65 static int
66 bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
67 {
68 struct interface *ifp;
69
70 ifp = zebra_interface_add_read (zclient->ibuf);
71
72 return 0;
73 }
74
75 static int
76 bgp_interface_delete (int command, struct zclient *zclient,
77 zebra_size_t length)
78 {
79 struct stream *s;
80 struct interface *ifp;
81
82 s = zclient->ibuf;
83 ifp = zebra_interface_state_read (s);
84 ifp->ifindex = IFINDEX_INTERNAL;
85
86 return 0;
87 }
88
89 static int
90 bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
91 {
92 struct stream *s;
93 struct interface *ifp;
94 struct connected *c;
95 struct listnode *node, *nnode;
96
97 s = zclient->ibuf;
98 ifp = zebra_interface_state_read (s);
99
100 if (! ifp)
101 return 0;
102
103 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
104 bgp_connected_add (c);
105
106 return 0;
107 }
108
109 static int
110 bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
111 {
112 struct stream *s;
113 struct interface *ifp;
114 struct connected *c;
115 struct listnode *node, *nnode;
116
117 s = zclient->ibuf;
118 ifp = zebra_interface_state_read (s);
119 if (! ifp)
120 return 0;
121
122 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
123 bgp_connected_delete (c);
124
125 /* Fast external-failover (Currently IPv4 only) */
126 {
127 struct listnode *mnode;
128 struct bgp *bgp;
129 struct peer *peer;
130 struct interface *peer_if;
131
132 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
133 {
134 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
135 continue;
136
137 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
138 {
139 if (peer->ttl != 1)
140 continue;
141
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;
146
147 if (ifp == peer_if)
148 BGP_EVENT_ADD (peer, BGP_Stop);
149 }
150 }
151 }
152
153 return 0;
154 }
155
156 static int
157 bgp_interface_address_add (int command, struct zclient *zclient,
158 zebra_size_t length)
159 {
160 struct connected *ifc;
161
162 ifc = zebra_interface_address_read (command, zclient->ibuf);
163
164 if (ifc == NULL)
165 return 0;
166
167 if (if_is_operative (ifc->ifp))
168 bgp_connected_add (ifc);
169
170 return 0;
171 }
172
173 static int
174 bgp_interface_address_delete (int command, struct zclient *zclient,
175 zebra_size_t length)
176 {
177 struct connected *ifc;
178
179 ifc = zebra_interface_address_read (command, zclient->ibuf);
180
181 if (ifc == NULL)
182 return 0;
183
184 if (if_is_operative (ifc->ifp))
185 bgp_connected_delete (ifc);
186
187 connected_free (ifc);
188
189 return 0;
190 }
191
192 /* Zebra route add and delete treatment. */
193 static int
194 zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
195 {
196 struct stream *s;
197 struct zapi_ipv4 api;
198 unsigned long ifindex;
199 struct in_addr nexthop;
200 struct prefix_ipv4 p;
201
202 s = zclient->ibuf;
203 ifindex = 0;
204 nexthop.s_addr = 0;
205
206 /* Type, flags, message. */
207 api.type = stream_getc (s);
208 api.flags = stream_getc (s);
209 api.message = stream_getc (s);
210
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));
216
217 /* Nexthop, ifindex, distance, metric. */
218 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
219 {
220 api.nexthop_num = stream_getc (s);
221 nexthop.s_addr = stream_get_ipv4 (s);
222 }
223 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
224 {
225 api.ifindex_num = stream_getc (s);
226 ifindex = stream_getl (s);
227 }
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;
234
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);
239
240 return 0;
241 }
242
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)
247 {
248 struct stream *s;
249 struct zapi_ipv6 api;
250 unsigned long ifindex;
251 struct in6_addr nexthop;
252 struct prefix_ipv6 p;
253
254 s = zclient->ibuf;
255 ifindex = 0;
256 memset (&nexthop, 0, sizeof (struct in6_addr));
257
258 /* Type, flags, message. */
259 api.type = stream_getc (s);
260 api.flags = stream_getc (s);
261 api.message = stream_getc (s);
262
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));
268
269 /* Nexthop, ifindex, distance, metric. */
270 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
271 {
272 api.nexthop_num = stream_getc (s);
273 stream_get (&nexthop, s, 16);
274 }
275 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
276 {
277 api.ifindex_num = stream_getc (s);
278 ifindex = stream_getl (s);
279 }
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;
288
289 /* Simply ignore link-local address. */
290 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
291 return 0;
292
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);
297
298 return 0;
299 }
300 #endif /* HAVE_IPV6 */
301 \f
302 struct interface *
303 if_lookup_by_ipv4 (struct in_addr *addr)
304 {
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;
311
312 p.family = AF_INET;
313 p.prefix = *addr;
314 p.prefixlen = IPV4_MAX_BITLEN;
315
316 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
317 {
318 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
319 {
320 cp = connected->address;
321
322 if (cp->family == AF_INET)
323 if (prefix_match (cp, (struct prefix *)&p))
324 return ifp;
325 }
326 }
327 return NULL;
328 }
329
330 struct interface *
331 if_lookup_by_ipv4_exact (struct in_addr *addr)
332 {
333 struct listnode *ifnode;
334 struct listnode *cnode;
335 struct interface *ifp;
336 struct connected *connected;
337 struct prefix *cp;
338
339 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
340 {
341 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
342 {
343 cp = connected->address;
344
345 if (cp->family == AF_INET)
346 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
347 return ifp;
348 }
349 }
350 return NULL;
351 }
352
353 #ifdef HAVE_IPV6
354 struct interface *
355 if_lookup_by_ipv6 (struct in6_addr *addr)
356 {
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;
363
364 p.family = AF_INET6;
365 p.prefix = *addr;
366 p.prefixlen = IPV6_MAX_BITLEN;
367
368 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
369 {
370 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
371 {
372 cp = connected->address;
373
374 if (cp->family == AF_INET6)
375 if (prefix_match (cp, (struct prefix *)&p))
376 return ifp;
377 }
378 }
379 return NULL;
380 }
381
382 struct interface *
383 if_lookup_by_ipv6_exact (struct in6_addr *addr)
384 {
385 struct listnode *ifnode;
386 struct listnode *cnode;
387 struct interface *ifp;
388 struct connected *connected;
389 struct prefix *cp;
390
391 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
392 {
393 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
394 {
395 cp = connected->address;
396
397 if (cp->family == AF_INET6)
398 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
399 return ifp;
400 }
401 }
402 return NULL;
403 }
404
405 static int
406 if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
407 {
408 struct listnode *cnode;
409 struct connected *connected;
410 struct prefix *cp;
411
412 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
413 {
414 cp = connected->address;
415
416 if (cp->family == AF_INET6)
417 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
418 {
419 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
420 return 1;
421 }
422 }
423 return 0;
424 }
425
426 static int
427 if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
428 {
429 struct listnode *cnode;
430 struct connected *connected;
431 struct prefix *cp;
432
433 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
434 {
435 cp = connected->address;
436
437 if (cp->family == AF_INET6)
438 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
439 {
440 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
441 return 1;
442 }
443 }
444 return 0;
445 }
446 #endif /* HAVE_IPV6 */
447
448 int
449 bgp_nexthop_set (union sockunion *local, union sockunion *remote,
450 struct bgp_nexthop *nexthop, struct peer *peer)
451 {
452 int ret = 0;
453 struct interface *ifp = NULL;
454
455 memset (nexthop, 0, sizeof (struct bgp_nexthop));
456
457 if (!local)
458 return -1;
459 if (!remote)
460 return -1;
461
462 if (local->sa.sa_family == AF_INET)
463 {
464 nexthop->v4 = local->sin.sin_addr;
465 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
466 }
467 #ifdef HAVE_IPV6
468 if (local->sa.sa_family == AF_INET6)
469 {
470 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
471 {
472 if (peer->ifname)
473 ifp = if_lookup_by_index (if_nametoindex (peer->ifname));
474 }
475 else
476 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
477 }
478 #endif /* HAVE_IPV6 */
479
480 if (!ifp)
481 return -1;
482
483 nexthop->ifp = ifp;
484
485 /* IPv4 connection. */
486 if (local->sa.sa_family == AF_INET)
487 {
488 #ifdef HAVE_IPV6
489 /* IPv6 nexthop*/
490 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
491
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 */
498 }
499
500 #ifdef HAVE_IPV6
501 /* IPv6 connection. */
502 if (local->sa.sa_family == AF_INET6)
503 {
504 struct interface *direct = NULL;
505
506 /* IPv4 nexthop. I don't care about it. */
507 if (peer->local_id.s_addr)
508 nexthop->v4 = peer->local_id;
509
510 /* Global address*/
511 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
512 {
513 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
514 IPV6_MAX_BYTELEN);
515
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);
520 }
521 else
522 /* Link-local address. */
523 {
524 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
525
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);
534 }
535 }
536
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;
542
543 /* KAME stack specific treatment. */
544 #ifdef KAME
545 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
546 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
547 {
548 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
549 }
550 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
551 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
552 {
553 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
554 }
555 #endif /* KAME */
556 #endif /* HAVE_IPV6 */
557 return ret;
558 }
559
560 #ifdef HAVE_IPV6
561 static unsigned int
562 bgp_ifindex_by_nexthop (struct in6_addr *addr)
563 {
564 struct listnode *ifnode;
565 struct listnode *cnode;
566 struct interface *ifp;
567 struct connected *connected;
568 struct prefix_ipv6 p;
569
570 p.family = AF_INET6;
571 p.prefix = *addr;
572 p.prefixlen = IPV6_MAX_BITLEN;
573
574 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
575 {
576 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
577 {
578 struct prefix *cp;
579
580 cp = connected->address;
581
582 if (cp->family == AF_INET6)
583 {
584 if (prefix_match (cp, (struct prefix *)&p))
585 return ifp->ifindex;
586 }
587 }
588 }
589 return 0;
590 }
591 #endif /* HAVE_IPV6 */
592
593 void
594 bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
595 {
596 int flags;
597 u_char distance;
598 struct peer *peer;
599
600 if (zclient->sock < 0)
601 return;
602
603 if (! zclient->redist[ZEBRA_ROUTE_BGP])
604 return;
605
606 flags = 0;
607 peer = info->peer;
608
609 if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED)
610 {
611 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
612 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
613 }
614
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);
618
619 if (p->family == AF_INET)
620 {
621 struct zapi_ipv4 api;
622 struct in_addr *nexthop;
623
624 api.flags = flags;
625 nexthop = &info->attr->nexthop;
626
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;
635
636 distance = bgp_distance_apply (p, info, bgp);
637
638 if (distance)
639 {
640 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
641 api.distance = distance;
642 }
643 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
644 (struct prefix_ipv4 *) p, &api);
645 }
646 #ifdef HAVE_IPV6
647 /* We have to think about a IPv6 link-local address curse. */
648 if (p->family == AF_INET6)
649 {
650 unsigned int ifindex;
651 struct in6_addr *nexthop;
652 struct zapi_ipv6 api;
653
654 ifindex = 0;
655 nexthop = NULL;
656
657 /* Only global address nexthop exists. */
658 if (info->attr->mp_nexthop_len == 16)
659 nexthop = &info->attr->mp_nexthop_global;
660
661 /* If both global and link-local address present. */
662 if (info->attr->mp_nexthop_len == 32)
663 {
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;
670
671 if (info->peer->nexthop.ifp)
672 ifindex = info->peer->nexthop.ifp->ifindex;
673 }
674
675 if (nexthop == NULL)
676 return;
677
678 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
679 {
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;
684 }
685
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;
698
699 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
700 (struct prefix_ipv6 *) p, &api);
701 }
702 #endif /* HAVE_IPV6 */
703 }
704
705 void
706 bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
707 {
708 int flags;
709 struct peer *peer;
710
711 if (zclient->sock < 0)
712 return;
713
714 if (! zclient->redist[ZEBRA_ROUTE_BGP])
715 return;
716
717 peer = info->peer;
718 flags = 0;
719
720 if (peer_sort (peer) == BGP_PEER_IBGP)
721 {
722 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
723 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
724 }
725
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);
729
730 if (p->family == AF_INET)
731 {
732 struct zapi_ipv4 api;
733 struct in_addr *nexthop;
734
735 api.flags = flags;
736 nexthop = &info->attr->nexthop;
737
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;
746
747 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
748 (struct prefix_ipv4 *) p, &api);
749 }
750 #ifdef HAVE_IPV6
751 /* We have to think about a IPv6 link-local address curse. */
752 if (p->family == AF_INET6)
753 {
754 struct zapi_ipv6 api;
755 unsigned int ifindex;
756 struct in6_addr *nexthop;
757
758 ifindex = 0;
759 nexthop = NULL;
760
761 /* Only global address nexthop exists. */
762 if (info->attr->mp_nexthop_len == 16)
763 nexthop = &info->attr->mp_nexthop_global;
764
765 /* If both global and link-local address present. */
766 if (info->attr->mp_nexthop_len == 32)
767 {
768 nexthop = &info->attr->mp_nexthop_local;
769 if (info->peer->nexthop.ifp)
770 ifindex = info->peer->nexthop.ifp->ifindex;
771 }
772
773 if (nexthop == NULL)
774 return;
775
776 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
777 if (info->peer->ifname)
778 ifindex = if_nametoindex (info->peer->ifname);
779
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;
791
792 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
793 (struct prefix_ipv6 *) p, &api);
794 }
795 #endif /* HAVE_IPV6 */
796 }
797 \f
798 /* Other routes redistribution into BGP. */
799 int
800 bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
801 {
802 /* Set flag to BGP instance. */
803 bgp->redist[afi][type] = 1;
804
805 /* Return if already redistribute flag is set. */
806 if (zclient->redist[type])
807 return CMD_WARNING;
808
809 zclient->redist[type] = 1;
810
811 /* Return if zebra connection is not established. */
812 if (zclient->sock < 0)
813 return CMD_WARNING;
814
815 /* Send distribute add message to zebra. */
816 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
817
818 return CMD_SUCCESS;
819 }
820
821 /* Redistribute with route-map specification. */
822 int
823 bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
824 const char *name)
825 {
826 if (bgp->rmap[afi][type].name
827 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
828 return 0;
829
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);
834
835 return 1;
836 }
837
838 /* Redistribute with metric specification. */
839 int
840 bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
841 u_int32_t metric)
842 {
843 if (bgp->redist_metric_flag[afi][type]
844 && bgp->redist_metric[afi][type] == metric)
845 return 0;
846
847 bgp->redist_metric_flag[afi][type] = 1;
848 bgp->redist_metric[afi][type] = metric;
849
850 return 1;
851 }
852
853 /* Unset redistribution. */
854 int
855 bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
856 {
857 /* Unset flag from BGP instance. */
858 bgp->redist[afi][type] = 0;
859
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;
865
866 /* Unset metric. */
867 bgp->redist_metric_flag[afi][type] = 0;
868 bgp->redist_metric[afi][type] = 0;
869
870 /* Return if zebra connection is disabled. */
871 if (! zclient->redist[type])
872 return CMD_WARNING;
873 zclient->redist[type] = 0;
874
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);
880
881 /* Withdraw redistributed routes from current BGP's routing table. */
882 bgp_redistribute_withdraw (bgp, afi, type);
883
884 return CMD_SUCCESS;
885 }
886
887 /* Unset redistribution route-map configuration. */
888 int
889 bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
890 {
891 if (! bgp->rmap[afi][type].name)
892 return 0;
893
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;
898
899 return 1;
900 }
901
902 /* Unset redistribution metric configuration. */
903 int
904 bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
905 {
906 if (! bgp->redist_metric_flag[afi][type])
907 return 0;
908
909 /* Unset metric. */
910 bgp->redist_metric_flag[afi][type] = 0;
911 bgp->redist_metric[afi][type] = 0;
912
913 return 1;
914 }
915 \f
916 void
917 bgp_zclient_reset (void)
918 {
919 zclient_reset (zclient);
920 }
921
922 void
923 bgp_zebra_init (void)
924 {
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 */
941
942 /* Interface related init. */
943 if_init ();
944 }