Annotation of embedaddon/quagga/zebra/redistribute.c, revision 1.1
1.1 ! misho 1: /* Redistribution Handler
! 2: * Copyright (C) 1998 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 Free
! 18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: * 02111-1307, USA.
! 20: */
! 21:
! 22: #include <zebra.h>
! 23:
! 24: #include "vector.h"
! 25: #include "vty.h"
! 26: #include "command.h"
! 27: #include "prefix.h"
! 28: #include "table.h"
! 29: #include "stream.h"
! 30: #include "zclient.h"
! 31: #include "linklist.h"
! 32: #include "log.h"
! 33:
! 34: #include "zebra/rib.h"
! 35: #include "zebra/zserv.h"
! 36: #include "zebra/redistribute.h"
! 37: #include "zebra/debug.h"
! 38: #include "zebra/router-id.h"
! 39:
! 40: /* master zebra server structure */
! 41: extern struct zebra_t zebrad;
! 42:
! 43: int
! 44: zebra_check_addr (struct prefix *p)
! 45: {
! 46: if (p->family == AF_INET)
! 47: {
! 48: u_int32_t addr;
! 49:
! 50: addr = p->u.prefix4.s_addr;
! 51: addr = ntohl (addr);
! 52:
! 53: if (IPV4_NET127 (addr)
! 54: || IN_CLASSD (addr)
! 55: || IPV4_LINKLOCAL(addr))
! 56: return 0;
! 57: }
! 58: #ifdef HAVE_IPV6
! 59: if (p->family == AF_INET6)
! 60: {
! 61: if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6))
! 62: return 0;
! 63: if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
! 64: return 0;
! 65: }
! 66: #endif /* HAVE_IPV6 */
! 67: return 1;
! 68: }
! 69:
! 70: static int
! 71: is_default (struct prefix *p)
! 72: {
! 73: if (p->family == AF_INET)
! 74: if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
! 75: return 1;
! 76: #ifdef HAVE_IPV6
! 77: #if 0 /* IPv6 default separation is now pending until protocol daemon
! 78: can handle that. */
! 79: if (p->family == AF_INET6)
! 80: if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0)
! 81: return 1;
! 82: #endif /* 0 */
! 83: #endif /* HAVE_IPV6 */
! 84: return 0;
! 85: }
! 86:
! 87: static void
! 88: zebra_redistribute_default (struct zserv *client)
! 89: {
! 90: struct prefix_ipv4 p;
! 91: struct route_table *table;
! 92: struct route_node *rn;
! 93: struct rib *newrib;
! 94: #ifdef HAVE_IPV6
! 95: struct prefix_ipv6 p6;
! 96: #endif /* HAVE_IPV6 */
! 97:
! 98:
! 99: /* Lookup default route. */
! 100: memset (&p, 0, sizeof (struct prefix_ipv4));
! 101: p.family = AF_INET;
! 102:
! 103: /* Lookup table. */
! 104: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 105: if (table)
! 106: {
! 107: rn = route_node_lookup (table, (struct prefix *)&p);
! 108: if (rn)
! 109: {
! 110: for (newrib = rn->info; newrib; newrib = newrib->next)
! 111: if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
! 112: && newrib->distance != DISTANCE_INFINITY)
! 113: zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
! 114: route_unlock_node (rn);
! 115: }
! 116: }
! 117:
! 118: #ifdef HAVE_IPV6
! 119: /* Lookup default route. */
! 120: memset (&p6, 0, sizeof (struct prefix_ipv6));
! 121: p6.family = AF_INET6;
! 122:
! 123: /* Lookup table. */
! 124: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 125: if (table)
! 126: {
! 127: rn = route_node_lookup (table, (struct prefix *)&p6);
! 128: if (rn)
! 129: {
! 130: for (newrib = rn->info; newrib; newrib = newrib->next)
! 131: if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
! 132: && newrib->distance != DISTANCE_INFINITY)
! 133: zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
! 134: route_unlock_node (rn);
! 135: }
! 136: }
! 137: #endif /* HAVE_IPV6 */
! 138: }
! 139:
! 140: /* Redistribute routes. */
! 141: static void
! 142: zebra_redistribute (struct zserv *client, int type)
! 143: {
! 144: struct rib *newrib;
! 145: struct route_table *table;
! 146: struct route_node *rn;
! 147:
! 148: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 149: if (table)
! 150: for (rn = route_top (table); rn; rn = route_next (rn))
! 151: for (newrib = rn->info; newrib; newrib = newrib->next)
! 152: if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
! 153: && newrib->type == type
! 154: && newrib->distance != DISTANCE_INFINITY
! 155: && zebra_check_addr (&rn->p))
! 156: zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
! 157:
! 158: #ifdef HAVE_IPV6
! 159: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 160: if (table)
! 161: for (rn = route_top (table); rn; rn = route_next (rn))
! 162: for (newrib = rn->info; newrib; newrib = newrib->next)
! 163: if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
! 164: && newrib->type == type
! 165: && newrib->distance != DISTANCE_INFINITY
! 166: && zebra_check_addr (&rn->p))
! 167: zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
! 168: #endif /* HAVE_IPV6 */
! 169: }
! 170:
! 171: void
! 172: redistribute_add (struct prefix *p, struct rib *rib)
! 173: {
! 174: struct listnode *node, *nnode;
! 175: struct zserv *client;
! 176:
! 177: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 178: {
! 179: if (is_default (p))
! 180: {
! 181: if (client->redist_default || client->redist[rib->type])
! 182: {
! 183: if (p->family == AF_INET)
! 184: zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
! 185: #ifdef HAVE_IPV6
! 186: if (p->family == AF_INET6)
! 187: zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
! 188: #endif /* HAVE_IPV6 */
! 189: }
! 190: }
! 191: else if (client->redist[rib->type])
! 192: {
! 193: if (p->family == AF_INET)
! 194: zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
! 195: #ifdef HAVE_IPV6
! 196: if (p->family == AF_INET6)
! 197: zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
! 198: #endif /* HAVE_IPV6 */
! 199: }
! 200: }
! 201: }
! 202:
! 203: void
! 204: redistribute_delete (struct prefix *p, struct rib *rib)
! 205: {
! 206: struct listnode *node, *nnode;
! 207: struct zserv *client;
! 208:
! 209: /* Add DISTANCE_INFINITY check. */
! 210: if (rib->distance == DISTANCE_INFINITY)
! 211: return;
! 212:
! 213: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 214: {
! 215: if (is_default (p))
! 216: {
! 217: if (client->redist_default || client->redist[rib->type])
! 218: {
! 219: if (p->family == AF_INET)
! 220: zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p,
! 221: rib);
! 222: #ifdef HAVE_IPV6
! 223: if (p->family == AF_INET6)
! 224: zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p,
! 225: rib);
! 226: #endif /* HAVE_IPV6 */
! 227: }
! 228: }
! 229: else if (client->redist[rib->type])
! 230: {
! 231: if (p->family == AF_INET)
! 232: zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib);
! 233: #ifdef HAVE_IPV6
! 234: if (p->family == AF_INET6)
! 235: zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, rib);
! 236: #endif /* HAVE_IPV6 */
! 237: }
! 238: }
! 239: }
! 240:
! 241: void
! 242: zebra_redistribute_add (int command, struct zserv *client, int length)
! 243: {
! 244: int type;
! 245:
! 246: type = stream_getc (client->ibuf);
! 247:
! 248: switch (type)
! 249: {
! 250: case ZEBRA_ROUTE_KERNEL:
! 251: case ZEBRA_ROUTE_CONNECT:
! 252: case ZEBRA_ROUTE_STATIC:
! 253: case ZEBRA_ROUTE_RIP:
! 254: case ZEBRA_ROUTE_RIPNG:
! 255: case ZEBRA_ROUTE_OSPF:
! 256: case ZEBRA_ROUTE_OSPF6:
! 257: case ZEBRA_ROUTE_BGP:
! 258: if (! client->redist[type])
! 259: {
! 260: client->redist[type] = 1;
! 261: zebra_redistribute (client, type);
! 262: }
! 263: break;
! 264: default:
! 265: break;
! 266: }
! 267: }
! 268:
! 269: void
! 270: zebra_redistribute_delete (int command, struct zserv *client, int length)
! 271: {
! 272: int type;
! 273:
! 274: type = stream_getc (client->ibuf);
! 275:
! 276: switch (type)
! 277: {
! 278: case ZEBRA_ROUTE_KERNEL:
! 279: case ZEBRA_ROUTE_CONNECT:
! 280: case ZEBRA_ROUTE_STATIC:
! 281: case ZEBRA_ROUTE_RIP:
! 282: case ZEBRA_ROUTE_RIPNG:
! 283: case ZEBRA_ROUTE_OSPF:
! 284: case ZEBRA_ROUTE_OSPF6:
! 285: case ZEBRA_ROUTE_BGP:
! 286: client->redist[type] = 0;
! 287: break;
! 288: default:
! 289: break;
! 290: }
! 291: }
! 292:
! 293: void
! 294: zebra_redistribute_default_add (int command, struct zserv *client, int length)
! 295: {
! 296: client->redist_default = 1;
! 297: zebra_redistribute_default (client);
! 298: }
! 299:
! 300: void
! 301: zebra_redistribute_default_delete (int command, struct zserv *client,
! 302: int length)
! 303: {
! 304: client->redist_default = 0;;
! 305: }
! 306:
! 307: /* Interface up information. */
! 308: void
! 309: zebra_interface_up_update (struct interface *ifp)
! 310: {
! 311: struct listnode *node, *nnode;
! 312: struct zserv *client;
! 313:
! 314: if (IS_ZEBRA_DEBUG_EVENT)
! 315: zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
! 316:
! 317: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 318: zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
! 319: }
! 320:
! 321: /* Interface down information. */
! 322: void
! 323: zebra_interface_down_update (struct interface *ifp)
! 324: {
! 325: struct listnode *node, *nnode;
! 326: struct zserv *client;
! 327:
! 328: if (IS_ZEBRA_DEBUG_EVENT)
! 329: zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
! 330:
! 331: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 332: zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
! 333: }
! 334:
! 335: /* Interface information update. */
! 336: void
! 337: zebra_interface_add_update (struct interface *ifp)
! 338: {
! 339: struct listnode *node, *nnode;
! 340: struct zserv *client;
! 341:
! 342: if (IS_ZEBRA_DEBUG_EVENT)
! 343: zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s", ifp->name);
! 344:
! 345: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 346: if (client->ifinfo)
! 347: zsend_interface_add (client, ifp);
! 348: }
! 349:
! 350: void
! 351: zebra_interface_delete_update (struct interface *ifp)
! 352: {
! 353: struct listnode *node, *nnode;
! 354: struct zserv *client;
! 355:
! 356: if (IS_ZEBRA_DEBUG_EVENT)
! 357: zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name);
! 358:
! 359: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 360: if (client->ifinfo)
! 361: zsend_interface_delete (client, ifp);
! 362: }
! 363:
! 364: /* Interface address addition. */
! 365: void
! 366: zebra_interface_address_add_update (struct interface *ifp,
! 367: struct connected *ifc)
! 368: {
! 369: struct listnode *node, *nnode;
! 370: struct zserv *client;
! 371: struct prefix *p;
! 372:
! 373: if (IS_ZEBRA_DEBUG_EVENT)
! 374: {
! 375: char buf[INET6_ADDRSTRLEN];
! 376:
! 377: p = ifc->address;
! 378: zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s/%d on %s",
! 379: inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN),
! 380: p->prefixlen, ifc->ifp->name);
! 381: }
! 382:
! 383: router_id_add_address(ifc);
! 384:
! 385: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 386: if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
! 387: zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc);
! 388: }
! 389:
! 390: /* Interface address deletion. */
! 391: void
! 392: zebra_interface_address_delete_update (struct interface *ifp,
! 393: struct connected *ifc)
! 394: {
! 395: struct listnode *node, *nnode;
! 396: struct zserv *client;
! 397: struct prefix *p;
! 398:
! 399: if (IS_ZEBRA_DEBUG_EVENT)
! 400: {
! 401: char buf[INET6_ADDRSTRLEN];
! 402:
! 403: p = ifc->address;
! 404: zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s/%d on %s",
! 405: inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN),
! 406: p->prefixlen, ifc->ifp->name);
! 407: }
! 408:
! 409: router_id_del_address(ifc);
! 410:
! 411: for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
! 412: if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
! 413: zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc);
! 414: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>