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

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,
                    192:        RT_TABLE_MAIN, ifp->metric, 0);
                    193: 
                    194:   rib_update ();
                    195: }
                    196: 
                    197: /* Add connected IPv4 route to the interface. */
                    198: void
                    199: connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, 
                    200:                    u_char prefixlen, struct in_addr *broad, 
                    201:                    const char *label)
                    202: {
                    203:   struct prefix_ipv4 *p;
                    204:   struct connected *ifc;
                    205: 
                    206:   /* Make connected structure. */
                    207:   ifc = connected_new ();
                    208:   ifc->ifp = ifp;
                    209:   ifc->flags = flags;
                    210: 
                    211:   /* Allocate new connected address. */
                    212:   p = prefix_ipv4_new ();
                    213:   p->family = AF_INET;
                    214:   p->prefix = *addr;
                    215:   p->prefixlen = prefixlen;
                    216:   ifc->address = (struct prefix *) p;
                    217:   
                    218:   /* If there is broadcast or peer address. */
                    219:   if (broad)
                    220:     {
                    221:       p = prefix_ipv4_new ();
                    222:       p->family = AF_INET;
                    223:       p->prefix = *broad;
                    224:       p->prefixlen = prefixlen;
                    225:       ifc->destination = (struct prefix *) p;
                    226: 
                    227:       /* validate the destination address */
                    228:       if (CONNECTED_PEER(ifc))
                    229:         {
                    230:          if (IPV4_ADDR_SAME(addr,broad))
                    231:            zlog_warn("warning: interface %s has same local and peer "
                    232:                      "address %s, routing protocols may malfunction",
                    233:                      ifp->name,inet_ntoa(*addr));
                    234:         }
                    235:       else
                    236:         {
                    237:          if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
                    238:            {
                    239:              char buf[2][INET_ADDRSTRLEN];
                    240:              struct in_addr bcalc;
                    241:              bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
                    242:              zlog_warn("warning: interface %s broadcast addr %s/%d != "
                    243:                        "calculated %s, routing protocols may malfunction",
                    244:                        ifp->name,
                    245:                        inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
                    246:                        prefixlen,
                    247:                        inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
                    248:            }
                    249:         }
                    250: 
                    251:     }
                    252:   else
                    253:     {
                    254:       if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
                    255:         {
                    256:          zlog_warn("warning: %s called for interface %s "
                    257:                    "with peer flag set, but no peer address supplied",
                    258:                    __func__, ifp->name);
                    259:          UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
                    260:        }
                    261: 
                    262:       /* no broadcast or destination address was supplied */
                    263:       if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
                    264:        zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
                    265:                  "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
                    266:     }
                    267: 
                    268:   /* Label of this address. */
                    269:   if (label)
                    270:     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
                    271: 
                    272:   /* nothing to do? */
                    273:   if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
                    274:     return;
                    275:   
                    276:   connected_announce (ifp, ifc);
                    277: }
                    278: 
                    279: void
                    280: connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
                    281: {
                    282:   struct prefix_ipv4 p;
                    283: 
                    284:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    285:     return;
                    286: 
                    287:   PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
                    288: 
                    289:   /* Apply mask to the network. */
                    290:   apply_mask_ipv4 (&p);
                    291: 
                    292:   /* In case of connected address is 0.0.0.0/0 we treat it tunnel
                    293:      address. */
                    294:   if (prefix_ipv4_any (&p))
                    295:     return;
                    296: 
                    297:   /* Same logic as for connected_up_ipv4(): push the changes into the head. */
                    298:   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
                    299: 
                    300:   rib_update ();
                    301: }
                    302: 
                    303: /* Delete connected IPv4 route to the interface. */
                    304: void
                    305: connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
                    306:                       u_char prefixlen, struct in_addr *broad)
                    307: {
                    308:   struct prefix_ipv4 p;
                    309:   struct connected *ifc;
                    310: 
                    311:   memset (&p, 0, sizeof (struct prefix_ipv4));
                    312:   p.family = AF_INET;
                    313:   p.prefix = *addr;
                    314:   p.prefixlen = prefixlen;
                    315: 
                    316:   ifc = connected_check (ifp, (struct prefix *) &p);
                    317:   if (! ifc)
                    318:     return;
                    319:     
                    320:   connected_withdraw (ifc);
                    321: 
                    322:   rib_update();
                    323: }
                    324: 
                    325: #ifdef HAVE_IPV6
                    326: void
                    327: connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
                    328: {
                    329:   struct prefix_ipv6 p;
                    330: 
                    331:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    332:     return;
                    333: 
                    334:   PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
                    335: 
                    336:   /* Apply mask to the network. */
                    337:   apply_mask_ipv6 (&p);
                    338: 
                    339: #if ! defined (MUSICA) && ! defined (LINUX)
                    340:   /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
                    341:   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
                    342:     return;
                    343: #endif
                    344: 
                    345:   rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN,
                    346:                 ifp->metric, 0);
                    347: 
                    348:   rib_update ();
                    349: }
                    350: 
                    351: /* Add connected IPv6 route to the interface. */
                    352: void
                    353: connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
                    354:                    u_char prefixlen, struct in6_addr *broad,
                    355:                    const char *label)
                    356: {
                    357:   struct prefix_ipv6 *p;
                    358:   struct connected *ifc;
                    359: 
                    360:   /* Make connected structure. */
                    361:   ifc = connected_new ();
                    362:   ifc->ifp = ifp;
                    363:   ifc->flags = flags;
                    364: 
                    365:   /* Allocate new connected address. */
                    366:   p = prefix_ipv6_new ();
                    367:   p->family = AF_INET6;
                    368:   IPV6_ADDR_COPY (&p->prefix, addr);
                    369:   p->prefixlen = prefixlen;
                    370:   ifc->address = (struct prefix *) p;
                    371: 
                    372:   /* If there is broadcast or peer address. */
                    373:   if (broad)
                    374:     {
                    375:       if (IN6_IS_ADDR_UNSPECIFIED(broad))
                    376:        zlog_warn("warning: %s called for interface %s with unspecified "
                    377:                  "destination address; ignoring!", __func__, ifp->name);
                    378:       else
                    379:        {
                    380:          p = prefix_ipv6_new ();
                    381:          p->family = AF_INET6;
                    382:          IPV6_ADDR_COPY (&p->prefix, broad);
                    383:          p->prefixlen = prefixlen;
                    384:          ifc->destination = (struct prefix *) p;
                    385:        }
                    386:     }
                    387:   if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
                    388:     {
                    389:       zlog_warn("warning: %s called for interface %s "
                    390:                "with peer flag set, but no peer address supplied",
                    391:                __func__, ifp->name);
                    392:       UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
                    393:     }
                    394: 
                    395:   /* Label of this address. */
                    396:   if (label)
                    397:     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
                    398:   
                    399:   if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
                    400:     return;
                    401:   
                    402:   connected_announce (ifp, ifc);
                    403: }
                    404: 
                    405: void
                    406: connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
                    407: {
                    408:   struct prefix_ipv6 p;
                    409: 
                    410:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
                    411:     return;
                    412: 
                    413:   PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
                    414: 
                    415:   apply_mask_ipv6 (&p);
                    416: 
                    417:   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
                    418:     return;
                    419: 
                    420:   rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
                    421: 
                    422:   rib_update ();
                    423: }
                    424: 
                    425: void
                    426: connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
                    427:                       u_char prefixlen, struct in6_addr *broad)
                    428: {
                    429:   struct prefix_ipv6 p;
                    430:   struct connected *ifc;
                    431:   
                    432:   memset (&p, 0, sizeof (struct prefix_ipv6));
                    433:   p.family = AF_INET6;
                    434:   memcpy (&p.prefix, address, sizeof (struct in6_addr));
                    435:   p.prefixlen = prefixlen;
                    436: 
                    437:   ifc = connected_check (ifp, (struct prefix *) &p);
                    438:   if (! ifc)
                    439:     return;
                    440: 
                    441:   connected_withdraw (ifc);
                    442: 
                    443:   rib_update();
                    444: }
                    445: #endif /* HAVE_IPV6 */

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