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