File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / kernel_socket.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: /* Kernel communication using routing socket.
    2:  * Copyright (C) 1999 Kunihiro Ishiguro
    3:  *
    4:  * This file is part of GNU Zebra.
    5:  *
    6:  * GNU Zebra is free software; you can redistribute it and/or modify it
    7:  * under the terms of the GNU General Public License as published by the
    8:  * Free Software Foundation; either version 2, or (at your option) any
    9:  * later version.
   10:  *
   11:  * GNU Zebra is distributed in the hope that it will be useful, but
   12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU General Public License
   17:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
   18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19:  * 02111-1307, USA.  
   20:  */
   21: 
   22: #include <zebra.h>
   23: 
   24: #include "if.h"
   25: #include "prefix.h"
   26: #include "sockunion.h"
   27: #include "connected.h"
   28: #include "memory.h"
   29: #include "ioctl.h"
   30: #include "log.h"
   31: #include "str.h"
   32: #include "table.h"
   33: #include "rib.h"
   34: #include "privs.h"
   35: 
   36: #include "zebra/interface.h"
   37: #include "zebra/zserv.h"
   38: #include "zebra/debug.h"
   39: #include "zebra/kernel_socket.h"
   40: 
   41: extern struct zebra_privs_t zserv_privs;
   42: extern struct zebra_t zebrad;
   43: 
   44: /*
   45:  * Given a sockaddr length, round it up to include pad bytes following
   46:  * it.  Assumes the kernel pads to sizeof(long).
   47:  *
   48:  * XXX: why is ROUNDUP(0) sizeof(long)?  0 is an illegal sockaddr
   49:  * length anyway (< sizeof (struct sockaddr)), so this shouldn't
   50:  * matter.
   51:  * On OS X, both 32, 64bit syatems align on 4 byte boundary
   52:  */
   53: #ifdef __APPLE__
   54: #define ROUNDUP(a) \
   55:   ((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))
   56: #else
   57: #define ROUNDUP(a) \
   58:   ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
   59: #endif
   60: 
   61: /*
   62:  * Given a pointer (sockaddr or void *), return the number of bytes
   63:  * taken up by the sockaddr and any padding needed for alignment.
   64:  */
   65: #if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
   66: #define SAROUNDUP(X)   ROUNDUP(((struct sockaddr *)(X))->sa_len)
   67: #elif defined(HAVE_IPV6)
   68: /*
   69:  * One would hope all fixed-size structure definitions are aligned,
   70:  * but round them up nonetheless.
   71:  */
   72: #define SAROUNDUP(X) \
   73:     (((struct sockaddr *)(X))->sa_family == AF_INET ?   \
   74:       ROUNDUP(sizeof(struct sockaddr_in)):\
   75:       (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \
   76:        ROUNDUP(sizeof(struct sockaddr_in6)) :  \
   77:        (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
   78:          ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr))))
   79: #else /* HAVE_IPV6 */ 
   80: #define SAROUNDUP(X) \
   81:       (((struct sockaddr *)(X))->sa_family == AF_INET ?   \
   82:         ROUNDUP(sizeof(struct sockaddr_in)):\
   83:          (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
   84:            ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))
   85: #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
   86: 
   87: /*
   88:  * We use a call to an inline function to copy (PNT) to (DEST)
   89:  * 1. Calculating the length of the copy requires an #ifdef to determine
   90:  *    if sa_len is a field and can't be used directly inside a #define
   91:  * 2. So the compiler doesn't complain when DEST is NULL, which is only true
   92:  *    when we are skipping the copy and incrementing to the next SA
   93:  */
   94: static void inline
   95: rta_copy (union sockunion *dest, caddr_t src) {
   96:   int len;
   97: #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   98:   len = (((struct sockaddr *)src)->sa_len > sizeof (*dest)) ?
   99:             sizeof (*dest) : ((struct sockaddr *)src)->sa_len ;
  100: #else
  101:   len = (SAROUNDUP (src) > sizeof (*dest)) ?
  102:             sizeof (*dest) : SAROUNDUP (src) ;
  103: #endif
  104:   memcpy (dest, src, len);
  105: }
  106: 
  107: #define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \
  108:   if ((RTMADDRS) & (RTA)) \
  109:     { \
  110:       int len = SAROUNDUP ((PNT)); \
  111:       if ( ((DEST) != NULL) && \
  112:            af_check (((struct sockaddr *)(PNT))->sa_family)) \
  113:         rta_copy((DEST), (PNT)); \
  114:       (PNT) += len; \
  115:     }
  116: #define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \
  117:   if ((RTMADDRS) & (RTA)) \
  118:     { \
  119:       int len = SAROUNDUP ((PNT)); \
  120:       if ((DEST) != NULL) \
  121:         rta_copy((DEST), (PNT)); \
  122:       (PNT) += len; \
  123:     }
  124: 
  125: #define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \
  126:   if ((RTMADDRS) & (RTA)) \
  127:     { \
  128:       u_char *pdest = (u_char *) (DEST); \
  129:       int len = SAROUNDUP ((PNT)); \
  130:       struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \
  131:       if (IS_ZEBRA_DEBUG_KERNEL) \
  132:         zlog_debug ("%s: RTA_SDL_GET nlen %d, alen %d", \
  133:                     __func__, sdl->sdl_nlen, sdl->sdl_alen); \
  134:       if ( ((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \
  135:            && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len) ) \
  136:         { \
  137:           memcpy (pdest, sdl->sdl_data, sdl->sdl_nlen); \
  138:           pdest[sdl->sdl_nlen] = '\0'; \
  139:           (LEN) = sdl->sdl_nlen; \
  140:         } \
  141:       (PNT) += len; \
  142:     } \
  143:   else \
  144:     { \
  145:       (LEN) = 0; \
  146:     }
  147: /* Routing socket message types. */
  148: const struct message rtm_type_str[] =
  149: {
  150:   {RTM_ADD,      "RTM_ADD"},
  151:   {RTM_DELETE,   "RTM_DELETE"},
  152:   {RTM_CHANGE,   "RTM_CHANGE"},
  153:   {RTM_GET,      "RTM_GET"},
  154:   {RTM_LOSING,   "RTM_LOSING"},
  155:   {RTM_REDIRECT, "RTM_REDIRECT"},
  156:   {RTM_MISS,     "RTM_MISS"},
  157:   {RTM_LOCK,     "RTM_LOCK"},
  158: #ifdef OLDADD
  159:   {RTM_OLDADD,   "RTM_OLDADD"},
  160: #endif /* RTM_OLDADD */
  161: #ifdef RTM_OLDDEL
  162:   {RTM_OLDDEL,   "RTM_OLDDEL"},
  163: #endif /* RTM_OLDDEL */
  164:   {RTM_RESOLVE,  "RTM_RESOLVE"},
  165:   {RTM_NEWADDR,  "RTM_NEWADDR"},
  166:   {RTM_DELADDR,  "RTM_DELADDR"},
  167:   {RTM_IFINFO,   "RTM_IFINFO"},
  168: #ifdef RTM_OIFINFO
  169:   {RTM_OIFINFO,   "RTM_OIFINFO"},
  170: #endif /* RTM_OIFINFO */
  171: #ifdef RTM_NEWMADDR
  172:   {RTM_NEWMADDR, "RTM_NEWMADDR"},
  173: #endif /* RTM_NEWMADDR */
  174: #ifdef RTM_DELMADDR
  175:   {RTM_DELMADDR, "RTM_DELMADDR"},
  176: #endif /* RTM_DELMADDR */
  177: #ifdef RTM_IFANNOUNCE
  178:   {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
  179: #endif /* RTM_IFANNOUNCE */
  180:   {0,            NULL}
  181: };
  182: 
  183: static const struct message rtm_flag_str[] =
  184: {
  185:   {RTF_UP,        "UP"},
  186:   {RTF_GATEWAY,   "GATEWAY"},
  187:   {RTF_HOST,      "HOST"},
  188:   {RTF_REJECT,    "REJECT"},
  189:   {RTF_DYNAMIC,   "DYNAMIC"},
  190:   {RTF_MODIFIED,  "MODIFIED"},
  191:   {RTF_DONE,      "DONE"},
  192: #ifdef RTF_MASK
  193:   {RTF_MASK,      "MASK"},
  194: #endif /* RTF_MASK */
  195: #ifdef RTF_CLONING
  196:   {RTF_CLONING,   "CLONING"},
  197: #endif /* RTF_CLONING */
  198:   {RTF_XRESOLVE,  "XRESOLVE"},
  199:   {RTF_LLINFO,    "LLINFO"},
  200:   {RTF_STATIC,    "STATIC"},
  201:   {RTF_BLACKHOLE, "BLACKHOLE"},
  202: #ifdef RTF_PRIVATE
  203:   {RTF_PRIVATE,	  "PRIVATE"},
  204: #endif /* RTF_PRIVATE */
  205:   {RTF_PROTO1,    "PROTO1"},
  206:   {RTF_PROTO2,    "PROTO2"},
  207: #ifdef RTF_PRCLONING
  208:   {RTF_PRCLONING, "PRCLONING"},
  209: #endif /* RTF_PRCLONING */
  210: #ifdef RTF_WASCLONED
  211:   {RTF_WASCLONED, "WASCLONED"},
  212: #endif /* RTF_WASCLONED */
  213: #ifdef RTF_PROTO3
  214:   {RTF_PROTO3,    "PROTO3"},
  215: #endif /* RTF_PROTO3 */
  216: #ifdef RTF_PINNED
  217:   {RTF_PINNED,    "PINNED"},
  218: #endif /* RTF_PINNED */
  219: #ifdef RTF_LOCAL
  220:   {RTF_LOCAL,    "LOCAL"},
  221: #endif /* RTF_LOCAL */
  222: #ifdef RTF_BROADCAST
  223:   {RTF_BROADCAST, "BROADCAST"},
  224: #endif /* RTF_BROADCAST */
  225: #ifdef RTF_MULTICAST
  226:   {RTF_MULTICAST, "MULTICAST"},
  227: #endif /* RTF_MULTICAST */
  228: #ifdef RTF_MULTIRT
  229:   {RTF_MULTIRT,   "MULTIRT"},
  230: #endif /* RTF_MULTIRT */
  231: #ifdef RTF_SETSRC
  232:   {RTF_SETSRC,    "SETSRC"},
  233: #endif /* RTF_SETSRC */
  234:   {0,             NULL}
  235: };
  236: 
  237: /* Kernel routing update socket. */
  238: int routing_sock = -1;
  239: 
  240: /* Yes I'm checking ugly routing socket behavior. */
  241: /* #define DEBUG */
  242: 
  243: /* Supported address family check. */
  244: static int inline
  245: af_check (int family)
  246: {
  247:   if (family == AF_INET)
  248:     return 1;
  249: #ifdef HAVE_IPV6
  250:   if (family == AF_INET6)
  251:     return 1;
  252: #endif /* HAVE_IPV6 */
  253:   return 0;
  254: }
  255: 
  256: /* Dump routing table flag for debug purpose. */
  257: static void
  258: rtm_flag_dump (int flag)
  259: {
  260:   const struct message *mes;
  261:   static char buf[BUFSIZ];
  262: 
  263:   buf[0] = '\0';
  264:   for (mes = rtm_flag_str; mes->key != 0; mes++)
  265:     {
  266:       if (mes->key & flag)
  267: 	{
  268: 	  strlcat (buf, mes->str, BUFSIZ);
  269: 	  strlcat (buf, " ", BUFSIZ);
  270: 	}
  271:     }
  272:   zlog_debug ("Kernel: %s", buf);
  273: }
  274: 
  275: #ifdef RTM_IFANNOUNCE
  276: /* Interface adding function */
  277: static int
  278: ifan_read (struct if_announcemsghdr *ifan)
  279: {
  280:   struct interface *ifp;
  281:   
  282:   ifp = if_lookup_by_index (ifan->ifan_index);
  283:   
  284:   if (ifp)
  285:     assert ( (ifp->ifindex == ifan->ifan_index) 
  286:              || (ifp->ifindex == IFINDEX_INTERNAL) );
  287: 
  288:   if ( (ifp == NULL) 
  289:       || ((ifp->ifindex == IFINDEX_INTERNAL)
  290:           && (ifan->ifan_what == IFAN_ARRIVAL)) )
  291:     {
  292:       if (IS_ZEBRA_DEBUG_KERNEL)
  293:         zlog_debug ("%s: creating interface for ifindex %d, name %s",
  294:                     __func__, ifan->ifan_index, ifan->ifan_name);
  295:       
  296:       /* Create Interface */
  297:       ifp = if_get_by_name_len(ifan->ifan_name,
  298: 			       strnlen(ifan->ifan_name,
  299: 				       sizeof(ifan->ifan_name)));
  300:       ifp->ifindex = ifan->ifan_index;
  301: 
  302:       if_add_update (ifp);
  303:     }
  304:   else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
  305:     if_delete_update (ifp);
  306: 
  307:   if_get_flags (ifp);
  308:   if_get_mtu (ifp);
  309:   if_get_metric (ifp);
  310: 
  311:   if (IS_ZEBRA_DEBUG_KERNEL)
  312:     zlog_debug ("%s: interface %s index %d", 
  313:                 __func__, ifan->ifan_name, ifan->ifan_index);
  314: 
  315:   return 0;
  316: }
  317: #endif /* RTM_IFANNOUNCE */
  318: 
  319: #ifdef HAVE_BSD_IFI_LINK_STATE
  320: /* BSD link detect translation */
  321: static void
  322: bsd_linkdetect_translate (struct if_msghdr *ifm)
  323: {
  324:   if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) ||
  325:       (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
  326:     SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
  327:   else
  328:     UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
  329: }
  330: #endif /* HAVE_BSD_IFI_LINK_STATE */
  331: 
  332: /*
  333:  * Handle struct if_msghdr obtained from reading routing socket or
  334:  * sysctl (from interface_list).  There may or may not be sockaddrs
  335:  * present after the header.
  336:  */
  337: int
  338: ifm_read (struct if_msghdr *ifm)
  339: {
  340:   struct interface *ifp = NULL;
  341:   struct sockaddr_dl *sdl;
  342:   char ifname[IFNAMSIZ];
  343:   short ifnlen = 0;
  344:   caddr_t cp;
  345:   
  346:   /* terminate ifname at head (for strnlen) and tail (for safety) */
  347:   ifname[IFNAMSIZ - 1] = '\0';
  348:   
  349:   /* paranoia: sanity check structure */
  350:   if (ifm->ifm_msglen < sizeof(struct if_msghdr))
  351:     {
  352:       zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
  353: 		ifm->ifm_msglen);
  354:       return -1;
  355:     }
  356: 
  357:   /*
  358:    * Check for a sockaddr_dl following the message.  First, point to
  359:    * where a socakddr might be if one follows the message.
  360:    */
  361:   cp = (void *)(ifm + 1);
  362: 
  363: #ifdef SUNOS_5
  364:   /* 
  365:    * XXX This behavior should be narrowed to only the kernel versions
  366:    * for which the structures returned do not match the headers.
  367:    *
  368:    * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
  369:    * is 12 bytes larger than the 32 bit version.
  370:    */
  371:   if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC)
  372:   	cp = cp + 12;
  373: #endif
  374: 
  375:   RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp);
  376:   RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
  377:   RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
  378:   RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
  379:   sdl = (struct sockaddr_dl *)cp;
  380:   RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
  381:   RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
  382:   RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
  383:   RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp);
  384:   
  385:   if (IS_ZEBRA_DEBUG_KERNEL)
  386:     zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)"));
  387:   
  388:   /* 
  389:    * Look up on ifindex first, because ifindices are the primary handle for
  390:    * interfaces across the user/kernel boundary, for most systems.  (Some
  391:    * messages, such as up/down status changes on NetBSD, do not include a
  392:    * sockaddr_dl).
  393:    */
  394:   if ( (ifp = if_lookup_by_index (ifm->ifm_index)) != NULL )
  395:     {
  396:       /* we have an ifp, verify that the name matches as some systems,
  397:        * eg Solaris, have a 1:many association of ifindex:ifname
  398:        * if they dont match, we dont have the correct ifp and should
  399:        * set it back to NULL to let next check do lookup by name
  400:        */
  401:       if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) )
  402:         {
  403:           if (IS_ZEBRA_DEBUG_KERNEL)
  404:             zlog_debug ("%s: ifp name %s doesnt match sdl name %s",
  405:                         __func__, ifp->name, ifname);
  406:           ifp = NULL;
  407:         }
  408:     }
  409:   
  410:   /* 
  411:    * If we dont have an ifp, try looking up by name.  Particularly as some
  412:    * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname
  413:    * is therefore our unique handle to that interface.
  414:    *
  415:    * Interfaces specified in the configuration file for which the ifindex
  416:    * has not been determined will have ifindex == IFINDEX_INTERNAL, and such
  417:    * interfaces are found by this search, and then their ifindex values can
  418:    * be filled in.
  419:    */
  420:   if ( (ifp == NULL) && ifnlen)
  421:     ifp = if_lookup_by_name (ifname);
  422: 
  423:   /*
  424:    * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL),
  425:    * create or fill in an interface.
  426:    */
  427:   if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL))
  428:     {
  429:       /*
  430:        * To create or fill in an interface, a sockaddr_dl (via
  431:        * RTA_IFP) is required.
  432:        */
  433:       if (!ifnlen)
  434: 	{
  435: 	  zlog_warn ("Interface index %d (new) missing ifname\n",
  436: 		     ifm->ifm_index);
  437: 	  return -1;
  438: 	}
  439: 
  440: #ifndef RTM_IFANNOUNCE
  441:       /* Down->Down interface should be ignored here.
  442:        * See further comment below.
  443:        */
  444:       if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP))
  445:         return 0;
  446: #endif /* !RTM_IFANNOUNCE */
  447:       
  448:       if (ifp == NULL)
  449:         {
  450: 	  /* Interface that zebra was not previously aware of, so create. */ 
  451: 	  ifp = if_create (ifname, ifnlen);
  452: 	  if (IS_ZEBRA_DEBUG_KERNEL)
  453: 	    zlog_debug ("%s: creating ifp for ifindex %d", 
  454: 	                __func__, ifm->ifm_index);
  455:         }
  456: 
  457:       if (IS_ZEBRA_DEBUG_KERNEL)
  458:         zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d",
  459:                     __func__, ifp->name, ifp->ifindex);
  460:       /* 
  461:        * Fill in newly created interface structure, or larval
  462:        * structure with ifindex IFINDEX_INTERNAL.
  463:        */
  464:       ifp->ifindex = ifm->ifm_index;
  465:       
  466: #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
  467:       bsd_linkdetect_translate(ifm);
  468: #endif /* HAVE_BSD_IFI_LINK_STATE */
  469: 
  470:       if_flags_update (ifp, ifm->ifm_flags);
  471: #if defined(__bsdi__)
  472:       if_kvm_get_mtu (ifp);
  473: #else
  474:       if_get_mtu (ifp);
  475: #endif /* __bsdi__ */
  476:       if_get_metric (ifp);
  477: 
  478:       /*
  479:        * XXX sockaddr_dl contents can be larger than the structure
  480:        * definition.  There are 2 big families here:
  481:        *  - BSD has sdl_len + sdl_data[16] + overruns sdl_data
  482:        *    we MUST use sdl_len here or we'll truncate data.
  483:        *  - Solaris has no sdl_len, but sdl_data[244]
  484:        *    presumably, it's not going to run past that, so sizeof()
  485:        *    is fine here.
  486:        * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
  487:        */
  488:       if (ifnlen)
  489:       {
  490: #ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN
  491: 	memcpy (&ifp->sdl, sdl, sdl->sdl_len);
  492: #else
  493: 	memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl));
  494: #endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */
  495:       }
  496: 
  497:       if_add_update (ifp);
  498:     }
  499:   else
  500:     /*
  501:      * Interface structure exists.  Adjust stored flags from
  502:      * notification.  If interface has up->down or down->up
  503:      * transition, call state change routines (to adjust routes,
  504:      * notify routing daemons, etc.).  (Other flag changes are stored
  505:      * but apparently do not trigger action.)
  506:      */
  507:     {
  508:       if (ifp->ifindex != ifm->ifm_index)
  509:         {
  510:           zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, "
  511:                      "ifm index %d", 
  512:                      __func__, ifp->name, ifp->ifindex, ifm->ifm_index);
  513:           return -1;
  514:         }
  515:       
  516: #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
  517:       bsd_linkdetect_translate(ifm);
  518: #endif /* HAVE_BSD_IFI_LINK_STATE */
  519: 
  520:       /* update flags and handle operative->inoperative transition, if any */
  521:       if_flags_update (ifp, ifm->ifm_flags);
  522:       
  523: #ifndef RTM_IFANNOUNCE
  524:       if (!if_is_up (ifp))
  525:           {
  526:             /* No RTM_IFANNOUNCE on this platform, so we can never
  527:              * distinguish between ~IFF_UP and delete. We must presume
  528:              * it has been deleted.
  529:              * Eg, Solaris will not notify us of unplumb.
  530:              *
  531:              * XXX: Fixme - this should be runtime detected
  532:              * So that a binary compiled on a system with IFANNOUNCE
  533:              * will still behave correctly if run on a platform without
  534:              */
  535:             if_delete_update (ifp);
  536:           }
  537: #endif /* RTM_IFANNOUNCE */
  538:       if (if_is_up (ifp))
  539:       {
  540: #if defined(__bsdi__)
  541:         if_kvm_get_mtu (ifp);
  542: #else
  543:         if_get_mtu (ifp);
  544: #endif /* __bsdi__ */
  545:         if_get_metric (ifp);
  546:       }
  547:     }
  548: 
  549: #ifdef HAVE_NET_RT_IFLIST
  550:   ifp->stats = ifm->ifm_data;
  551: #endif /* HAVE_NET_RT_IFLIST */
  552: 
  553:   if (IS_ZEBRA_DEBUG_KERNEL)
  554:     zlog_debug ("%s: interface %s index %d", 
  555:                 __func__, ifp->name, ifp->ifindex);
  556: 
  557:   return 0;
  558: }
  559: 
  560: /* Address read from struct ifa_msghdr. */
  561: static void
  562: ifam_read_mesg (struct ifa_msghdr *ifm,
  563: 		union sockunion *addr,
  564: 		union sockunion *mask,
  565: 		union sockunion *brd,
  566: 		char *ifname,
  567: 		short *ifnlen)
  568: {
  569:   caddr_t pnt, end;
  570:   union sockunion dst;
  571:   union sockunion gateway;
  572: 
  573:   pnt = (caddr_t)(ifm + 1);
  574:   end = ((caddr_t)ifm) + ifm->ifam_msglen;
  575: 
  576:   /* Be sure structure is cleared */
  577:   memset (mask, 0, sizeof (union sockunion));
  578:   memset (addr, 0, sizeof (union sockunion));
  579:   memset (brd, 0, sizeof (union sockunion));
  580:   memset (&dst, 0, sizeof (union sockunion));
  581:   memset (&gateway, 0, sizeof (union sockunion));
  582: 
  583:   /* We fetch each socket variable into sockunion. */
  584:   RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
  585:   RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
  586:   RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
  587:   RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
  588:   RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
  589:   RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
  590:   RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
  591:   RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);
  592: 
  593:   if (IS_ZEBRA_DEBUG_KERNEL)
  594:     {
  595:       switch (sockunion_family(addr))
  596:         {
  597: 	case AF_INET:
  598: 	  {
  599: 	    char buf[4][INET_ADDRSTRLEN];
  600: 	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
  601: 			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
  602: 			"gateway %s",
  603: 			__func__, ifm->ifam_index,
  604: 			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
  605: 			ifm->ifam_flags,
  606: 			inet_ntop(AF_INET,&addr->sin.sin_addr,
  607: 			          buf[0],sizeof(buf[0])),
  608: 			ip_masklen(mask->sin.sin_addr),
  609: 			inet_ntop(AF_INET,&brd->sin.sin_addr,
  610: 			          buf[1],sizeof(buf[1])),
  611: 			inet_ntop(AF_INET,&dst.sin.sin_addr,
  612: 			          buf[2],sizeof(buf[2])),
  613: 			inet_ntop(AF_INET,&gateway.sin.sin_addr,
  614: 			          buf[3],sizeof(buf[3])));
  615: 	  }
  616: 	  break;
  617: #ifdef HAVE_IPV6
  618: 	case AF_INET6:
  619: 	  {
  620: 	    char buf[4][INET6_ADDRSTRLEN];
  621: 	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
  622: 			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
  623: 			"gateway %s",
  624: 			__func__, ifm->ifam_index, 
  625: 			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
  626: 			ifm->ifam_flags,
  627: 			inet_ntop(AF_INET6,&addr->sin6.sin6_addr,
  628: 			          buf[0],sizeof(buf[0])),
  629: 			ip6_masklen(mask->sin6.sin6_addr),
  630: 			inet_ntop(AF_INET6,&brd->sin6.sin6_addr,
  631: 			          buf[1],sizeof(buf[1])),
  632: 			inet_ntop(AF_INET6,&dst.sin6.sin6_addr,
  633: 			          buf[2],sizeof(buf[2])),
  634: 			inet_ntop(AF_INET6,&gateway.sin6.sin6_addr,
  635: 			          buf[3],sizeof(buf[3])));
  636: 	  }
  637: 	  break;
  638: #endif /* HAVE_IPV6 */
  639:         default:
  640: 	  zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
  641: 		      __func__, ifm->ifam_index, 
  642: 		      (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
  643: 	  break;
  644:         }
  645:     }
  646: 
  647:   /* Assert read up end point matches to end point */
  648:   if (pnt != end)
  649:     zlog_warn ("ifam_read() doesn't read all socket data");
  650: }
  651: 
  652: /* Interface's address information get. */
  653: int
  654: ifam_read (struct ifa_msghdr *ifam)
  655: {
  656:   struct interface *ifp = NULL;
  657:   union sockunion addr, mask, brd;
  658:   char ifname[INTERFACE_NAMSIZ];
  659:   short ifnlen = 0;
  660:   char isalias = 0;
  661:   int flags = 0;
  662:   
  663:   ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
  664:   
  665:   /* Allocate and read address information. */
  666:   ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
  667:   
  668:   if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL)
  669:     {
  670:       zlog_warn ("%s: no interface for ifname %s, index %d", 
  671:                  __func__, ifname, ifam->ifam_index);
  672:       return -1;
  673:     }
  674:   
  675:   if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
  676:     isalias = 1;
  677:   
  678:   /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
  679:      field contains a broadcast address or a peer address, so we are forced to
  680:      rely upon the interface type. */
  681:   if (if_is_pointopoint(ifp))
  682:     SET_FLAG(flags, ZEBRA_IFA_PEER);
  683: 
  684: #if 0
  685:   /* it might seem cute to grab the interface metric here, however
  686:    * we're processing an address update message, and so some systems
  687:    * (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
  688:    * in deliberately, as comment.
  689:    */
  690:   ifp->metric = ifam->ifam_metric;
  691: #endif
  692: 
  693:   /* Add connected address. */
  694:   switch (sockunion_family (&addr))
  695:     {
  696:     case AF_INET:
  697:       if (ifam->ifam_type == RTM_NEWADDR)
  698: 	connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, 
  699: 			    ip_masklen (mask.sin.sin_addr),
  700: 			    &brd.sin.sin_addr,
  701: 			    (isalias ? ifname : NULL));
  702:       else
  703: 	connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, 
  704: 			       ip_masklen (mask.sin.sin_addr),
  705: 			       &brd.sin.sin_addr);
  706:       break;
  707: #ifdef HAVE_IPV6
  708:     case AF_INET6:
  709:       /* Unset interface index from link-local address when IPv6 stack
  710: 	 is KAME. */
  711:       if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
  712: 	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
  713: 
  714:       if (ifam->ifam_type == RTM_NEWADDR)
  715: 	connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, 
  716: 			    ip6_masklen (mask.sin6.sin6_addr),
  717: 			    &brd.sin6.sin6_addr,
  718: 			    (isalias ? ifname : NULL));
  719:       else
  720: 	connected_delete_ipv6 (ifp,
  721: 			       &addr.sin6.sin6_addr, 
  722: 			       ip6_masklen (mask.sin6.sin6_addr),
  723: 			       &brd.sin6.sin6_addr);
  724:       break;
  725: #endif /* HAVE_IPV6 */
  726:     default:
  727:       /* Unsupported family silently ignore... */
  728:       break;
  729:     }
  730:   
  731:   /* Check interface flag for implicit up of the interface. */
  732:   if_refresh (ifp);
  733: 
  734: #ifdef SUNOS_5
  735:   /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. 
  736:    * See comments for SUNOS_5 in interface.c::if_flags_mangle.
  737:    * 
  738:    * Here we take care of case where the real IFF_UP was previously
  739:    * unset (as kept in struct zebra_if.primary_state) and the mangled
  740:    * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
  741:    * to unset due to the lost non-primary address having DELADDR'd.
  742:    *
  743:    * we must delete the interface, because in between here and next
  744:    * event for this interface-name the administrator could unplumb
  745:    * and replumb the interface.
  746:    */
  747:   if (!if_is_up (ifp))
  748:     if_delete_update (ifp);
  749: #endif /* SUNOS_5 */
  750:   
  751:   return 0;
  752: }
  753: 
  754: /* Interface function for reading kernel routing table information. */
  755: static int
  756: rtm_read_mesg (struct rt_msghdr *rtm,
  757: 	       union sockunion *dest,
  758: 	       union sockunion *mask,
  759: 	       union sockunion *gate,
  760: 	       char *ifname,
  761: 	       short *ifnlen)
  762: {
  763:   caddr_t pnt, end;
  764: 
  765:   /* Pnt points out socket data start point. */
  766:   pnt = (caddr_t)(rtm + 1);
  767:   end = ((caddr_t)rtm) + rtm->rtm_msglen;
  768: 
  769:   /* rt_msghdr version check. */
  770:   if (rtm->rtm_version != RTM_VERSION) 
  771:       zlog (NULL, LOG_WARNING,
  772: 	      "Routing message version different %d should be %d."
  773: 	      "This may cause problem\n", rtm->rtm_version, RTM_VERSION);
  774:   
  775:   /* Be sure structure is cleared */
  776:   memset (dest, 0, sizeof (union sockunion));
  777:   memset (gate, 0, sizeof (union sockunion));
  778:   memset (mask, 0, sizeof (union sockunion));
  779: 
  780:   /* We fetch each socket variable into sockunion. */
  781:   RTA_ADDR_GET (dest, RTA_DST, rtm->rtm_addrs, pnt);
  782:   RTA_ADDR_GET (gate, RTA_GATEWAY, rtm->rtm_addrs, pnt);
  783:   RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
  784:   RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
  785:   RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
  786:   RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt);
  787:   RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
  788:   RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt);
  789: 
  790:   /* If there is netmask information set it's family same as
  791:      destination family*/
  792:   if (rtm->rtm_addrs & RTA_NETMASK)
  793:     mask->sa.sa_family = dest->sa.sa_family;
  794: 
  795:   /* Assert read up to the end of pointer. */
  796:   if (pnt != end) 
  797:       zlog (NULL, LOG_WARNING, "rtm_read() doesn't read all socket data.");
  798: 
  799:   return rtm->rtm_flags;
  800: }
  801: 
  802: void
  803: rtm_read (struct rt_msghdr *rtm)
  804: {
  805:   int flags;
  806:   u_char zebra_flags;
  807:   union sockunion dest, mask, gate;
  808:   char ifname[INTERFACE_NAMSIZ + 1];
  809:   short ifnlen = 0;
  810: 
  811:   zebra_flags = 0;
  812: 
  813:   /* Read destination and netmask and gateway from rtm message
  814:      structure. */
  815:   flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen);
  816:   if (!(flags & RTF_DONE))
  817:     return;
  818:   if (IS_ZEBRA_DEBUG_KERNEL)
  819:     zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type,
  820:       lookup (rtm_type_str, rtm->rtm_type));
  821: 
  822: #ifdef RTF_CLONED	/*bsdi, netbsd 1.6*/
  823:   if (flags & RTF_CLONED)
  824:     return;
  825: #endif
  826: #ifdef RTF_WASCLONED	/*freebsd*/
  827:   if (flags & RTF_WASCLONED)
  828:     return;
  829: #endif
  830: 
  831:   if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
  832:     return;
  833: 
  834:   /* This is connected route. */
  835:   if (! (flags & RTF_GATEWAY))
  836:       return;
  837: 
  838:   if (flags & RTF_PROTO1)
  839:     SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);
  840: 
  841:   /* This is persistent route. */
  842:   if (flags & RTF_STATIC)
  843:     SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
  844: 
  845:   /* This is a reject or blackhole route */
  846:   if (flags & RTF_REJECT)
  847:     SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
  848:   if (flags & RTF_BLACKHOLE)
  849:     SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);
  850: 
  851:   if (dest.sa.sa_family == AF_INET)
  852:     {
  853:       struct prefix_ipv4 p;
  854: 
  855:       p.family = AF_INET;
  856:       p.prefix = dest.sin.sin_addr;
  857:       if (flags & RTF_HOST)
  858: 	p.prefixlen = IPV4_MAX_PREFIXLEN;
  859:       else
  860: 	p.prefixlen = ip_masklen (mask.sin.sin_addr);
  861:       
  862:       /* Catch self originated messages and match them against our current RIB.
  863:        * At the same time, ignore unconfirmed messages, they should be tracked
  864:        * by rtm_write() and kernel_rtm_ipv4().
  865:        */
  866:       if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
  867:       {
  868:         char buf[INET_ADDRSTRLEN], gate_buf[INET_ADDRSTRLEN];
  869:         int ret;
  870:         if (! IS_ZEBRA_DEBUG_RIB)
  871:           return;
  872:         ret = rib_lookup_ipv4_route (&p, &gate); 
  873:         inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN);
  874:         switch (rtm->rtm_type)
  875:         {
  876:           case RTM_ADD:
  877:           case RTM_GET:
  878:           case RTM_CHANGE:
  879:             /* The kernel notifies us about a new route in FIB created by us.
  880:                Do we have a correspondent entry in our RIB? */
  881:             switch (ret)
  882:             {
  883:               case ZEBRA_RIB_NOTFOUND:
  884:                 zlog_debug ("%s: %s %s/%d: desync: RR isn't yet in RIB, while already in FIB",
  885:                   __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
  886:                 break;
  887:               case ZEBRA_RIB_FOUND_CONNECTED:
  888:               case ZEBRA_RIB_FOUND_NOGATE:
  889:                 inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN);
  890:                 zlog_debug ("%s: %s %s/%d: desync: RR is in RIB, but gate differs (ours is %s)",
  891:                   __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen, gate_buf);
  892:                 break;
  893:               case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */
  894:                 zlog_debug ("%s: %s %s/%d: done Ok",
  895:                   __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
  896:                 rib_lookup_and_dump (&p);
  897:                 return;
  898:                 break;
  899:             }
  900:             break;
  901:           case RTM_DELETE:
  902:             /* The kernel notifies us about a route deleted by us. Do we still
  903:                have it in the RIB? Do we have anything instead? */
  904:             switch (ret)
  905:             {
  906:               case ZEBRA_RIB_FOUND_EXACT:
  907:                 zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, while already not in FIB",
  908:                   __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
  909:                 rib_lookup_and_dump (&p);
  910:                 break;
  911:               case ZEBRA_RIB_FOUND_CONNECTED:
  912:               case ZEBRA_RIB_FOUND_NOGATE:
  913:                 zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, plus gate differs",
  914:                   __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
  915:                 rib_lookup_and_dump (&p);
  916:                 break;
  917:               case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
  918:                 zlog_debug ("%s: %s %s/%d: done Ok",
  919:                   __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
  920:                 rib_lookup_and_dump (&p);
  921:                 return;
  922:                 break;
  923:             }
  924:             break;
  925:           default:
  926:             zlog_debug ("%s: %s/%d: warning: loopback RTM of type %s received",
  927:               __func__, buf, p.prefixlen, lookup (rtm_type_str, rtm->rtm_type));
  928:         }
  929:         return;
  930:       }
  931: 
  932:       /* Change, delete the old prefix, we have no further information
  933:        * to specify the route really
  934:        */
  935:       if (rtm->rtm_type == RTM_CHANGE)
  936:         rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
  937:                          NULL, 0, 0, SAFI_UNICAST);
  938:       
  939:       if (rtm->rtm_type == RTM_GET 
  940:           || rtm->rtm_type == RTM_ADD
  941:           || rtm->rtm_type == RTM_CHANGE)
  942: 	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
  943: 		      &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, SAFI_UNICAST);
  944:       else
  945: 	rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
  946: 		      &p, &gate.sin.sin_addr, 0, 0, SAFI_UNICAST);
  947:     }
  948: #ifdef HAVE_IPV6
  949:   if (dest.sa.sa_family == AF_INET6)
  950:     {
  951:       /* One day we might have a debug section here like one in the
  952:        * IPv4 case above. Just ignore own messages at the moment.
  953:        */
  954:       if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
  955:         return;
  956:       struct prefix_ipv6 p;
  957:       unsigned int ifindex = 0;
  958: 
  959:       p.family = AF_INET6;
  960:       p.prefix = dest.sin6.sin6_addr;
  961:       if (flags & RTF_HOST)
  962: 	p.prefixlen = IPV6_MAX_PREFIXLEN;
  963:       else
  964: 	p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);
  965: 
  966: #ifdef KAME
  967:       if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
  968: 	{
  969: 	  ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
  970: 	  SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
  971: 	}
  972: #endif /* KAME */
  973: 
  974:       /* CHANGE: delete the old prefix, we have no further information
  975:        * to specify the route really
  976:        */
  977:       if (rtm->rtm_type == RTM_CHANGE)
  978:         rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
  979:                          NULL, 0, 0, SAFI_UNICAST);
  980:       
  981:       if (rtm->rtm_type == RTM_GET 
  982:           || rtm->rtm_type == RTM_ADD
  983:           || rtm->rtm_type == RTM_CHANGE)
  984: 	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
  985: 		      &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0, SAFI_UNICAST);
  986:       else
  987: 	rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
  988: 			 &p, &gate.sin6.sin6_addr, ifindex, 0, SAFI_UNICAST);
  989:     }
  990: #endif /* HAVE_IPV6 */
  991: }
  992: 
  993: /* Interface function for the kernel routing table updates.  Support
  994:  * for RTM_CHANGE will be needed.
  995:  * Exported only for rt_socket.c
  996:  */
  997: int
  998: rtm_write (int message,
  999: 	   union sockunion *dest,
 1000: 	   union sockunion *mask,
 1001: 	   union sockunion *gate,
 1002: 	   unsigned int index,
 1003: 	   int zebra_flags,
 1004: 	   int metric)
 1005: {
 1006:   int ret;
 1007:   caddr_t pnt;
 1008:   struct interface *ifp;
 1009: 
 1010:   /* Sequencial number of routing message. */
 1011:   static int msg_seq = 0;
 1012: 
 1013:   /* Struct of rt_msghdr and buffer for storing socket's data. */
 1014:   struct 
 1015:   {
 1016:     struct rt_msghdr rtm;
 1017:     char buf[512];
 1018:   } msg;
 1019:   
 1020:   if (routing_sock < 0)
 1021:     return ZEBRA_ERR_EPERM;
 1022: 
 1023:   /* Clear and set rt_msghdr values */
 1024:   memset (&msg, 0, sizeof (struct rt_msghdr));
 1025:   msg.rtm.rtm_version = RTM_VERSION;
 1026:   msg.rtm.rtm_type = message;
 1027:   msg.rtm.rtm_seq = msg_seq++;
 1028:   msg.rtm.rtm_addrs = RTA_DST;
 1029:   msg.rtm.rtm_addrs |= RTA_GATEWAY;
 1030:   msg.rtm.rtm_flags = RTF_UP;
 1031:   msg.rtm.rtm_index = index;
 1032: 
 1033:   if (metric != 0)
 1034:     {
 1035:       msg.rtm.rtm_rmx.rmx_hopcount = metric;
 1036:       msg.rtm.rtm_inits |= RTV_HOPCOUNT;
 1037:     }
 1038: 
 1039:   ifp = if_lookup_by_index (index);
 1040: 
 1041:   if (gate && message == RTM_ADD)
 1042:     msg.rtm.rtm_flags |= RTF_GATEWAY;
 1043: 
 1044:   /* When RTF_CLONING is unavailable on BSD, should we set some
 1045:    * other flag instead?
 1046:    */
 1047: #ifdef RTF_CLONING
 1048:   if (! gate && message == RTM_ADD && ifp &&
 1049:       (ifp->flags & IFF_POINTOPOINT) == 0)
 1050:     msg.rtm.rtm_flags |= RTF_CLONING;
 1051: #endif /* RTF_CLONING */
 1052: 
 1053:   /* If no protocol specific gateway is specified, use link
 1054:      address for gateway. */
 1055:   if (! gate)
 1056:     {
 1057:       if (!ifp)
 1058:         {
 1059:           char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
 1060:           if (dest)
 1061:             inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN);
 1062:           if (mask)
 1063:             inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN);
 1064:           zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
 1065:             __func__, dest_buf, mask_buf, index);
 1066:           return -1;
 1067:         }
 1068:       gate = (union sockunion *) & ifp->sdl;
 1069:     }
 1070: 
 1071:   if (mask)
 1072:     msg.rtm.rtm_addrs |= RTA_NETMASK;
 1073:   else if (message == RTM_ADD) 
 1074:     msg.rtm.rtm_flags |= RTF_HOST;
 1075: 
 1076:   /* Tagging route with flags */
 1077:   msg.rtm.rtm_flags |= (RTF_PROTO1);
 1078: 
 1079:   /* Additional flags. */
 1080:   if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
 1081:     msg.rtm.rtm_flags |= RTF_BLACKHOLE;
 1082:   if (zebra_flags & ZEBRA_FLAG_REJECT)
 1083:     msg.rtm.rtm_flags |= RTF_REJECT;
 1084: 
 1085: 
 1086: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
 1087: #define SOCKADDRSET(X,R) \
 1088:   if (msg.rtm.rtm_addrs & (R)) \
 1089:     { \
 1090:       int len = ROUNDUP ((X)->sa.sa_len); \
 1091:       memcpy (pnt, (caddr_t)(X), len); \
 1092:       pnt += len; \
 1093:     }
 1094: #else 
 1095: #define SOCKADDRSET(X,R) \
 1096:   if (msg.rtm.rtm_addrs & (R)) \
 1097:     { \
 1098:       int len = SAROUNDUP (X); \
 1099:       memcpy (pnt, (caddr_t)(X), len); \
 1100:       pnt += len; \
 1101:     }
 1102: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
 1103: 
 1104:   pnt = (caddr_t) msg.buf;
 1105: 
 1106:   /* Write each socket data into rtm message buffer */
 1107:   SOCKADDRSET (dest, RTA_DST);
 1108:   SOCKADDRSET (gate, RTA_GATEWAY);
 1109:   SOCKADDRSET (mask, RTA_NETMASK);
 1110: 
 1111:   msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;
 1112: 
 1113:   ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);
 1114: 
 1115:   if (ret != msg.rtm.rtm_msglen) 
 1116:     {
 1117:       if (errno == EEXIST) 
 1118: 	return ZEBRA_ERR_RTEXIST;
 1119:       if (errno == ENETUNREACH)
 1120: 	return ZEBRA_ERR_RTUNREACH;
 1121:       if (errno == ESRCH)
 1122: 	return ZEBRA_ERR_RTNOEXIST;
 1123:       
 1124:       zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno);
 1125:       return ZEBRA_ERR_KERNEL;
 1126:     }
 1127:   return ZEBRA_ERR_NOERROR;
 1128: }
 1129: 
 1130: 
 1131: #include "thread.h"
 1132: #include "zebra/zserv.h"
 1133: 
 1134: /* For debug purpose. */
 1135: static void
 1136: rtmsg_debug (struct rt_msghdr *rtm)
 1137: {
 1138:   zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup (rtm_type_str, rtm->rtm_type));
 1139:   rtm_flag_dump (rtm->rtm_flags);
 1140:   zlog_debug ("Kernel: message seq %d", rtm->rtm_seq);
 1141:   zlog_debug ("Kernel: pid %d, rtm_addrs 0x%x", rtm->rtm_pid, rtm->rtm_addrs);
 1142: }
 1143: 
 1144: /* This is pretty gross, better suggestions welcome -- mhandler */
 1145: #ifndef RTAX_MAX
 1146: #ifdef RTA_NUMBITS
 1147: #define RTAX_MAX	RTA_NUMBITS
 1148: #else
 1149: #define RTAX_MAX	8
 1150: #endif /* RTA_NUMBITS */
 1151: #endif /* RTAX_MAX */
 1152: 
 1153: /* Kernel routing table and interface updates via routing socket. */
 1154: static int
 1155: kernel_read (struct thread *thread)
 1156: {
 1157:   int sock;
 1158:   int nbytes;
 1159:   struct rt_msghdr *rtm;
 1160: 
 1161:   /*
 1162:    * This must be big enough for any message the kernel might send.
 1163:    * Rather than determining how many sockaddrs of what size might be
 1164:    * in each particular message, just use RTAX_MAX of sockaddr_storage
 1165:    * for each.  Note that the sockaddrs must be after each message
 1166:    * definition, or rather after whichever happens to be the largest,
 1167:    * since the buffer needs to be big enough for a message and the
 1168:    * sockaddrs together.
 1169:    */
 1170:   union 
 1171:   {
 1172:     /* Routing information. */
 1173:     struct 
 1174:     {
 1175:       struct rt_msghdr rtm;
 1176:       struct sockaddr_storage addr[RTAX_MAX];
 1177:     } r;
 1178: 
 1179:     /* Interface information. */
 1180:     struct
 1181:     {
 1182:       struct if_msghdr ifm;
 1183:       struct sockaddr_storage addr[RTAX_MAX];
 1184:     } im;
 1185: 
 1186:     /* Interface address information. */
 1187:     struct
 1188:     {
 1189:       struct ifa_msghdr ifa;
 1190:       struct sockaddr_storage addr[RTAX_MAX];
 1191:     } ia;
 1192: 
 1193: #ifdef RTM_IFANNOUNCE
 1194:     /* Interface arrival/departure */
 1195:     struct
 1196:     {
 1197:       struct if_announcemsghdr ifan;
 1198:       struct sockaddr_storage addr[RTAX_MAX];
 1199:     } ian;
 1200: #endif /* RTM_IFANNOUNCE */
 1201: 
 1202:   } buf;
 1203: 
 1204:   /* Fetch routing socket. */
 1205:   sock = THREAD_FD (thread);
 1206: 
 1207:   nbytes= read (sock, &buf, sizeof buf);
 1208: 
 1209:   if (nbytes <= 0)
 1210:     {
 1211:       if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
 1212: 	zlog_warn ("routing socket error: %s", safe_strerror (errno));
 1213:       return 0;
 1214:     }
 1215: 
 1216:   thread_add_read (zebrad.master, kernel_read, NULL, sock);
 1217: 
 1218:   if (IS_ZEBRA_DEBUG_KERNEL)
 1219:     rtmsg_debug (&buf.r.rtm);
 1220: 
 1221:   rtm = &buf.r.rtm;
 1222: 
 1223:   /*
 1224:    * Ensure that we didn't drop any data, so that processing routines
 1225:    * can assume they have the whole message.
 1226:    */
 1227:   if (rtm->rtm_msglen != nbytes)
 1228:     {
 1229:       zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
 1230: 		 rtm->rtm_msglen, nbytes, rtm->rtm_type);
 1231:       return -1;
 1232:     }
 1233: 
 1234:   switch (rtm->rtm_type)
 1235:     {
 1236:     case RTM_ADD:
 1237:     case RTM_DELETE:
 1238:     case RTM_CHANGE:
 1239:       rtm_read (rtm);
 1240:       break;
 1241:     case RTM_IFINFO:
 1242:       ifm_read (&buf.im.ifm);
 1243:       break;
 1244:     case RTM_NEWADDR:
 1245:     case RTM_DELADDR:
 1246:       ifam_read (&buf.ia.ifa);
 1247:       break;
 1248: #ifdef RTM_IFANNOUNCE
 1249:     case RTM_IFANNOUNCE:
 1250:       ifan_read (&buf.ian.ifan);
 1251:       break;
 1252: #endif /* RTM_IFANNOUNCE */
 1253:     default:
 1254:       if (IS_ZEBRA_DEBUG_KERNEL)
 1255:         zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
 1256:       break;
 1257:     }
 1258:   return 0;
 1259: }
 1260: 
 1261: /* Make routing socket. */
 1262: static void
 1263: routing_socket (void)
 1264: {
 1265:   if ( zserv_privs.change (ZPRIVS_RAISE) )
 1266:     zlog_err ("routing_socket: Can't raise privileges");
 1267: 
 1268:   routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
 1269: 
 1270:   if (routing_sock < 0) 
 1271:     {
 1272:       if ( zserv_privs.change (ZPRIVS_LOWER) )
 1273:         zlog_err ("routing_socket: Can't lower privileges");
 1274:       zlog_warn ("Can't init kernel routing socket");
 1275:       return;
 1276:     }
 1277: 
 1278:   /* XXX: Socket should be NONBLOCK, however as we currently 
 1279:    * discard failed writes, this will lead to inconsistencies.
 1280:    * For now, socket must be blocking.
 1281:    */
 1282:   /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) 
 1283:     zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
 1284:     
 1285:   if ( zserv_privs.change (ZPRIVS_LOWER) )
 1286:     zlog_err ("routing_socket: Can't lower privileges");
 1287: 
 1288:   /* kernel_read needs rewrite. */
 1289:   thread_add_read (zebrad.master, kernel_read, NULL, routing_sock);
 1290: }
 1291: 
 1292: /* Exported interface function.  This function simply calls
 1293:    routing_socket (). */
 1294: void
 1295: kernel_init (void)
 1296: {
 1297:   routing_socket ();
 1298: }

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