Annotation of embedaddon/quagga/zebra/connected.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * Address linked list routine.
                      3:  * Copyright (C) 1997, 98 Kunihiro Ishiguro
                      4:  *
                      5:  * This file is part of GNU Zebra.
                      6:  *
                      7:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2, or (at your option) any
                     10:  * later version.
                     11:  *
                     12:  * GNU Zebra is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License
                     18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     20:  * 02111-1307, USA.  
                     21:  */
                     22: 
                     23: #include <zebra.h>
                     24: 
                     25: #include "prefix.h"
                     26: #include "linklist.h"
                     27: #include "if.h"
                     28: #include "table.h"
                     29: #include "rib.h"
                     30: #include "table.h"
                     31: #include "log.h"
                     32: #include "memory.h"
                     33: 
                     34: #include "zebra/zserv.h"
                     35: #include "zebra/redistribute.h"
                     36: #include "zebra/interface.h"
                     37: #include "zebra/connected.h"
                     38: extern struct zebra_t zebrad;
                     39: 
                     40: /* withdraw a connected address */
                     41: static void
                     42: connected_withdraw (struct connected *ifc)
                     43: {
                     44:   if (! ifc)
                     45:     return;
                     46: 
                     47:   /* Update interface address information to protocol daemon. */
                     48:   if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                     49:     {
                     50:       zebra_interface_address_delete_update (ifc->ifp, ifc);
                     51: 
                     52:       if_subnet_delete (ifc->ifp, ifc);
                     53:       
                     54:       if (ifc->address->family == AF_INET)
                     55:         connected_down_ipv4 (ifc->ifp, ifc);
                     56: #ifdef HAVE_IPV6
                     57:       else
                     58:         connected_down_ipv6 (ifc->ifp, ifc);
                     59: #endif
                     60: 
                     61:       UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
                     62:     }
                     63: 
                     64:   if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
                     65:     {
                     66:       listnode_delete (ifc->ifp->connected, ifc);
                     67:       connected_free (ifc);
                     68:     }
                     69: }
                     70: 
                     71: static void
                     72: connected_announce (struct interface *ifp, struct connected *ifc)
                     73: {
                     74:   if (!ifc)
                     75:     return;
                     76:   
                     77:   listnode_add (ifp->connected, ifc);
                     78: 
                     79:   /* Update interface address information to protocol daemon. */
                     80:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                     81:     {
                     82:       if (ifc->address->family == AF_INET)
                     83:         if_subnet_add (ifp, ifc);
                     84: 
                     85:       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
                     86: 
                     87:       zebra_interface_address_add_update (ifp, ifc);
                     88: 
                     89:       if (if_is_operative(ifp))
                     90:         {
                     91:           if (ifc->address->family == AF_INET)
                     92:            connected_up_ipv4 (ifp, ifc);
                     93: #ifdef HAVE_IPV6
                     94:           else
                     95:             connected_up_ipv6 (ifp, ifc);
                     96: #endif
                     97:         }
                     98:     }
                     99: }
                    100: 
                    101: /* If same interface address is already exist... */
                    102: struct connected *
                    103: connected_check (struct interface *ifp, struct prefix *p)
                    104: {
                    105:   struct connected *ifc;
                    106:   struct listnode *node;
                    107: 
                    108:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
                    109:     if (prefix_same (ifc->address, p))
                    110:       return ifc;
                    111: 
                    112:   return NULL;
                    113: }
                    114: 
                    115: /* Check if two ifc's describe the same address */
                    116: static int
                    117: connected_same (struct connected *ifc1, struct connected *ifc2)
                    118: {
                    119:   if (ifc1->ifp != ifc2->ifp)
                    120:     return 0;
                    121:   
                    122:   if (ifc1->destination)
                    123:     if (!ifc2->destination)
                    124:       return 0;
                    125:   if (ifc2->destination)
                    126:     if (!ifc1->destination)
                    127:       return 0;
                    128:   
                    129:   if (ifc1->destination && ifc2->destination)
                    130:     if (!prefix_same (ifc1->destination, ifc2->destination))
                    131:       return 0;
                    132: 
                    133:   if (ifc1->flags != ifc2->flags)
                    134:     return 0;
                    135:   
                    136:   return 1;
                    137: }
                    138: 
                    139: /* Handle implicit withdrawals of addresses, where a system ADDs an address
                    140:  * to an interface which already has the same address configured.
                    141:  *
                    142:  * Returns the struct connected which must be announced to clients,
                    143:  * or NULL if nothing to do.
                    144:  */
                    145: static struct connected *
                    146: connected_implicit_withdraw (struct interface *ifp, struct connected *ifc)
                    147: {
                    148:   struct connected *current;
                    149:   
                    150:   /* Check same connected route. */
                    151:   if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
                    152:     {
                    153:       if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
                    154:         SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
                    155:        
                    156:       /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
                    157:        * back an address we have already added.
                    158:        */
                    159:       if (connected_same (current, ifc) && CHECK_FLAG(current->conf, ZEBRA_IFC_REAL))
                    160:         {
                    161:           /* nothing to do */
                    162:           connected_free (ifc);
                    163:           return NULL;
                    164:         }
                    165:       
                    166:       UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
                    167:       connected_withdraw (current); /* implicit withdraw - freebsd does this */
                    168:     }
                    169:   return ifc;
                    170: }
                    171: 
                    172: /* Called from if_up(). */
                    173: void
                    174: connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
                    175: {
                    176:   struct prefix_ipv4 p;
                    177: 
                    178:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    179:     return;
                    180: 
                    181:   PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
                    182: 
                    183:   /* Apply mask to the network. */
                    184:   apply_mask_ipv4 (&p);
                    185: 
                    186:   /* In case of connected address is 0.0.0.0/0 we treat it tunnel
                    187:      address. */
                    188:   if (prefix_ipv4_any (&p))
                    189:     return;
                    190: 
                    191:   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
1.1.1.2   misho     192:        RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
1.1       misho     193: 
1.1.1.3 ! misho     194:   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
        !           195:        RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
        !           196: 
1.1       misho     197:   rib_update ();
                    198: }
                    199: 
                    200: /* Add connected IPv4 route to the interface. */
                    201: void
                    202: connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, 
                    203:                    u_char prefixlen, struct in_addr *broad, 
                    204:                    const char *label)
                    205: {
                    206:   struct prefix_ipv4 *p;
                    207:   struct connected *ifc;
                    208: 
                    209:   /* Make connected structure. */
                    210:   ifc = connected_new ();
                    211:   ifc->ifp = ifp;
                    212:   ifc->flags = flags;
                    213: 
                    214:   /* Allocate new connected address. */
                    215:   p = prefix_ipv4_new ();
                    216:   p->family = AF_INET;
                    217:   p->prefix = *addr;
                    218:   p->prefixlen = prefixlen;
                    219:   ifc->address = (struct prefix *) p;
                    220:   
                    221:   /* If there is broadcast or peer address. */
                    222:   if (broad)
                    223:     {
                    224:       p = prefix_ipv4_new ();
                    225:       p->family = AF_INET;
                    226:       p->prefix = *broad;
                    227:       p->prefixlen = prefixlen;
                    228:       ifc->destination = (struct prefix *) p;
                    229: 
                    230:       /* validate the destination address */
                    231:       if (CONNECTED_PEER(ifc))
                    232:         {
                    233:          if (IPV4_ADDR_SAME(addr,broad))
                    234:            zlog_warn("warning: interface %s has same local and peer "
                    235:                      "address %s, routing protocols may malfunction",
                    236:                      ifp->name,inet_ntoa(*addr));
                    237:         }
                    238:       else
                    239:         {
                    240:          if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
                    241:            {
                    242:              char buf[2][INET_ADDRSTRLEN];
                    243:              struct in_addr bcalc;
                    244:              bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
                    245:              zlog_warn("warning: interface %s broadcast addr %s/%d != "
                    246:                        "calculated %s, routing protocols may malfunction",
                    247:                        ifp->name,
                    248:                        inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
                    249:                        prefixlen,
                    250:                        inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
                    251:            }
                    252:         }
                    253: 
                    254:     }
                    255:   else
                    256:     {
                    257:       if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
                    258:         {
                    259:          zlog_warn("warning: %s called for interface %s "
                    260:                    "with peer flag set, but no peer address supplied",
                    261:                    __func__, ifp->name);
                    262:          UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
                    263:        }
                    264: 
                    265:       /* no broadcast or destination address was supplied */
                    266:       if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
                    267:        zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
                    268:                  "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
                    269:     }
                    270: 
                    271:   /* Label of this address. */
                    272:   if (label)
                    273:     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
                    274: 
                    275:   /* nothing to do? */
                    276:   if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
                    277:     return;
                    278:   
                    279:   connected_announce (ifp, ifc);
                    280: }
                    281: 
                    282: void
                    283: connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
                    284: {
                    285:   struct prefix_ipv4 p;
                    286: 
                    287:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    288:     return;
                    289: 
                    290:   PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
                    291: 
                    292:   /* Apply mask to the network. */
                    293:   apply_mask_ipv4 (&p);
                    294: 
                    295:   /* In case of connected address is 0.0.0.0/0 we treat it tunnel
                    296:      address. */
                    297:   if (prefix_ipv4_any (&p))
                    298:     return;
                    299: 
                    300:   /* Same logic as for connected_up_ipv4(): push the changes into the head. */
1.1.1.2   misho     301:   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
1.1       misho     302: 
1.1.1.3 ! misho     303:   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST);
        !           304: 
1.1       misho     305:   rib_update ();
                    306: }
                    307: 
                    308: /* Delete connected IPv4 route to the interface. */
                    309: void
                    310: connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
                    311:                       u_char prefixlen, struct in_addr *broad)
                    312: {
                    313:   struct prefix_ipv4 p;
                    314:   struct connected *ifc;
                    315: 
                    316:   memset (&p, 0, sizeof (struct prefix_ipv4));
                    317:   p.family = AF_INET;
                    318:   p.prefix = *addr;
                    319:   p.prefixlen = prefixlen;
                    320: 
                    321:   ifc = connected_check (ifp, (struct prefix *) &p);
                    322:   if (! ifc)
                    323:     return;
                    324:     
                    325:   connected_withdraw (ifc);
                    326: 
                    327:   rib_update();
                    328: }
                    329: 
                    330: #ifdef HAVE_IPV6
                    331: void
                    332: connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
                    333: {
                    334:   struct prefix_ipv6 p;
                    335: 
                    336:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    337:     return;
                    338: 
                    339:   PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
                    340: 
                    341:   /* Apply mask to the network. */
                    342:   apply_mask_ipv6 (&p);
                    343: 
                    344: #if ! defined (MUSICA) && ! defined (LINUX)
                    345:   /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
                    346:   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
                    347:     return;
                    348: #endif
                    349: 
                    350:   rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN,
1.1.1.2   misho     351:                 ifp->metric, 0, SAFI_UNICAST);
1.1       misho     352: 
                    353:   rib_update ();
                    354: }
                    355: 
                    356: /* Add connected IPv6 route to the interface. */
                    357: void
                    358: connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
                    359:                    u_char prefixlen, struct in6_addr *broad,
                    360:                    const char *label)
                    361: {
                    362:   struct prefix_ipv6 *p;
                    363:   struct connected *ifc;
                    364: 
                    365:   /* Make connected structure. */
                    366:   ifc = connected_new ();
                    367:   ifc->ifp = ifp;
                    368:   ifc->flags = flags;
                    369: 
                    370:   /* Allocate new connected address. */
                    371:   p = prefix_ipv6_new ();
                    372:   p->family = AF_INET6;
                    373:   IPV6_ADDR_COPY (&p->prefix, addr);
                    374:   p->prefixlen = prefixlen;
                    375:   ifc->address = (struct prefix *) p;
                    376: 
                    377:   /* If there is broadcast or peer address. */
                    378:   if (broad)
                    379:     {
                    380:       if (IN6_IS_ADDR_UNSPECIFIED(broad))
                    381:        zlog_warn("warning: %s called for interface %s with unspecified "
                    382:                  "destination address; ignoring!", __func__, ifp->name);
                    383:       else
                    384:        {
                    385:          p = prefix_ipv6_new ();
                    386:          p->family = AF_INET6;
                    387:          IPV6_ADDR_COPY (&p->prefix, broad);
                    388:          p->prefixlen = prefixlen;
                    389:          ifc->destination = (struct prefix *) p;
                    390:        }
                    391:     }
                    392:   if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
                    393:     {
                    394:       zlog_warn("warning: %s called for interface %s "
                    395:                "with peer flag set, but no peer address supplied",
                    396:                __func__, ifp->name);
                    397:       UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
                    398:     }
                    399: 
                    400:   /* Label of this address. */
                    401:   if (label)
                    402:     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
                    403:   
                    404:   if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
                    405:     return;
                    406:   
                    407:   connected_announce (ifp, ifc);
                    408: }
                    409: 
                    410: void
                    411: connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
                    412: {
                    413:   struct prefix_ipv6 p;
                    414: 
                    415:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    416:     return;
                    417: 
                    418:   PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
                    419: 
                    420:   apply_mask_ipv6 (&p);
                    421: 
                    422:   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
                    423:     return;
                    424: 
1.1.1.2   misho     425:   rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
1.1       misho     426: 
                    427:   rib_update ();
                    428: }
                    429: 
                    430: void
                    431: connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
                    432:                       u_char prefixlen, struct in6_addr *broad)
                    433: {
                    434:   struct prefix_ipv6 p;
                    435:   struct connected *ifc;
                    436:   
                    437:   memset (&p, 0, sizeof (struct prefix_ipv6));
                    438:   p.family = AF_INET6;
                    439:   memcpy (&p.prefix, address, sizeof (struct in6_addr));
                    440:   p.prefixlen = prefixlen;
                    441: 
                    442:   ifc = connected_check (ifp, (struct prefix *) &p);
                    443:   if (! ifc)
                    444:     return;
                    445: 
                    446:   connected_withdraw (ifc);
                    447: 
                    448:   rib_update();
                    449: }
                    450: #endif /* HAVE_IPV6 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>