File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / connected.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:41 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    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, SAFI_UNICAST);
  193: 
  194:   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
  195: 	RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
  196: 
  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. */
  301:   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
  302: 
  303:   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST);
  304: 
  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,
  351:                 ifp->metric, 0, SAFI_UNICAST);
  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: 
  425:   rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
  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>