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