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