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