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>