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