blob: 176e447a376f11a1580101179b4f01225486c250 [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;
hasso18a6dce2004-10-03 18:18:34 +000042struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000043
hasso18a6dce2004-10-03 18:18:34 +000044/* Router-id update message from zebra. */
paul718e3742002-12-13 20:15:29 +000045int
hasso18a6dce2004-10-03 18:18:34 +000046bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
paul718e3742002-12-13 20:15:29 +000047{
hasso18a6dce2004-10-03 18:18:34 +000048 struct prefix router_id;
paul718e3742002-12-13 20:15:29 +000049 struct listnode *nn;
hasso18a6dce2004-10-03 18:18:34 +000050 struct bgp *bgp;
paul718e3742002-12-13 20:15:29 +000051
hasso18a6dce2004-10-03 18:18:34 +000052 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)
paul718e3742002-12-13 20:15:29 +000056 {
hasso18a6dce2004-10-03 18:18:34 +000057 if (!bgp->router_id_static.s_addr)
58 bgp_router_id_set (bgp, &router_id.u.prefix4);
paul718e3742002-12-13 20:15:29 +000059 }
paul718e3742002-12-13 20:15:29 +000060
paul718e3742002-12-13 20:15:29 +000061 return 0;
62}
63
64/* Inteface addition message from zebra. */
65int
66bgp_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);
paul718e3742002-12-13 20:15:29 +000071
72 return 0;
73}
74
75int
76bgp_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);
ajsd2fc8892005-04-02 18:38:43 +000084 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +000085
86 return 0;
87}
88
89int
90bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
91{
92 struct stream *s;
93 struct interface *ifp;
94 struct connected *c;
hasso52dc7ee2004-09-23 19:18:23 +000095 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000096
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
112int
113bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
114{
115 struct stream *s;
116 struct interface *ifp;
117 struct connected *c;
hasso52dc7ee2004-09-23 19:18:23 +0000118 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000119
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
162int
163bgp_interface_address_add (int command, struct zclient *zclient,
164 zebra_size_t length)
165{
166 struct connected *ifc;
167
paul0a589352004-05-08 11:48:26 +0000168 ifc = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000169
170 if (ifc == NULL)
171 return 0;
172
paul2e3b2e42002-12-13 21:03:13 +0000173 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000174 bgp_connected_add (ifc);
175
176 return 0;
177}
178
179int
180bgp_interface_address_delete (int command, struct zclient *zclient,
181 zebra_size_t length)
182{
183 struct connected *ifc;
184
paul0a589352004-05-08 11:48:26 +0000185 ifc = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000186
187 if (ifc == NULL)
188 return 0;
189
paul2e3b2e42002-12-13 21:03:13 +0000190 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000191 bgp_connected_delete (ifc);
192
193 connected_free (ifc);
194
195 return 0;
196}
197
198/* Zebra route add and delete treatment. */
199int
200zebra_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. */
251int
252zebra_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
308struct interface *
309if_lookup_by_ipv4 (struct in_addr *addr)
310{
hasso52dc7ee2004-09-23 19:18:23 +0000311 struct listnode *ifnode;
312 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000313 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
339struct interface *
340if_lookup_by_ipv4_exact (struct in_addr *addr)
341{
hasso52dc7ee2004-09-23 19:18:23 +0000342 struct listnode *ifnode;
343 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000344 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
366struct interface *
367if_lookup_by_ipv6 (struct in6_addr *addr)
368{
hasso52dc7ee2004-09-23 19:18:23 +0000369 struct listnode *ifnode;
370 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000371 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
397struct interface *
398if_lookup_by_ipv6_exact (struct in6_addr *addr)
399{
hasso52dc7ee2004-09-23 19:18:23 +0000400 struct listnode *ifnode;
401 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000402 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
423int
424if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
425{
hasso52dc7ee2004-09-23 19:18:23 +0000426 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000427 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
445int
446if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
447{
hasso52dc7ee2004-09-23 19:18:23 +0000448 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000449 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
468int
469bgp_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
581unsigned int
582bgp_ifindex_by_nexthop (struct in6_addr *addr)
583{
hasso52dc7ee2004-09-23 19:18:23 +0000584 struct listnode *ifnode;
585 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000586 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
616void
617bgp_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)
hasso6ffd2072005-02-02 14:50:11 +0000639 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000640 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 }
paul0a589352004-05-08 11:48:26 +0000666 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
667 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000668 }
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
paul0a589352004-05-08 11:48:26 +0000722 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
723 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000724 }
725#endif /* HAVE_IPV6 */
726}
727
728void
729bgp_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)
hasso6ffd2072005-02-02 14:50:11 +0000750 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000751 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
paul0a589352004-05-08 11:48:26 +0000770 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
771 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000772 }
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
paul0a589352004-05-08 11:48:26 +0000815 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
816 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000817 }
818#endif /* HAVE_IPV6 */
819}
820
821/* Other routes redistribution into BGP. */
822int
823bgp_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. */
845int
paulfd79ac92004-10-13 05:06:08 +0000846bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
847 const char *name)
paul718e3742002-12-13 20:15:29 +0000848{
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. */
862int
863bgp_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. */
877int
878bgp_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. */
911int
912bgp_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. */
926int
927bgp_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
939void
940bgp_zclient_reset ()
941{
942 zclient_reset (zclient);
943}
944
945void
946bgp_zebra_init (int enable)
947{
948 /* Set default values. */
949 zclient = zclient_new ();
950 zclient_init (zclient, ZEBRA_ROUTE_BGP);
hasso18a6dce2004-10-03 18:18:34 +0000951 zclient->router_id_update = bgp_router_id_update;
paul718e3742002-12-13 20:15:29 +0000952 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}