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