Annotation of embedaddon/quagga/zebra/rt_socket.c, revision 1.1.1.2

1.1       misho       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: 
1.1.1.2 ! misho      44: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1.1       misho      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: }
1.1.1.2 ! misho      67: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1.1       misho      68: 
                     69: /* Interface between zebra message and rtm message. */
                     70: static int
1.1.1.2 ! misho      71: kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib)
1.1       misho      72: 
                     73: {
                     74:   struct sockaddr_in *mask = NULL;
                     75:   struct sockaddr_in sin_dest, sin_mask, sin_gate;
1.1.1.2 ! misho      76:   struct nexthop *nexthop, *tnexthop;
        !            77:   int recursing;
1.1       misho      78:   int nexthop_num = 0;
1.1.1.2 ! misho      79:   ifindex_t ifindex = 0;
1.1       misho      80:   int gate = 0;
                     81:   int error;
1.1.1.2 ! misho      82:   char prefix_buf[PREFIX_STRLEN];
1.1       misho      83: 
                     84:   if (IS_ZEBRA_DEBUG_RIB)
1.1.1.2 ! misho      85:     prefix2str (p, prefix_buf, sizeof(prefix_buf));
1.1       misho      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. */
1.1.1.2 ! misho     102:   for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1.1       misho     103:     {
1.1.1.2 ! misho     104:       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
        !           105:         continue;
        !           106: 
1.1       misho     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:        {
1.1.1.2 ! misho     121:          if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
        !           122:              nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1.1       misho     123:            {
1.1.1.2 ! misho     124:              sin_gate.sin_addr = nexthop->gate.ipv4;
        !           125:              gate = 1;
1.1       misho     126:            }
1.1.1.2 ! misho     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)
1.1       misho     132:            {
1.1.1.2 ! misho     133:              struct in_addr loopback;
        !           134:              loopback.s_addr = htonl (INADDR_LOOPBACK);
        !           135:              sin_gate.sin_addr = loopback;
        !           136:              gate = 1;
1.1       misho     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:              {
1.1.1.2 ! misho     163:                zlog_debug ("%s: %s: attention! gate not found for rib %p",
        !           164:                  __func__, prefix_buf, rib);
        !           165:                rib_dump (p, rib);
1.1       misho     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)
1.1.1.2 ! misho     177:                  zlog_debug ("%s: %s: successfully did NH %s",
        !           178:                    __func__, prefix_buf, gate_buf);
1.1       misho     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:
1.1.1.2 ! misho     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));
1.1       misho     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);
1.1.1.2 ! misho     210:      } /* for (ALL_NEXTHOPS_RO(...))*/
1.1       misho     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: 
1.1.1.2 ! misho     221: #ifdef SIN6_LEN
1.1       misho     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
1.1.1.2 ! misho     248: kernel_rtm_ipv6 (int cmd, struct prefix *p, struct rib *rib)
1.1       misho     249: {
                    250:   struct sockaddr_in6 *mask;
                    251:   struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
1.1.1.2 ! misho     252:   struct nexthop *nexthop, *tnexthop;
        !           253:   int recursing;
1.1       misho     254:   int nexthop_num = 0;
1.1.1.2 ! misho     255:   ifindex_t ifindex = 0;
1.1       misho     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. */
1.1.1.2 ! misho     275:   for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1.1       misho     276:     {
1.1.1.2 ! misho     277:       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
        !           278:        continue;
        !           279: 
1.1       misho     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:        {
1.1.1.2 ! misho     290:          if (nexthop->type == NEXTHOP_TYPE_IPV6
        !           291:              || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
        !           292:              || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1.1       misho     293:            {
1.1.1.2 ! misho     294:              sin_gate.sin6_addr = nexthop->gate.ipv6;
        !           295:              gate = 1;
1.1       misho     296:            }
1.1.1.2 ! misho     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;
1.1       misho     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:        {
1.1.1.2 ! misho     343:          zlog_info ("kernel_rtm_ipv6(): nexthop %d add error=%d.",
1.1       misho     344:            nexthop_num, error);
                    345:        }
1.1.1.2 ! misho     346: #else
        !           347:       (void)error;
1.1       misho     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)
1.1.1.2 ! misho     357:        zlog_debug ("kernel_rtm_ipv6(): No useful nexthop.");
1.1       misho     358:       return 0;
                    359:     }
                    360: 
                    361:   return 0; /*XXX*/
                    362: }
                    363: 
1.1.1.2 ! misho     364: #endif
1.1       misho     365: 
1.1.1.2 ! misho     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;
1.1       misho     377: }
                    378: 
                    379: int
1.1.1.2 ! misho     380: kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
1.1       misho     381: {
1.1.1.2 ! misho     382:   int route = 0;
1.1       misho     383: 
                    384:   if (zserv_privs.change(ZPRIVS_RAISE))
                    385:     zlog (NULL, LOG_ERR, "Can't raise privileges");
                    386: 
1.1.1.2 ! misho     387:   if (old)
        !           388:     route |= kernel_rtm (RTM_DELETE, p, old);
1.1       misho     389: 
1.1.1.2 ! misho     390:   if (new)
        !           391:     route |= kernel_rtm (RTM_ADD, p, new);
1.1       misho     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>