blob: 0c0c8c0c791e38ae6d4e38d470d05870a5ed64ff [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;
paul1eb8ef22005-04-07 07:30:20 +000049 struct listnode *node, *nnode;
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
paul1eb8ef22005-04-07 07:30:20 +000055 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +000056 {
hasso18a6dce2004-10-03 18:18:34 +000057 if (!bgp->router_id_static.s_addr)
paul1eb8ef22005-04-07 07:30:20 +000058 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;
paul1eb8ef22005-04-07 07:30:20 +000095 struct listnode *node, *nnode;
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
paul1eb8ef22005-04-07 07:30:20 +0000103 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
104 bgp_connected_add (c);
paul718e3742002-12-13 20:15:29 +0000105
106 return 0;
107}
108
109int
110bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
111{
112 struct stream *s;
113 struct interface *ifp;
114 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000115 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000116
117 s = zclient->ibuf;
118 ifp = zebra_interface_state_read (s);
119 if (! ifp)
120 return 0;
121
paul1eb8ef22005-04-07 07:30:20 +0000122 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
123 bgp_connected_delete (c);
paul718e3742002-12-13 20:15:29 +0000124
125 /* Fast external-failover (Currently IPv4 only) */
126 {
paul1eb8ef22005-04-07 07:30:20 +0000127 struct listnode *mnode;
paul718e3742002-12-13 20:15:29 +0000128 struct bgp *bgp;
129 struct peer *peer;
130 struct interface *peer_if;
131
paul1eb8ef22005-04-07 07:30:20 +0000132 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
paul718e3742002-12-13 20:15:29 +0000133 {
134 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
135 continue;
136
paul1eb8ef22005-04-07 07:30:20 +0000137 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000138 {
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
156int
157bgp_interface_address_add (int command, struct zclient *zclient,
158 zebra_size_t length)
159{
160 struct connected *ifc;
161
paul0a589352004-05-08 11:48:26 +0000162 ifc = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000163
164 if (ifc == NULL)
165 return 0;
166
paul2e3b2e42002-12-13 21:03:13 +0000167 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000168 bgp_connected_add (ifc);
169
170 return 0;
171}
172
173int
174bgp_interface_address_delete (int command, struct zclient *zclient,
175 zebra_size_t length)
176{
177 struct connected *ifc;
178
paul0a589352004-05-08 11:48:26 +0000179 ifc = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000180
181 if (ifc == NULL)
182 return 0;
183
paul2e3b2e42002-12-13 21:03:13 +0000184 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000185 bgp_connected_delete (ifc);
186
187 connected_free (ifc);
188
189 return 0;
190}
191
192/* Zebra route add and delete treatment. */
193int
194zebra_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. */
245int
246zebra_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
302struct interface *
303if_lookup_by_ipv4 (struct in_addr *addr)
304{
hasso52dc7ee2004-09-23 19:18:23 +0000305 struct listnode *ifnode;
306 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000307 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
paul1eb8ef22005-04-07 07:30:20 +0000316 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000317 {
paul1eb8ef22005-04-07 07:30:20 +0000318 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000319 {
paul718e3742002-12-13 20:15:29 +0000320 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
330struct interface *
331if_lookup_by_ipv4_exact (struct in_addr *addr)
332{
hasso52dc7ee2004-09-23 19:18:23 +0000333 struct listnode *ifnode;
334 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000335 struct interface *ifp;
336 struct connected *connected;
337 struct prefix *cp;
338
paul1eb8ef22005-04-07 07:30:20 +0000339 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000340 {
paul1eb8ef22005-04-07 07:30:20 +0000341 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000342 {
paul718e3742002-12-13 20:15:29 +0000343 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
354struct interface *
355if_lookup_by_ipv6 (struct in6_addr *addr)
356{
hasso52dc7ee2004-09-23 19:18:23 +0000357 struct listnode *ifnode;
358 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000359 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
paul1eb8ef22005-04-07 07:30:20 +0000368 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000369 {
paul1eb8ef22005-04-07 07:30:20 +0000370 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000371 {
paul718e3742002-12-13 20:15:29 +0000372 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
382struct interface *
383if_lookup_by_ipv6_exact (struct in6_addr *addr)
384{
hasso52dc7ee2004-09-23 19:18:23 +0000385 struct listnode *ifnode;
386 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000387 struct interface *ifp;
388 struct connected *connected;
389 struct prefix *cp;
390
paul1eb8ef22005-04-07 07:30:20 +0000391 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000392 {
paul1eb8ef22005-04-07 07:30:20 +0000393 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000394 {
paul718e3742002-12-13 20:15:29 +0000395 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
405int
406if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
407{
hasso52dc7ee2004-09-23 19:18:23 +0000408 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000409 struct connected *connected;
410 struct prefix *cp;
411
paul1eb8ef22005-04-07 07:30:20 +0000412 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000413 {
paul718e3742002-12-13 20:15:29 +0000414 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
426int
427if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
428{
hasso52dc7ee2004-09-23 19:18:23 +0000429 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000430 struct connected *connected;
431 struct prefix *cp;
432
paul1eb8ef22005-04-07 07:30:20 +0000433 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000434 {
paul718e3742002-12-13 20:15:29 +0000435 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
448int
449bgp_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
561unsigned int
562bgp_ifindex_by_nexthop (struct in6_addr *addr)
563{
hasso52dc7ee2004-09-23 19:18:23 +0000564 struct listnode *ifnode;
565 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000566 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
paul1eb8ef22005-04-07 07:30:20 +0000574 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000575 {
paul1eb8ef22005-04-07 07:30:20 +0000576 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000577 {
578 struct prefix *cp;
579
paul718e3742002-12-13 20:15:29 +0000580 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
593void
594bgp_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)
hasso6ffd2072005-02-02 14:50:11 +0000616 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000617 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 }
paul0a589352004-05-08 11:48:26 +0000643 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
644 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000645 }
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
paul0a589352004-05-08 11:48:26 +0000699 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
700 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000701 }
702#endif /* HAVE_IPV6 */
703}
704
705void
706bgp_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)
hasso6ffd2072005-02-02 14:50:11 +0000727 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000728 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
paul0a589352004-05-08 11:48:26 +0000747 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
748 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000749 }
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
paul0a589352004-05-08 11:48:26 +0000792 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
793 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000794 }
795#endif /* HAVE_IPV6 */
796}
797
798/* Other routes redistribution into BGP. */
799int
800bgp_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->sock, type);
817
818 return CMD_SUCCESS;
819}
820
821/* Redistribute with route-map specification. */
822int
paulfd79ac92004-10-13 05:06:08 +0000823bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
824 const char *name)
paul718e3742002-12-13 20:15:29 +0000825{
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. */
839int
840bgp_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. */
854int
855bgp_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->sock, 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. */
888int
889bgp_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. */
903int
904bgp_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
916void
917bgp_zclient_reset ()
918{
919 zclient_reset (zclient);
920}
921
922void
923bgp_zebra_init (int enable)
924{
925 /* Set default values. */
926 zclient = zclient_new ();
927 zclient_init (zclient, ZEBRA_ROUTE_BGP);
hasso18a6dce2004-10-03 18:18:34 +0000928 zclient->router_id_update = bgp_router_id_update;
paul718e3742002-12-13 20:15:29 +0000929 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}