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