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