]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_zebra.c
Save the last message from a peer that caused us to send a NOTIFICATION
[mirror_frr.git] / bgpd / bgp_zebra.c
1 /* zebra client
2 Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3
4 This file is part of GNU Zebra.
5
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, 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 #include "bgpd/bgp_debug.h"
40 #include "bgpd/bgp_mpath.h"
41 #include "bgpd/bgp_nexthop.h"
42
43 /* All information about zebra. */
44 struct zclient *zclient = NULL;
45 struct in_addr router_id_zebra;
46
47 /* Growable buffer for nexthops sent to zebra */
48 struct stream *bgp_nexthop_buf = NULL;
49 struct stream *bgp_ifindices_buf = NULL;
50
51 /* These array buffers are used in making a copy of the attributes for
52 route-map apply. Arrays are being used here to minimize mallocs and
53 frees for the temporary copy of the attributes.
54 Given the zapi api expects the nexthop buffer to contain pointer to
55 pointers for nexthops, we couldnt have used a single nexthop variable
56 on the stack, hence we had two options:
57 1. maintain a linked-list and free it after zapi_*_route call
58 2. use an array to avoid number of mallocs.
59 Number of supported next-hops are finite, use of arrays should be ok. */
60 struct attr attr_cp[BGP_MAXIMUM_MAXPATHS];
61 struct attr_extra attr_extra_cp[BGP_MAXIMUM_MAXPATHS];
62 int attr_index = 0;
63
64 /* Once per address-family initialization of the attribute array */
65 #define BGP_INFO_ATTR_BUF_INIT()\
66 do {\
67 memset(attr_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr));\
68 memset(attr_extra_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr_extra));\
69 attr_index = 0;\
70 } while (0)
71
72 #define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\
73 do { \
74 *info_dst = *info_src; \
75 assert(attr_index != BGP_MAXIMUM_MAXPATHS);\
76 attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \
77 bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \
78 bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \
79 info_dst->attr = &attr_cp[attr_index]; \
80 attr_index++;\
81 } while (0)
82
83 #define BGP_INFO_ATTR_BUF_FREE(info) \
84 do { \
85 bgp_attr_deep_free(info->attr); \
86 } while (0)
87
88 /* Router-id update message from zebra. */
89 static int
90 bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
91 {
92 struct prefix router_id;
93 struct listnode *node, *nnode;
94 struct bgp *bgp;
95
96 zebra_router_id_update_read(zclient->ibuf,&router_id);
97
98 if (BGP_DEBUG(zebra, ZEBRA))
99 {
100 char buf[128];
101 prefix2str(&router_id, buf, sizeof(buf));
102 zlog_debug("Zebra rcvd: router id update %s", buf);
103 }
104
105 router_id_zebra = router_id.u.prefix4;
106
107 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
108 {
109 if (!bgp->router_id_static.s_addr)
110 bgp_router_id_set (bgp, &router_id.u.prefix4);
111 }
112
113 return 0;
114 }
115
116 /* Nexthop update message from zebra. */
117 static int
118 bgp_read_nexthop_update (int command, struct zclient *zclient,
119 zebra_size_t length)
120 {
121 bgp_parse_nexthop_update();
122 return 0;
123 }
124
125 /* Inteface addition message from zebra. */
126 static int
127 bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
128 {
129 struct interface *ifp;
130
131 ifp = zebra_interface_add_read (zclient->ibuf);
132
133 if (BGP_DEBUG(zebra, ZEBRA) && ifp)
134 zlog_debug("Zebra rcvd: interface add %s", ifp->name);
135
136 return 0;
137 }
138
139 static int
140 bgp_interface_delete (int command, struct zclient *zclient,
141 zebra_size_t length)
142 {
143 struct stream *s;
144 struct interface *ifp;
145
146 s = zclient->ibuf;
147 ifp = zebra_interface_state_read (s);
148 ifp->ifindex = IFINDEX_INTERNAL;
149
150 if (BGP_DEBUG(zebra, ZEBRA))
151 zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
152
153 return 0;
154 }
155
156 static int
157 bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
158 {
159 struct stream *s;
160 struct interface *ifp;
161 struct connected *c;
162 struct listnode *node, *nnode;
163
164 s = zclient->ibuf;
165 ifp = zebra_interface_state_read (s);
166
167 if (! ifp)
168 return 0;
169
170 if (BGP_DEBUG(zebra, ZEBRA))
171 zlog_debug("Zebra rcvd: interface %s up", ifp->name);
172
173 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
174 bgp_connected_add (c);
175
176 return 0;
177 }
178
179 static int
180 bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
181 {
182 struct stream *s;
183 struct interface *ifp;
184 struct connected *c;
185 struct listnode *node, *nnode;
186
187 s = zclient->ibuf;
188 ifp = zebra_interface_state_read (s);
189 if (! ifp)
190 return 0;
191
192 if (BGP_DEBUG(zebra, ZEBRA))
193 zlog_debug("Zebra rcvd: interface %s down", ifp->name);
194
195 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
196 bgp_connected_delete (c);
197
198 /* Fast external-failover */
199 {
200 struct listnode *mnode;
201 struct bgp *bgp;
202 struct peer *peer;
203
204 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
205 {
206 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
207 continue;
208
209 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
210 {
211 if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
212 continue;
213
214 if (ifp == peer->nexthop.ifp)
215 BGP_EVENT_ADD (peer, BGP_Stop);
216 }
217 }
218 }
219
220 return 0;
221 }
222
223 static int
224 bgp_interface_address_add (int command, struct zclient *zclient,
225 zebra_size_t length)
226 {
227 struct connected *ifc;
228
229 ifc = zebra_interface_address_read (command, zclient->ibuf);
230
231 if (ifc == NULL)
232 return 0;
233
234 if (BGP_DEBUG(zebra, ZEBRA))
235 {
236 char buf[128];
237 prefix2str(ifc->address, buf, sizeof(buf));
238 zlog_debug("Zebra rcvd: interface %s address add %s",
239 ifc->ifp->name, buf);
240 }
241
242 if (if_is_operative (ifc->ifp))
243 bgp_connected_add (ifc);
244
245 return 0;
246 }
247
248 static int
249 bgp_interface_address_delete (int command, struct zclient *zclient,
250 zebra_size_t length)
251 {
252 struct connected *ifc;
253
254 ifc = zebra_interface_address_read (command, zclient->ibuf);
255
256 if (ifc == NULL)
257 return 0;
258
259 if (BGP_DEBUG(zebra, ZEBRA))
260 {
261 char buf[128];
262 prefix2str(ifc->address, buf, sizeof(buf));
263 zlog_debug("Zebra rcvd: interface %s address delete %s",
264 ifc->ifp->name, buf);
265 }
266
267 if (if_is_operative (ifc->ifp))
268 bgp_connected_delete (ifc);
269
270 connected_free (ifc);
271
272 return 0;
273 }
274
275 /* Zebra route add and delete treatment. */
276 static int
277 zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
278 {
279 struct stream *s;
280 struct zapi_ipv4 api;
281 struct in_addr nexthop;
282 struct prefix_ipv4 p;
283
284 s = zclient->ibuf;
285 nexthop.s_addr = 0;
286
287 /* Type, flags, message. */
288 api.type = stream_getc (s);
289 api.flags = stream_getc (s);
290 api.message = stream_getc (s);
291
292 /* IPv4 prefix. */
293 memset (&p, 0, sizeof (struct prefix_ipv4));
294 p.family = AF_INET;
295 p.prefixlen = stream_getc (s);
296 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
297
298 /* Nexthop, ifindex, distance, metric. */
299 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
300 {
301 api.nexthop_num = stream_getc (s);
302 nexthop.s_addr = stream_get_ipv4 (s);
303 }
304 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
305 {
306 api.ifindex_num = stream_getc (s);
307 stream_getl (s); /* ifindex, unused */
308 }
309 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
310 api.distance = stream_getc (s);
311 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
312 api.metric = stream_getl (s);
313 else
314 api.metric = 0;
315
316 if (command == ZEBRA_IPV4_ROUTE_ADD)
317 {
318 if (BGP_DEBUG(zebra, ZEBRA))
319 {
320 char buf[2][INET_ADDRSTRLEN];
321 zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
322 zebra_route_string(api.type),
323 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
324 p.prefixlen,
325 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
326 api.metric);
327 }
328 bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
329 api.metric, api.type);
330 }
331 else
332 {
333 if (BGP_DEBUG(zebra, ZEBRA))
334 {
335 char buf[2][INET_ADDRSTRLEN];
336 zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
337 "nexthop %s metric %u",
338 zebra_route_string(api.type),
339 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
340 p.prefixlen,
341 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
342 api.metric);
343 }
344 bgp_redistribute_delete((struct prefix *)&p, api.type);
345 }
346
347 return 0;
348 }
349
350 #ifdef HAVE_IPV6
351 /* Zebra route add and delete treatment. */
352 static int
353 zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
354 {
355 struct stream *s;
356 struct zapi_ipv6 api;
357 struct in6_addr nexthop;
358 struct prefix_ipv6 p;
359
360 s = zclient->ibuf;
361 memset (&nexthop, 0, sizeof (struct in6_addr));
362
363 /* Type, flags, message. */
364 api.type = stream_getc (s);
365 api.flags = stream_getc (s);
366 api.message = stream_getc (s);
367
368 /* IPv6 prefix. */
369 memset (&p, 0, sizeof (struct prefix_ipv6));
370 p.family = AF_INET6;
371 p.prefixlen = stream_getc (s);
372 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
373
374 /* Nexthop, ifindex, distance, metric. */
375 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
376 {
377 api.nexthop_num = stream_getc (s);
378 stream_get (&nexthop, s, 16);
379 }
380 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
381 {
382 api.ifindex_num = stream_getc (s);
383 stream_getl (s); /* ifindex, unused */
384 }
385 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
386 api.distance = stream_getc (s);
387 else
388 api.distance = 0;
389 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
390 api.metric = stream_getl (s);
391 else
392 api.metric = 0;
393
394 /* Simply ignore link-local address. */
395 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
396 return 0;
397
398 if (command == ZEBRA_IPV6_ROUTE_ADD)
399 {
400 if (BGP_DEBUG(zebra, ZEBRA))
401 {
402 char buf[2][INET6_ADDRSTRLEN];
403 zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
404 zebra_route_string(api.type),
405 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
406 p.prefixlen,
407 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
408 api.metric);
409 }
410 bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
411 api.metric, api.type);
412 }
413 else
414 {
415 if (BGP_DEBUG(zebra, ZEBRA))
416 {
417 char buf[2][INET6_ADDRSTRLEN];
418 zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
419 "nexthop %s metric %u",
420 zebra_route_string(api.type),
421 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
422 p.prefixlen,
423 inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
424 api.metric);
425 }
426 bgp_redistribute_delete ((struct prefix *) &p, api.type);
427 }
428
429 return 0;
430 }
431 #endif /* HAVE_IPV6 */
432
433 struct interface *
434 if_lookup_by_ipv4 (struct in_addr *addr)
435 {
436 struct listnode *ifnode;
437 struct listnode *cnode;
438 struct interface *ifp;
439 struct connected *connected;
440 struct prefix_ipv4 p;
441 struct prefix *cp;
442
443 p.family = AF_INET;
444 p.prefix = *addr;
445 p.prefixlen = IPV4_MAX_BITLEN;
446
447 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
448 {
449 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
450 {
451 cp = connected->address;
452
453 if (cp->family == AF_INET)
454 if (prefix_match (cp, (struct prefix *)&p))
455 return ifp;
456 }
457 }
458 return NULL;
459 }
460
461 struct interface *
462 if_lookup_by_ipv4_exact (struct in_addr *addr)
463 {
464 struct listnode *ifnode;
465 struct listnode *cnode;
466 struct interface *ifp;
467 struct connected *connected;
468 struct prefix *cp;
469
470 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
471 {
472 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
473 {
474 cp = connected->address;
475
476 if (cp->family == AF_INET)
477 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
478 return ifp;
479 }
480 }
481 return NULL;
482 }
483
484 #ifdef HAVE_IPV6
485 struct interface *
486 if_lookup_by_ipv6 (struct in6_addr *addr)
487 {
488 struct listnode *ifnode;
489 struct listnode *cnode;
490 struct interface *ifp;
491 struct connected *connected;
492 struct prefix_ipv6 p;
493 struct prefix *cp;
494
495 p.family = AF_INET6;
496 p.prefix = *addr;
497 p.prefixlen = IPV6_MAX_BITLEN;
498
499 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
500 {
501 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
502 {
503 cp = connected->address;
504
505 if (cp->family == AF_INET6)
506 if (prefix_match (cp, (struct prefix *)&p))
507 return ifp;
508 }
509 }
510 return NULL;
511 }
512
513 struct interface *
514 if_lookup_by_ipv6_exact (struct in6_addr *addr)
515 {
516 struct listnode *ifnode;
517 struct listnode *cnode;
518 struct interface *ifp;
519 struct connected *connected;
520 struct prefix *cp;
521
522 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
523 {
524 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
525 {
526 cp = connected->address;
527
528 if (cp->family == AF_INET6)
529 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
530 return ifp;
531 }
532 }
533 return NULL;
534 }
535
536 static int
537 if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
538 {
539 struct listnode *cnode;
540 struct connected *connected;
541 struct prefix *cp;
542
543 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
544 {
545 cp = connected->address;
546
547 if (cp->family == AF_INET6)
548 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
549 {
550 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
551 return 1;
552 }
553 }
554 return 0;
555 }
556
557 static int
558 if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
559 {
560 struct listnode *cnode;
561 struct connected *connected;
562 struct prefix *cp;
563
564 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
565 {
566 cp = connected->address;
567
568 if (cp->family == AF_INET6)
569 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
570 {
571 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
572 return 1;
573 }
574 }
575 return 0;
576 }
577 #endif /* HAVE_IPV6 */
578
579 static int
580 if_get_ipv4_address (struct interface *ifp, struct in_addr *addr)
581 {
582 struct listnode *cnode;
583 struct connected *connected;
584 struct prefix *cp;
585
586 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
587 {
588 cp = connected->address;
589 if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4)))
590 {
591 *addr = cp->u.prefix4;
592 return 1;
593 }
594 }
595 return 0;
596 }
597
598 int
599 bgp_nexthop_set (union sockunion *local, union sockunion *remote,
600 struct bgp_nexthop *nexthop, struct peer *peer)
601 {
602 int ret = 0;
603 struct interface *ifp = NULL;
604
605 memset (nexthop, 0, sizeof (struct bgp_nexthop));
606
607 if (!local)
608 return -1;
609 if (!remote)
610 return -1;
611
612 if (local->sa.sa_family == AF_INET)
613 {
614 nexthop->v4 = local->sin.sin_addr;
615 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
616 }
617 #ifdef HAVE_IPV6
618 if (local->sa.sa_family == AF_INET6)
619 {
620 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
621 {
622 if (peer->ifname)
623 ifp = if_lookup_by_index (if_nametoindex (peer->ifname));
624 }
625 else
626 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
627 }
628 #endif /* HAVE_IPV6 */
629
630 if (!ifp)
631 return -1;
632
633 nexthop->ifp = ifp;
634
635 /* IPv4 connection. */
636 if (local->sa.sa_family == AF_INET)
637 {
638 #ifdef HAVE_IPV6
639 /* IPv6 nexthop*/
640 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
641
642 /* There is no global nexthop. */
643 if (!ret)
644 if_get_ipv6_local (ifp, &nexthop->v6_global);
645 else
646 if_get_ipv6_local (ifp, &nexthop->v6_local);
647 #endif /* HAVE_IPV6 */
648 }
649
650 #ifdef HAVE_IPV6
651 /* IPv6 connection. */
652 if (local->sa.sa_family == AF_INET6)
653 {
654 struct interface *direct = NULL;
655
656 /* IPv4 nexthop. */
657 ret = if_get_ipv4_address(ifp, &nexthop->v4);
658 if (!ret && peer->local_id.s_addr)
659 nexthop->v4 = peer->local_id;
660
661 /* Global address*/
662 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
663 {
664 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
665 IPV6_MAX_BYTELEN);
666
667 /* If directory connected set link-local address. */
668 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
669 if (direct)
670 if_get_ipv6_local (ifp, &nexthop->v6_local);
671 }
672 else
673 /* Link-local address. */
674 {
675 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
676
677 /* If there is no global address. Set link-local address as
678 global. I know this break RFC specification... */
679 if (!ret)
680 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
681 IPV6_MAX_BYTELEN);
682 else
683 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
684 IPV6_MAX_BYTELEN);
685 }
686 }
687
688 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
689 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
690 peer->shared_network = 1;
691 else
692 peer->shared_network = 0;
693
694 /* KAME stack specific treatment. */
695 #ifdef KAME
696 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
697 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
698 {
699 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
700 }
701 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
702 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
703 {
704 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
705 }
706 #endif /* KAME */
707 #endif /* HAVE_IPV6 */
708 return ret;
709 }
710
711 static struct in6_addr *
712 bgp_info_to_ipv6_nexthop (struct bgp_info *info)
713 {
714 struct in6_addr *nexthop = NULL;
715
716 /* Only global address nexthop exists. */
717 if (info->attr->extra->mp_nexthop_len == 16)
718 nexthop = &info->attr->extra->mp_nexthop_global;
719
720 /* If both global and link-local address present. */
721 if (info->attr->extra->mp_nexthop_len == 32)
722 {
723 /* Workaround for Cisco's nexthop bug. */
724 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
725 && info->peer->su_remote->sa.sa_family == AF_INET6)
726 nexthop = &info->peer->su_remote->sin6.sin6_addr;
727 else
728 nexthop = &info->attr->extra->mp_nexthop_local;
729 }
730
731 return nexthop;
732 }
733
734 static int
735 bgp_table_map_apply (struct route_map *map, struct prefix *p,
736 struct bgp_info *info)
737 {
738 if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH)
739 return 1;
740
741 if (BGP_DEBUG(zebra, ZEBRA))
742 {
743 if (p->family == AF_INET)
744 {
745 char buf[2][INET_ADDRSTRLEN];
746 zlog_debug("Zebra rmap deny: IPv4 route %s/%d nexthop %s",
747 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
748 p->prefixlen,
749 inet_ntop(AF_INET, &info->attr->nexthop, buf[1],
750 sizeof(buf[1])));
751 }
752 if (p->family == AF_INET6)
753 {
754 char buf[2][INET6_ADDRSTRLEN];
755 zlog_debug("Zebra rmap deny: IPv6 route %s/%d nexthop %s",
756 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
757 p->prefixlen,
758 inet_ntop(AF_INET6, bgp_info_to_ipv6_nexthop(info), buf[1],
759 sizeof(buf[1])));
760 }
761 }
762 return 0;
763 }
764
765 void
766 bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
767 afi_t afi, safi_t safi)
768 {
769 int flags;
770 u_char distance;
771 struct peer *peer;
772 struct bgp_info *mpinfo;
773 size_t oldsize, newsize;
774 u_int32_t nhcount, metric;
775 struct bgp_info local_info;
776 struct bgp_info *info_cp = &local_info;
777
778 if (zclient->sock < 0)
779 return;
780
781 if (! zclient->redist[ZEBRA_ROUTE_BGP])
782 return;
783
784 flags = 0;
785 peer = info->peer;
786
787 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
788 {
789 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
790 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
791 }
792
793 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
794 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
795 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
796
797 nhcount = 1 + bgp_info_mpath_count (info);
798
799 if (p->family == AF_INET)
800 {
801 struct zapi_ipv4 api;
802 struct in_addr *nexthop;
803 char buf[2][INET_ADDRSTRLEN];
804 int valid_nh_count = 0;
805
806 /* resize nexthop buffer size if necessary */
807 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
808 (sizeof (struct in_addr *) * nhcount))
809 {
810 newsize = (sizeof (struct in_addr *) * nhcount);
811 newsize = stream_resize (bgp_nexthop_buf, newsize);
812 if (newsize == oldsize)
813 {
814 zlog_err ("can't resize nexthop buffer");
815 return;
816 }
817 }
818 stream_reset (bgp_nexthop_buf);
819 nexthop = NULL;
820
821 /* Metric is currently based on the best-path only. */
822 metric = info->attr->med;
823
824 if (bgp->table_map[afi][safi].name)
825 {
826 BGP_INFO_ATTR_BUF_INIT();
827
828 /* Copy info and attributes, so the route-map apply doesn't modify the
829 BGP route info. */
830 BGP_INFO_ATTR_BUF_COPY(info, info_cp);
831 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
832 {
833 metric = info_cp->attr->med;
834 nexthop = &info_cp->attr->nexthop;
835 }
836 BGP_INFO_ATTR_BUF_FREE(info_cp);
837 }
838 else
839 {
840 nexthop = &info->attr->nexthop;
841 }
842
843 if (nexthop)
844 {
845 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
846 valid_nh_count++;
847 }
848
849 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
850 mpinfo = bgp_info_mpath_next (mpinfo))
851 {
852 nexthop = NULL;
853
854 if (bgp->table_map[afi][safi].name)
855 {
856 /* Copy info and attributes, so the route-map apply doesn't modify the
857 BGP route info. */
858 BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
859 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
860 nexthop = &info_cp->attr->nexthop;
861 BGP_INFO_ATTR_BUF_FREE(info_cp);
862 }
863 else
864 {
865 nexthop = &mpinfo->attr->nexthop;
866 }
867
868 if (nexthop == NULL)
869 continue;
870
871 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
872 valid_nh_count++;
873 }
874
875 api.flags = flags;
876 api.type = ZEBRA_ROUTE_BGP;
877 api.message = 0;
878 api.safi = safi;
879 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
880 api.nexthop_num = valid_nh_count;
881 api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
882 api.ifindex_num = 0;
883 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
884 api.metric = metric;
885
886 distance = bgp_distance_apply (p, info, bgp);
887
888 if (distance)
889 {
890 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
891 api.distance = distance;
892 }
893
894 if (BGP_DEBUG(zebra, ZEBRA))
895 {
896 int i;
897 zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u"
898 " count %d", (valid_nh_count ? "add":"delete"),
899 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
900 p->prefixlen, api.metric, api.nexthop_num);
901 for (i = 0; i < api.nexthop_num; i++)
902 zlog_debug(" IPv4 [nexthop %d] %s", i+1,
903 inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1])));
904 }
905
906 zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE,
907 zclient, (struct prefix_ipv4 *) p, &api);
908 }
909 #ifdef HAVE_IPV6
910
911 /* We have to think about a IPv6 link-local address curse. */
912 if (p->family == AF_INET6)
913 {
914 unsigned int ifindex;
915 struct in6_addr *nexthop;
916 struct zapi_ipv6 api;
917 int valid_nh_count = 0;
918 char buf[2][INET6_ADDRSTRLEN];
919
920 /* resize nexthop buffer size if necessary */
921 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
922 (sizeof (struct in6_addr *) * nhcount))
923 {
924 newsize = (sizeof (struct in6_addr *) * nhcount);
925 newsize = stream_resize (bgp_nexthop_buf, newsize);
926 if (newsize == oldsize)
927 {
928 zlog_err ("can't resize nexthop buffer");
929 return;
930 }
931 }
932 stream_reset (bgp_nexthop_buf);
933
934 /* resize ifindices buffer size if necessary */
935 if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
936 (sizeof (unsigned int) * nhcount))
937 {
938 newsize = (sizeof (unsigned int) * nhcount);
939 newsize = stream_resize (bgp_ifindices_buf, newsize);
940 if (newsize == oldsize)
941 {
942 zlog_err ("can't resize nexthop buffer");
943 return;
944 }
945 }
946 stream_reset (bgp_ifindices_buf);
947
948 ifindex = 0;
949 nexthop = NULL;
950
951 assert (info->attr->extra);
952
953 /* Metric is currently based on the best-path only. */
954 metric = info->attr->med;
955
956 if (bgp->table_map[afi][safi].name)
957 {
958 BGP_INFO_ATTR_BUF_INIT();
959
960 /* Copy info and attributes, so the route-map apply doesn't modify the
961 BGP route info. */
962 BGP_INFO_ATTR_BUF_COPY(info, info_cp);
963 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
964 {
965 metric = info_cp->attr->med;
966 nexthop = bgp_info_to_ipv6_nexthop(info_cp);
967 }
968 BGP_INFO_ATTR_BUF_FREE(info_cp);
969 }
970 else
971 {
972 nexthop = bgp_info_to_ipv6_nexthop(info);
973 }
974
975 if (nexthop)
976 {
977 if (info->attr->extra->mp_nexthop_len == 32)
978 if (info->peer->nexthop.ifp)
979 ifindex = info->peer->nexthop.ifp->ifindex;
980
981 if (!ifindex)
982 if (info->peer->ifname)
983 ifindex = if_nametoindex (info->peer->ifname);
984 else if (info->peer->nexthop.ifp)
985 ifindex = info->peer->nexthop.ifp->ifindex;
986
987 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
988 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
989 valid_nh_count++;
990 }
991
992 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
993 mpinfo = bgp_info_mpath_next (mpinfo))
994 {
995 ifindex = 0;
996 nexthop = NULL;
997
998 if (bgp->table_map[afi][safi].name)
999 {
1000 /* Copy info and attributes, so the route-map apply doesn't modify the
1001 BGP route info. */
1002 BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
1003 if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
1004 nexthop = bgp_info_to_ipv6_nexthop(info_cp);
1005 BGP_INFO_ATTR_BUF_FREE(info_cp);
1006 }
1007 else
1008 {
1009 nexthop = bgp_info_to_ipv6_nexthop(mpinfo);
1010 }
1011
1012 if (nexthop == NULL)
1013 continue;
1014
1015 if (mpinfo->attr->extra->mp_nexthop_len == 32)
1016 if (mpinfo->peer->nexthop.ifp)
1017 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
1018
1019 if (!ifindex)
1020 if (mpinfo->peer->ifname)
1021 ifindex = if_nametoindex (mpinfo->peer->ifname);
1022 else if (mpinfo->peer->nexthop.ifp)
1023 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
1024
1025 if (ifindex == 0)
1026 continue;
1027
1028 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
1029 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
1030 valid_nh_count++;
1031 }
1032
1033 /* Make Zebra API structure. */
1034 api.flags = flags;
1035 api.type = ZEBRA_ROUTE_BGP;
1036 api.message = 0;
1037 api.safi = safi;
1038 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
1039 api.nexthop_num = valid_nh_count;
1040 api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
1041 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
1042 api.ifindex_num = valid_nh_count;
1043 api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf);
1044 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1045 api.metric = metric;
1046
1047 if (BGP_DEBUG(zebra, ZEBRA))
1048 {
1049 int i;
1050 zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u",
1051 valid_nh_count ? "add" : "delete",
1052 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
1053 p->prefixlen, api.metric);
1054 for (i = 0; i < api.nexthop_num; i++)
1055 zlog_debug(" IPv6 [nexthop %d] %s", i+1,
1056 inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])));
1057 }
1058
1059 zapi_ipv6_route (valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE,
1060 zclient, (struct prefix_ipv6 *) p, &api);
1061 }
1062 #endif /* HAVE_IPV6 */
1063 }
1064
1065 /* Announce all routes of a table to zebra */
1066 void
1067 bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi)
1068 {
1069 struct bgp_node *rn;
1070 struct bgp_table *table;
1071 struct bgp_info *ri;
1072
1073 table = bgp->rib[afi][safi];
1074
1075 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
1076 for (ri = rn->info; ri; ri = ri->next)
1077 if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
1078 && ri->type == ZEBRA_ROUTE_BGP
1079 && ri->sub_type == BGP_ROUTE_NORMAL)
1080 bgp_zebra_announce (&rn->p, ri, bgp, afi, safi);
1081 }
1082
1083 void
1084 bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
1085 {
1086 int flags;
1087 struct peer *peer;
1088
1089 if (zclient->sock < 0)
1090 return;
1091
1092 if (! zclient->redist[ZEBRA_ROUTE_BGP])
1093 return;
1094
1095 peer = info->peer;
1096 flags = 0;
1097
1098 if (peer->sort == BGP_PEER_IBGP)
1099 {
1100 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
1101 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
1102 }
1103
1104 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
1105 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
1106 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
1107
1108 if (p->family == AF_INET)
1109 {
1110 struct zapi_ipv4 api;
1111 struct in_addr *nexthop;
1112
1113 api.flags = flags;
1114 nexthop = &info->attr->nexthop;
1115
1116 api.type = ZEBRA_ROUTE_BGP;
1117 api.message = 0;
1118 api.safi = safi;
1119 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
1120 api.nexthop_num = 1;
1121 api.nexthop = &nexthop;
1122 api.ifindex_num = 0;
1123 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1124 api.metric = info->attr->med;
1125
1126 if (BGP_DEBUG(zebra, ZEBRA))
1127 {
1128 char buf[2][INET_ADDRSTRLEN];
1129 zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u",
1130 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
1131 p->prefixlen,
1132 inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
1133 api.metric);
1134 }
1135
1136 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
1137 (struct prefix_ipv4 *) p, &api);
1138 }
1139 #ifdef HAVE_IPV6
1140 /* We have to think about a IPv6 link-local address curse. */
1141 if (p->family == AF_INET6)
1142 {
1143 struct zapi_ipv6 api;
1144 unsigned int ifindex;
1145 struct in6_addr *nexthop;
1146
1147 assert (info->attr->extra);
1148
1149 ifindex = 0;
1150 nexthop = NULL;
1151
1152 /* Only global address nexthop exists. */
1153 if (info->attr->extra->mp_nexthop_len == 16)
1154 nexthop = &info->attr->extra->mp_nexthop_global;
1155
1156 /* If both global and link-local address present. */
1157 if (info->attr->extra->mp_nexthop_len == 32)
1158 {
1159 nexthop = &info->attr->extra->mp_nexthop_local;
1160 if (info->peer->nexthop.ifp)
1161 ifindex = info->peer->nexthop.ifp->ifindex;
1162 }
1163
1164 if (nexthop == NULL)
1165 return;
1166
1167 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
1168 if (info->peer->ifname)
1169 ifindex = if_nametoindex (info->peer->ifname);
1170
1171 api.flags = flags;
1172 api.type = ZEBRA_ROUTE_BGP;
1173 api.message = 0;
1174 api.safi = safi;
1175 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
1176 api.nexthop_num = 1;
1177 api.nexthop = &nexthop;
1178 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
1179 api.ifindex_num = 1;
1180 api.ifindex = &ifindex;
1181 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1182 api.metric = info->attr->med;
1183
1184 if (BGP_DEBUG(zebra, ZEBRA))
1185 {
1186 char buf[2][INET6_ADDRSTRLEN];
1187 zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u",
1188 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
1189 p->prefixlen,
1190 inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
1191 api.metric);
1192 }
1193
1194 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
1195 (struct prefix_ipv6 *) p, &api);
1196 }
1197 #endif /* HAVE_IPV6 */
1198 }
1199
1200 /* Other routes redistribution into BGP. */
1201 int
1202 bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
1203 {
1204 /* Set flag to BGP instance. */
1205 bgp->redist[afi][type] = 1;
1206
1207 /* Return if already redistribute flag is set. */
1208 if (zclient->redist[type])
1209 return CMD_WARNING;
1210
1211 zclient->redist[type] = 1;
1212
1213 /* Return if zebra connection is not established. */
1214 if (zclient->sock < 0)
1215 return CMD_WARNING;
1216
1217 if (BGP_DEBUG(zebra, ZEBRA))
1218 zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
1219
1220 /* Send distribute add message to zebra. */
1221 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
1222
1223 return CMD_SUCCESS;
1224 }
1225
1226 /* Redistribute with route-map specification. */
1227 int
1228 bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
1229 const char *name)
1230 {
1231 if (bgp->rmap[afi][type].name
1232 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
1233 return 0;
1234
1235 if (bgp->rmap[afi][type].name)
1236 free (bgp->rmap[afi][type].name);
1237 bgp->rmap[afi][type].name = strdup (name);
1238 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
1239
1240 return 1;
1241 }
1242
1243 /* Redistribute with metric specification. */
1244 int
1245 bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
1246 u_int32_t metric)
1247 {
1248 if (bgp->redist_metric_flag[afi][type]
1249 && bgp->redist_metric[afi][type] == metric)
1250 return 0;
1251
1252 bgp->redist_metric_flag[afi][type] = 1;
1253 bgp->redist_metric[afi][type] = metric;
1254
1255 return 1;
1256 }
1257
1258 /* Unset redistribution. */
1259 int
1260 bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
1261 {
1262 /* Unset flag from BGP instance. */
1263 bgp->redist[afi][type] = 0;
1264
1265 /* Unset route-map. */
1266 if (bgp->rmap[afi][type].name)
1267 free (bgp->rmap[afi][type].name);
1268 bgp->rmap[afi][type].name = NULL;
1269 bgp->rmap[afi][type].map = NULL;
1270
1271 /* Unset metric. */
1272 bgp->redist_metric_flag[afi][type] = 0;
1273 bgp->redist_metric[afi][type] = 0;
1274
1275 /* Return if zebra connection is disabled. */
1276 if (! zclient->redist[type])
1277 return CMD_WARNING;
1278 zclient->redist[type] = 0;
1279
1280 if (bgp->redist[AFI_IP][type] == 0
1281 && bgp->redist[AFI_IP6][type] == 0
1282 && zclient->sock >= 0)
1283 {
1284 /* Send distribute delete message to zebra. */
1285 if (BGP_DEBUG(zebra, ZEBRA))
1286 zlog_debug("Zebra send: redistribute delete %s",
1287 zebra_route_string(type));
1288 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
1289 }
1290
1291 /* Withdraw redistributed routes from current BGP's routing table. */
1292 bgp_redistribute_withdraw (bgp, afi, type);
1293
1294 return CMD_SUCCESS;
1295 }
1296
1297 /* Unset redistribution route-map configuration. */
1298 int
1299 bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
1300 {
1301 if (! bgp->rmap[afi][type].name)
1302 return 0;
1303
1304 /* Unset route-map. */
1305 free (bgp->rmap[afi][type].name);
1306 bgp->rmap[afi][type].name = NULL;
1307 bgp->rmap[afi][type].map = NULL;
1308
1309 return 1;
1310 }
1311
1312 /* Unset redistribution metric configuration. */
1313 int
1314 bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
1315 {
1316 if (! bgp->redist_metric_flag[afi][type])
1317 return 0;
1318
1319 /* Unset metric. */
1320 bgp->redist_metric_flag[afi][type] = 0;
1321 bgp->redist_metric[afi][type] = 0;
1322
1323 return 1;
1324 }
1325
1326 void
1327 bgp_zclient_reset (void)
1328 {
1329 zclient_reset (zclient);
1330 }
1331
1332 void
1333 bgp_zebra_init (void)
1334 {
1335 /* Set default values. */
1336 zclient = zclient_new ();
1337 zclient_init (zclient, ZEBRA_ROUTE_BGP);
1338 zclient->router_id_update = bgp_router_id_update;
1339 zclient->interface_add = bgp_interface_add;
1340 zclient->interface_delete = bgp_interface_delete;
1341 zclient->interface_address_add = bgp_interface_address_add;
1342 zclient->interface_address_delete = bgp_interface_address_delete;
1343 zclient->ipv4_route_add = zebra_read_ipv4;
1344 zclient->ipv4_route_delete = zebra_read_ipv4;
1345 zclient->interface_up = bgp_interface_up;
1346 zclient->interface_down = bgp_interface_down;
1347 #ifdef HAVE_IPV6
1348 zclient->ipv6_route_add = zebra_read_ipv6;
1349 zclient->ipv6_route_delete = zebra_read_ipv6;
1350 #endif /* HAVE_IPV6 */
1351 zclient->nexthop_update = bgp_read_nexthop_update;
1352
1353 /* Interface related init. */
1354 if_init ();
1355
1356 bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
1357 bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
1358 }