File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / rt_socket.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    1: /*
    2:  * Kernel routing table updates by routing socket.
    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 "if.h"
   26: #include "prefix.h"
   27: #include "sockunion.h"
   28: #include "log.h"
   29: #include "str.h"
   30: #include "privs.h"
   31: 
   32: #include "zebra/debug.h"
   33: #include "zebra/rib.h"
   34: #include "zebra/rt.h"
   35: #include "zebra/kernel_socket.h"
   36: 
   37: extern struct zebra_privs_t zserv_privs;
   38: 
   39: /* kernel socket export */
   40: extern int rtm_write (int message, union sockunion *dest,
   41:                       union sockunion *mask, union sockunion *gate,
   42:                       unsigned int index, int zebra_flags, int metric);
   43: 
   44: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
   45: /* Adjust netmask socket length. Return value is a adjusted sin_len
   46:    value. */
   47: static int
   48: sin_masklen (struct in_addr mask)
   49: {
   50:   char *p, *lim;
   51:   int len;
   52:   struct sockaddr_in sin;
   53: 
   54:   if (mask.s_addr == 0) 
   55:     return sizeof (long);
   56: 
   57:   sin.sin_addr = mask;
   58:   len = sizeof (struct sockaddr_in);
   59: 
   60:   lim = (char *) &sin.sin_addr;
   61:   p = lim + sizeof (sin.sin_addr);
   62: 
   63:   while (*--p == 0 && p >= lim) 
   64:     len--;
   65:   return len;
   66: }
   67: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
   68: 
   69: /* Interface between zebra message and rtm message. */
   70: static int
   71: kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib)
   72: 
   73: {
   74:   struct sockaddr_in *mask = NULL;
   75:   struct sockaddr_in sin_dest, sin_mask, sin_gate;
   76:   struct nexthop *nexthop, *tnexthop;
   77:   int recursing;
   78:   int nexthop_num = 0;
   79:   ifindex_t ifindex = 0;
   80:   int gate = 0;
   81:   int error;
   82:   char prefix_buf[PREFIX_STRLEN];
   83: 
   84:   if (IS_ZEBRA_DEBUG_RIB)
   85:     prefix2str (p, prefix_buf, sizeof(prefix_buf));
   86:   memset (&sin_dest, 0, sizeof (struct sockaddr_in));
   87:   sin_dest.sin_family = AF_INET;
   88: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
   89:   sin_dest.sin_len = sizeof (struct sockaddr_in);
   90: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
   91:   sin_dest.sin_addr = p->u.prefix4;
   92: 
   93:   memset (&sin_mask, 0, sizeof (struct sockaddr_in));
   94: 
   95:   memset (&sin_gate, 0, sizeof (struct sockaddr_in));
   96:   sin_gate.sin_family = AF_INET;
   97: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
   98:   sin_gate.sin_len = sizeof (struct sockaddr_in);
   99: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  100: 
  101:   /* Make gateway. */
  102:   for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  103:     {
  104:       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  105:         continue;
  106: 
  107:       gate = 0;
  108:       char gate_buf[INET_ADDRSTRLEN] = "NULL";
  109: 
  110:       /*
  111:        * XXX We need to refrain from kernel operations in some cases,
  112:        * but this if statement seems overly cautious - what about
  113:        * other than ADD and DELETE?
  114:        */
  115:       if ((cmd == RTM_ADD
  116: 	   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  117: 	  || (cmd == RTM_DELETE
  118: 	      && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  119: 	      ))
  120: 	{
  121: 	  if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
  122: 	      nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  123: 	    {
  124: 	      sin_gate.sin_addr = nexthop->gate.ipv4;
  125: 	      gate = 1;
  126: 	    }
  127: 	  if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  128: 	      || nexthop->type == NEXTHOP_TYPE_IFNAME
  129: 	      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  130: 	    ifindex = nexthop->ifindex;
  131: 	  if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
  132: 	    {
  133: 	      struct in_addr loopback;
  134: 	      loopback.s_addr = htonl (INADDR_LOOPBACK);
  135: 	      sin_gate.sin_addr = loopback;
  136: 	      gate = 1;
  137: 	    }
  138: 
  139: 	  if (gate && p->prefixlen == 32)
  140: 	    mask = NULL;
  141: 	  else
  142: 	    {
  143: 	      masklen2ip (p->prefixlen, &sin_mask.sin_addr);
  144: 	      sin_mask.sin_family = AF_INET;
  145: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  146: 	      sin_mask.sin_len = sin_masklen (sin_mask.sin_addr);
  147: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  148: 	      mask = &sin_mask;
  149: 	    }
  150: 
  151: 	  error = rtm_write (cmd,
  152: 			     (union sockunion *)&sin_dest, 
  153: 			     (union sockunion *)mask, 
  154: 			     gate ? (union sockunion *)&sin_gate : NULL,
  155: 			     ifindex,
  156: 			     rib->flags,
  157: 			     rib->metric);
  158: 
  159:            if (IS_ZEBRA_DEBUG_RIB)
  160:            {
  161:              if (!gate)
  162:              {
  163:                zlog_debug ("%s: %s: attention! gate not found for rib %p",
  164:                  __func__, prefix_buf, rib);
  165:                rib_dump (p, rib);
  166:              }
  167:              else
  168:                inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN);
  169:            }
  170:  
  171:            switch (error)
  172:            {
  173:              /* We only flag nexthops as being in FIB if rtm_write() did its work. */
  174:              case ZEBRA_ERR_NOERROR:
  175:                nexthop_num++;
  176:                if (IS_ZEBRA_DEBUG_RIB)
  177:                  zlog_debug ("%s: %s: successfully did NH %s",
  178:                    __func__, prefix_buf, gate_buf);
  179:                if (cmd == RTM_ADD)
  180:                  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  181:                break;
  182:  
  183:              /* The only valid case for this error is kernel's failure to install
  184:               * a multipath route, which is common for FreeBSD. This should be
  185:               * ignored silently, but logged as an error otherwise.
  186:               */
  187:              case ZEBRA_ERR_RTEXIST:
  188:                if (cmd != RTM_ADD)
  189:                  zlog_err ("%s: rtm_write() returned %d for command %d",
  190:                    __func__, error, cmd);
  191:                continue;
  192:                break;
  193:  
  194:              /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't
  195:               * normal to get any other messages in ANY case.
  196:               */
  197:              case ZEBRA_ERR_RTNOEXIST:
  198:              case ZEBRA_ERR_RTUNREACH:
  199:              default:
  200:                zlog_err ("%s: %s: rtm_write() unexpectedly returned %d for command %s",
  201:                  __func__, prefix2str(p, prefix_buf, sizeof(prefix_buf)),
  202:                  error, lookup (rtm_type_str, cmd));
  203:                break;
  204:            }
  205:          } /* if (cmd and flags make sense) */
  206:        else
  207:          if (IS_ZEBRA_DEBUG_RIB)
  208:            zlog_debug ("%s: odd command %s for flags %d",
  209:              __func__, lookup (rtm_type_str, cmd), nexthop->flags);
  210:      } /* for (ALL_NEXTHOPS_RO(...))*/
  211:  
  212:    /* If there was no useful nexthop, then complain. */
  213:    if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL)
  214:      zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, rib);
  215: 
  216:   return 0; /*XXX*/
  217: }
  218: 
  219: #ifdef HAVE_IPV6
  220: 
  221: #ifdef SIN6_LEN
  222: /* Calculate sin6_len value for netmask socket value. */
  223: static int
  224: sin6_masklen (struct in6_addr mask)
  225: {
  226:   struct sockaddr_in6 sin6;
  227:   char *p, *lim;
  228:   int len;
  229: 
  230:   if (IN6_IS_ADDR_UNSPECIFIED (&mask)) 
  231:     return sizeof (long);
  232: 
  233:   sin6.sin6_addr = mask;
  234:   len = sizeof (struct sockaddr_in6);
  235: 
  236:   lim = (char *) & sin6.sin6_addr;
  237:   p = lim + sizeof (sin6.sin6_addr);
  238: 
  239:   while (*--p == 0 && p >= lim) 
  240:     len--;
  241: 
  242:   return len;
  243: }
  244: #endif /* SIN6_LEN */
  245: 
  246: /* Interface between zebra message and rtm message. */
  247: static int
  248: kernel_rtm_ipv6 (int cmd, struct prefix *p, struct rib *rib)
  249: {
  250:   struct sockaddr_in6 *mask;
  251:   struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
  252:   struct nexthop *nexthop, *tnexthop;
  253:   int recursing;
  254:   int nexthop_num = 0;
  255:   ifindex_t ifindex = 0;
  256:   int gate = 0;
  257:   int error;
  258: 
  259:   memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
  260:   sin_dest.sin6_family = AF_INET6;
  261: #ifdef SIN6_LEN
  262:   sin_dest.sin6_len = sizeof (struct sockaddr_in6);
  263: #endif /* SIN6_LEN */
  264:   sin_dest.sin6_addr = p->u.prefix6;
  265: 
  266:   memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
  267: 
  268:   memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
  269:   sin_gate.sin6_family = AF_INET6;
  270: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  271:   sin_gate.sin6_len = sizeof (struct sockaddr_in6);
  272: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  273: 
  274:   /* Make gateway. */
  275:   for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  276:     {
  277:       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  278: 	continue;
  279: 
  280:       gate = 0;
  281: 
  282:       if ((cmd == RTM_ADD
  283: 	   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  284: 	  || (cmd == RTM_DELETE
  285: #if 0
  286: 	      && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  287: #endif
  288: 	      ))
  289: 	{
  290: 	  if (nexthop->type == NEXTHOP_TYPE_IPV6
  291: 	      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  292: 	      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  293: 	    {
  294: 	      sin_gate.sin6_addr = nexthop->gate.ipv6;
  295: 	      gate = 1;
  296: 	    }
  297: 	  if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  298: 	      || nexthop->type == NEXTHOP_TYPE_IFNAME
  299: 	      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  300: 	      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  301: 	    ifindex = nexthop->ifindex;
  302: 
  303: 	  if (cmd == RTM_ADD)
  304: 	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  305: 	}
  306: 
  307:       /* Under kame set interface index to link local address. */
  308: #ifdef KAME
  309: 
  310: #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
  311:       do { \
  312: 	(a).s6_addr[2] = ((i) >> 8) & 0xff; \
  313: 	(a).s6_addr[3] = (i) & 0xff; \
  314:       } while (0)
  315: 
  316:       if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr))
  317: 	SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex);
  318: #endif /* KAME */
  319: 
  320:       if (gate && p->prefixlen == 128)
  321: 	mask = NULL;
  322:       else
  323: 	{
  324: 	  masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr);
  325: 	  sin_mask.sin6_family = AF_INET6;
  326: #ifdef SIN6_LEN
  327: 	  sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
  328: #endif /* SIN6_LEN */
  329: 	  mask = &sin_mask;
  330: 	}
  331: 
  332:       error = rtm_write (cmd,
  333: 			(union sockunion *) &sin_dest,
  334: 			(union sockunion *) mask,
  335: 			gate ? (union sockunion *)&sin_gate : NULL,
  336: 			ifindex,
  337: 			rib->flags,
  338: 			rib->metric);
  339: 
  340: #if 0
  341:       if (error)
  342: 	{
  343: 	  zlog_info ("kernel_rtm_ipv6(): nexthop %d add error=%d.",
  344: 	    nexthop_num, error);
  345: 	}
  346: #else
  347:       (void)error;
  348: #endif
  349: 
  350:       nexthop_num++;
  351:     }
  352: 
  353:   /* If there is no useful nexthop then return. */
  354:   if (nexthop_num == 0)
  355:     {
  356:       if (IS_ZEBRA_DEBUG_KERNEL)
  357: 	zlog_debug ("kernel_rtm_ipv6(): No useful nexthop.");
  358:       return 0;
  359:     }
  360: 
  361:   return 0; /*XXX*/
  362: }
  363: 
  364: #endif
  365: 
  366: static int
  367: kernel_rtm (int cmd, struct prefix *p, struct rib *rib)
  368: {
  369:   switch (PREFIX_FAMILY(p))
  370:     {
  371:     case AF_INET:
  372:       return kernel_rtm_ipv4 (cmd, p, rib);
  373:     case AF_INET6:
  374:       return kernel_rtm_ipv6 (cmd, p, rib);
  375:     }
  376:   return 0;
  377: }
  378: 
  379: int
  380: kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
  381: {
  382:   int route = 0;
  383: 
  384:   if (zserv_privs.change(ZPRIVS_RAISE))
  385:     zlog (NULL, LOG_ERR, "Can't raise privileges");
  386: 
  387:   if (old)
  388:     route |= kernel_rtm (RTM_DELETE, p, old);
  389: 
  390:   if (new)
  391:     route |= kernel_rtm (RTM_ADD, p, new);
  392: 
  393:   if (zserv_privs.change(ZPRIVS_LOWER))
  394:     zlog (NULL, LOG_ERR, "Can't lower privileges");
  395: 
  396:   return route;
  397: }

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