File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / rt_netlink.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:29 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_21, HEAD
quagga

    1: /* Kernel routing table updates using netlink over GNU/Linux system.
    2:  * Copyright (C) 1997, 98, 99 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: /* Hack for GNU libc version 2. */
   25: #ifndef MSG_TRUNC
   26: #define MSG_TRUNC      0x20
   27: #endif /* MSG_TRUNC */
   28: 
   29: #include "linklist.h"
   30: #include "if.h"
   31: #include "log.h"
   32: #include "prefix.h"
   33: #include "connected.h"
   34: #include "table.h"
   35: #include "memory.h"
   36: #include "rib.h"
   37: #include "thread.h"
   38: #include "privs.h"
   39: 
   40: #include "zebra/zserv.h"
   41: #include "zebra/rt.h"
   42: #include "zebra/redistribute.h"
   43: #include "zebra/interface.h"
   44: #include "zebra/debug.h"
   45: 
   46: #define NL_PKT_BUF_SIZE 4096
   47: 
   48: /* Socket interface to kernel */
   49: struct nlsock
   50: {
   51:   int sock;
   52:   int seq;
   53:   struct sockaddr_nl snl;
   54:   const char *name;
   55: } netlink      = { -1, 0, {0}, "netlink-listen"},     /* kernel messages */
   56:   netlink_cmd  = { -1, 0, {0}, "netlink-cmd"};        /* command channel */
   57: 
   58: static const struct message nlmsg_str[] = {
   59:   {RTM_NEWROUTE, "RTM_NEWROUTE"},
   60:   {RTM_DELROUTE, "RTM_DELROUTE"},
   61:   {RTM_GETROUTE, "RTM_GETROUTE"},
   62:   {RTM_NEWLINK,  "RTM_NEWLINK"},
   63:   {RTM_DELLINK,  "RTM_DELLINK"},
   64:   {RTM_GETLINK,  "RTM_GETLINK"},
   65:   {RTM_NEWADDR,  "RTM_NEWADDR"},
   66:   {RTM_DELADDR,  "RTM_DELADDR"},
   67:   {RTM_GETADDR,  "RTM_GETADDR"},
   68:   {0, NULL}
   69: };
   70: 
   71: static const char *nexthop_types_desc[] =
   72: {
   73:   "none",
   74:   "Directly connected",
   75:   "Interface route",
   76:   "IPv4 nexthop",
   77:   "IPv4 nexthop with ifindex",
   78:   "IPv4 nexthop with ifname",
   79:   "IPv6 nexthop",
   80:   "IPv6 nexthop with ifindex",
   81:   "IPv6 nexthop with ifname",
   82:   "Null0 nexthop",
   83: };
   84: 
   85: extern struct zebra_t zebrad;
   86: 
   87: extern struct zebra_privs_t zserv_privs;
   88: 
   89: extern u_int32_t nl_rcvbufsize;
   90: 
   91: /* Note: on netlink systems, there should be a 1-to-1 mapping between interface
   92:    names and ifindex values. */
   93: static void
   94: set_ifindex(struct interface *ifp, unsigned int ifi_index)
   95: {
   96:   struct interface *oifp;
   97: 
   98:   if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
   99:     {
  100:       if (ifi_index == IFINDEX_INTERNAL)
  101:         zlog_err("Netlink is setting interface %s ifindex to reserved "
  102: 		 "internal value %u", ifp->name, ifi_index);
  103:       else
  104:         {
  105: 	  if (IS_ZEBRA_DEBUG_KERNEL)
  106: 	    zlog_debug("interface index %d was renamed from %s to %s",
  107: 	    	       ifi_index, oifp->name, ifp->name);
  108: 	  if (if_is_up(oifp))
  109: 	    zlog_err("interface rename detected on up interface: index %d "
  110: 		     "was renamed from %s to %s, results are uncertain!", 
  111: 	    	     ifi_index, oifp->name, ifp->name);
  112: 	  if_delete_update(oifp);
  113:         }
  114:     }
  115:   ifp->ifindex = ifi_index;
  116: }
  117: 
  118: static int
  119: netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
  120: {
  121:   u_int32_t oldsize;
  122:   socklen_t newlen = sizeof(newsize);
  123:   socklen_t oldlen = sizeof(oldsize);
  124:   int ret;
  125: 
  126:   ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
  127:   if (ret < 0)
  128:     {
  129:       zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
  130: 	    safe_strerror (errno));
  131:       return -1;
  132:     }
  133: 
  134:   ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
  135: 		   sizeof(nl_rcvbufsize));
  136:   if (ret < 0)
  137:     {
  138:       zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
  139: 	    safe_strerror (errno));
  140:       return -1;
  141:     }
  142: 
  143:   ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
  144:   if (ret < 0)
  145:     {
  146:       zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
  147: 	    safe_strerror (errno));
  148:       return -1;
  149:     }
  150: 
  151:   zlog (NULL, LOG_INFO,
  152: 	"Setting netlink socket receive buffer size: %u -> %u",
  153: 	oldsize, newsize);
  154:   return 0;
  155: }
  156: 
  157: /* Make socket for Linux netlink interface. */
  158: static int
  159: netlink_socket (struct nlsock *nl, unsigned long groups)
  160: {
  161:   int ret;
  162:   struct sockaddr_nl snl;
  163:   int sock;
  164:   int namelen;
  165:   int save_errno;
  166: 
  167:   sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  168:   if (sock < 0)
  169:     {
  170:       zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
  171:             safe_strerror (errno));
  172:       return -1;
  173:     }
  174: 
  175:   memset (&snl, 0, sizeof snl);
  176:   snl.nl_family = AF_NETLINK;
  177:   snl.nl_groups = groups;
  178: 
  179:   /* Bind the socket to the netlink structure for anything. */
  180:   if (zserv_privs.change (ZPRIVS_RAISE))
  181:     {
  182:       zlog (NULL, LOG_ERR, "Can't raise privileges");
  183:       return -1;
  184:     }
  185: 
  186:   ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
  187:   save_errno = errno;
  188:   if (zserv_privs.change (ZPRIVS_LOWER))
  189:     zlog (NULL, LOG_ERR, "Can't lower privileges");
  190: 
  191:   if (ret < 0)
  192:     {
  193:       zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
  194:             nl->name, snl.nl_groups, safe_strerror (save_errno));
  195:       close (sock);
  196:       return -1;
  197:     }
  198: 
  199:   /* multiple netlink sockets will have different nl_pid */
  200:   namelen = sizeof snl;
  201:   ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
  202:   if (ret < 0 || namelen != sizeof snl)
  203:     {
  204:       zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
  205:             safe_strerror (errno));
  206:       close (sock);
  207:       return -1;
  208:     }
  209: 
  210:   nl->snl = snl;
  211:   nl->sock = sock;
  212:   return ret;
  213: }
  214: 
  215: /* Get type specified information from netlink. */
  216: static int
  217: netlink_request (int family, int type, struct nlsock *nl)
  218: {
  219:   int ret;
  220:   struct sockaddr_nl snl;
  221:   int save_errno;
  222: 
  223:   struct
  224:   {
  225:     struct nlmsghdr nlh;
  226:     struct rtgenmsg g;
  227:   } req;
  228: 
  229: 
  230:   /* Check netlink socket. */
  231:   if (nl->sock < 0)
  232:     {
  233:       zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
  234:       return -1;
  235:     }
  236: 
  237:   memset (&snl, 0, sizeof snl);
  238:   snl.nl_family = AF_NETLINK;
  239: 
  240:   memset (&req, 0, sizeof req);
  241:   req.nlh.nlmsg_len = sizeof req;
  242:   req.nlh.nlmsg_type = type;
  243:   req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
  244:   req.nlh.nlmsg_pid = nl->snl.nl_pid;
  245:   req.nlh.nlmsg_seq = ++nl->seq;
  246:   req.g.rtgen_family = family;
  247: 
  248:   /* linux appears to check capabilities on every message 
  249:    * have to raise caps for every message sent
  250:    */
  251:   if (zserv_privs.change (ZPRIVS_RAISE))
  252:     {
  253:       zlog (NULL, LOG_ERR, "Can't raise privileges");
  254:       return -1;
  255:     }
  256: 
  257:   ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
  258:                 (struct sockaddr *) &snl, sizeof snl);
  259:   save_errno = errno;
  260: 
  261:   if (zserv_privs.change (ZPRIVS_LOWER))
  262:     zlog (NULL, LOG_ERR, "Can't lower privileges");
  263: 
  264:   if (ret < 0)
  265:     {
  266:       zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
  267:             safe_strerror (save_errno));
  268:       return -1;
  269:     }
  270: 
  271:   return 0;
  272: }
  273: 
  274: /* Receive message from netlink interface and pass those information
  275:    to the given function. */
  276: static int
  277: netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
  278:                     struct nlsock *nl)
  279: {
  280:   int status;
  281:   int ret = 0;
  282:   int error;
  283: 
  284:   while (1)
  285:     {
  286:       char buf[NL_PKT_BUF_SIZE];
  287:       struct iovec iov = { buf, sizeof buf };
  288:       struct sockaddr_nl snl;
  289:       struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
  290:       struct nlmsghdr *h;
  291: 
  292:       status = recvmsg (nl->sock, &msg, 0);
  293:       if (status < 0)
  294:         {
  295:           if (errno == EINTR)
  296:             continue;
  297:           if (errno == EWOULDBLOCK || errno == EAGAIN)
  298:             break;
  299:           zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
  300: 	  	nl->name, safe_strerror(errno));
  301:           continue;
  302:         }
  303: 
  304:       if (status == 0)
  305:         {
  306:           zlog (NULL, LOG_ERR, "%s EOF", nl->name);
  307:           return -1;
  308:         }
  309: 
  310:       if (msg.msg_namelen != sizeof snl)
  311:         {
  312:           zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
  313:                 nl->name, msg.msg_namelen);
  314:           return -1;
  315:         }
  316:       
  317:       for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
  318:            h = NLMSG_NEXT (h, status))
  319:         {
  320:           /* Finish of reading. */
  321:           if (h->nlmsg_type == NLMSG_DONE)
  322:             return ret;
  323: 
  324:           /* Error handling. */
  325:           if (h->nlmsg_type == NLMSG_ERROR)
  326:             {
  327:               struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
  328: 	      int errnum = err->error;
  329: 	      int msg_type = err->msg.nlmsg_type;
  330: 
  331:               /* If the error field is zero, then this is an ACK */
  332:               if (err->error == 0)
  333:                 {
  334:                   if (IS_ZEBRA_DEBUG_KERNEL)
  335:                     {
  336:                       zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u",
  337:                                  __FUNCTION__, nl->name,
  338:                                  lookup (nlmsg_str, err->msg.nlmsg_type),
  339:                                  err->msg.nlmsg_type, err->msg.nlmsg_seq,
  340:                                  err->msg.nlmsg_pid);
  341:                     }
  342: 
  343:                   /* return if not a multipart message, otherwise continue */
  344:                   if (!(h->nlmsg_flags & NLM_F_MULTI))
  345:                     {
  346:                       return 0;
  347:                     }
  348:                   continue;
  349:                 }
  350: 
  351:               if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
  352:                 {
  353:                   zlog (NULL, LOG_ERR, "%s error: message truncated",
  354:                         nl->name);
  355:                   return -1;
  356:                 }
  357: 
  358:               /* Deal with errors that occur because of races in link handling */
  359: 	      if (nl == &netlink_cmd
  360: 		  && ((msg_type == RTM_DELROUTE &&
  361: 		       (-errnum == ENODEV || -errnum == ESRCH))
  362: 		      || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
  363: 		{
  364: 		  if (IS_ZEBRA_DEBUG_KERNEL)
  365: 		    zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u",
  366: 				nl->name, safe_strerror (-errnum),
  367: 				lookup (nlmsg_str, msg_type),
  368: 				msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
  369: 		  return 0;
  370: 		}
  371: 
  372: 	      zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u",
  373: 			nl->name, safe_strerror (-errnum),
  374: 			lookup (nlmsg_str, msg_type),
  375: 			msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
  376:               return -1;
  377:             }
  378: 
  379:           /* OK we got netlink message. */
  380:           if (IS_ZEBRA_DEBUG_KERNEL)
  381:             zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%u",
  382:                        nl->name,
  383:                        lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
  384:                        h->nlmsg_seq, h->nlmsg_pid);
  385: 
  386:           /* skip unsolicited messages originating from command socket */
  387:           if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
  388:             {
  389:               if (IS_ZEBRA_DEBUG_KERNEL)
  390:                 zlog_debug ("netlink_parse_info: %s packet comes from %s",
  391:                             netlink_cmd.name, nl->name);
  392:               continue;
  393:             }
  394: 
  395:           error = (*filter) (&snl, h);
  396:           if (error < 0)
  397:             {
  398:               zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
  399:               ret = error;
  400:             }
  401:         }
  402: 
  403:       /* After error care. */
  404:       if (msg.msg_flags & MSG_TRUNC)
  405:         {
  406:           zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
  407:           continue;
  408:         }
  409:       if (status)
  410:         {
  411:           zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
  412:                 status);
  413:           return -1;
  414:         }
  415:     }
  416:   return ret;
  417: }
  418: 
  419: /* Utility function for parse rtattr. */
  420: static void
  421: netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
  422:                       int len)
  423: {
  424:   while (RTA_OK (rta, len))
  425:     {
  426:       if (rta->rta_type <= max)
  427:         tb[rta->rta_type] = rta;
  428:       rta = RTA_NEXT (rta, len);
  429:     }
  430: }
  431: 
  432: /* Utility function to parse hardware link-layer address and update ifp */
  433: static void
  434: netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
  435: {
  436:   int i;
  437: 
  438:   if (tb[IFLA_ADDRESS])
  439:     {
  440:       int hw_addr_len;
  441: 
  442:       hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
  443: 
  444:       if (hw_addr_len > INTERFACE_HWADDR_MAX)
  445:         zlog_warn ("Hardware address is too large: %d", hw_addr_len);
  446:       else
  447:         {
  448:           ifp->hw_addr_len = hw_addr_len;
  449:           memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
  450: 
  451:           for (i = 0; i < hw_addr_len; i++)
  452:             if (ifp->hw_addr[i] != 0)
  453:               break;
  454: 
  455:           if (i == hw_addr_len)
  456:             ifp->hw_addr_len = 0;
  457:           else
  458:             ifp->hw_addr_len = hw_addr_len;
  459:         }
  460:     }
  461: }
  462: 
  463: /* Called from interface_lookup_netlink().  This function is only used
  464:    during bootstrap. */
  465: static int
  466: netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
  467: {
  468:   int len;
  469:   struct ifinfomsg *ifi;
  470:   struct rtattr *tb[IFLA_MAX + 1];
  471:   struct interface *ifp;
  472:   char *name;
  473: 
  474:   ifi = NLMSG_DATA (h);
  475: 
  476:   if (h->nlmsg_type != RTM_NEWLINK)
  477:     return 0;
  478: 
  479:   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
  480:   if (len < 0)
  481:     return -1;
  482: 
  483:   /* Looking up interface name. */
  484:   memset (tb, 0, sizeof tb);
  485:   netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
  486:   
  487: #ifdef IFLA_WIRELESS
  488:   /* check for wireless messages to ignore */
  489:   if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
  490:     {
  491:       if (IS_ZEBRA_DEBUG_KERNEL)
  492:         zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
  493:       return 0;
  494:     }
  495: #endif /* IFLA_WIRELESS */
  496: 
  497:   if (tb[IFLA_IFNAME] == NULL)
  498:     return -1;
  499:   name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
  500: 
  501:   /* Add interface. */
  502:   ifp = if_get_by_name (name);
  503:   set_ifindex(ifp, ifi->ifi_index);
  504:   ifp->flags = ifi->ifi_flags & 0x0000fffff;
  505:   ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
  506:   ifp->metric = 1;
  507: 
  508:   /* Hardware type and address. */
  509:   ifp->hw_type = ifi->ifi_type;
  510:   netlink_interface_update_hw_addr (tb, ifp);
  511: 
  512:   if_add_update (ifp);
  513: 
  514:   return 0;
  515: }
  516: 
  517: /* Lookup interface IPv4/IPv6 address. */
  518: static int
  519: netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
  520: {
  521:   int len;
  522:   struct ifaddrmsg *ifa;
  523:   struct rtattr *tb[IFA_MAX + 1];
  524:   struct interface *ifp;
  525:   void *addr;
  526:   void *broad;
  527:   u_char flags = 0;
  528:   char *label = NULL;
  529: 
  530:   ifa = NLMSG_DATA (h);
  531: 
  532:   if (ifa->ifa_family != AF_INET
  533: #ifdef HAVE_IPV6
  534:       && ifa->ifa_family != AF_INET6
  535: #endif /* HAVE_IPV6 */
  536:     )
  537:     return 0;
  538: 
  539:   if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
  540:     return 0;
  541: 
  542:   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
  543:   if (len < 0)
  544:     return -1;
  545: 
  546:   memset (tb, 0, sizeof tb);
  547:   netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
  548: 
  549:   ifp = if_lookup_by_index (ifa->ifa_index);
  550:   if (ifp == NULL)
  551:     {
  552:       zlog_err ("netlink_interface_addr can't find interface by index %d",
  553:                 ifa->ifa_index);
  554:       return -1;
  555:     }
  556: 
  557:   if (IS_ZEBRA_DEBUG_KERNEL)    /* remove this line to see initial ifcfg */
  558:     {
  559:       char buf[BUFSIZ];
  560:       zlog_debug ("netlink_interface_addr %s %s:",
  561:                  lookup (nlmsg_str, h->nlmsg_type), ifp->name);
  562:       if (tb[IFA_LOCAL])
  563:         zlog_debug ("  IFA_LOCAL     %s/%d",
  564: 		    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
  565: 			       buf, BUFSIZ), ifa->ifa_prefixlen);
  566:       if (tb[IFA_ADDRESS])
  567:         zlog_debug ("  IFA_ADDRESS   %s/%d",
  568: 		    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
  569:                                buf, BUFSIZ), ifa->ifa_prefixlen);
  570:       if (tb[IFA_BROADCAST])
  571:         zlog_debug ("  IFA_BROADCAST %s/%d",
  572: 		    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
  573: 			       buf, BUFSIZ), ifa->ifa_prefixlen);
  574:       if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
  575:         zlog_debug ("  IFA_LABEL     %s", (char *)RTA_DATA (tb[IFA_LABEL]));
  576:       
  577:       if (tb[IFA_CACHEINFO])
  578:         {
  579:           struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
  580:           zlog_debug ("  IFA_CACHEINFO pref %d, valid %d",
  581:                       ci->ifa_prefered, ci->ifa_valid);
  582:         }
  583:     }
  584:   
  585:   /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
  586:   if (tb[IFA_LOCAL] == NULL)
  587:     tb[IFA_LOCAL] = tb[IFA_ADDRESS];
  588:   if (tb[IFA_ADDRESS] == NULL)
  589:     tb[IFA_ADDRESS] = tb[IFA_LOCAL];
  590:   
  591:   /* local interface address */
  592:   addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
  593: 
  594:   /* is there a peer address? */
  595:   if (tb[IFA_ADDRESS] &&
  596:       memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
  597:     {
  598:       broad = RTA_DATA(tb[IFA_ADDRESS]);
  599:       SET_FLAG (flags, ZEBRA_IFA_PEER);
  600:     }
  601:   else
  602:     /* seeking a broadcast address */
  603:     broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
  604: 
  605:   /* addr is primary key, SOL if we don't have one */
  606:   if (addr == NULL)
  607:     {
  608:       zlog_debug ("%s: NULL address", __func__);
  609:       return -1;
  610:     }
  611: 
  612:   /* Flags. */
  613:   if (ifa->ifa_flags & IFA_F_SECONDARY)
  614:     SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
  615: 
  616:   /* Label */
  617:   if (tb[IFA_LABEL])
  618:     label = (char *) RTA_DATA (tb[IFA_LABEL]);
  619: 
  620:   if (ifp && label && strcmp (ifp->name, label) == 0)
  621:     label = NULL;
  622: 
  623:   /* Register interface address to the interface. */
  624:   if (ifa->ifa_family == AF_INET)
  625:     {
  626:       if (h->nlmsg_type == RTM_NEWADDR)
  627:         connected_add_ipv4 (ifp, flags,
  628:                             (struct in_addr *) addr, ifa->ifa_prefixlen,
  629:                             (struct in_addr *) broad, label);
  630:       else
  631:         connected_delete_ipv4 (ifp, flags,
  632:                                (struct in_addr *) addr, ifa->ifa_prefixlen,
  633:                                (struct in_addr *) broad);
  634:     }
  635: #ifdef HAVE_IPV6
  636:   if (ifa->ifa_family == AF_INET6)
  637:     {
  638:       if (h->nlmsg_type == RTM_NEWADDR)
  639:         connected_add_ipv6 (ifp, flags,
  640:                             (struct in6_addr *) addr, ifa->ifa_prefixlen,
  641:                             (struct in6_addr *) broad, label);
  642:       else
  643:         connected_delete_ipv6 (ifp,
  644:                                (struct in6_addr *) addr, ifa->ifa_prefixlen,
  645:                                (struct in6_addr *) broad);
  646:     }
  647: #endif /* HAVE_IPV6 */
  648: 
  649:   return 0;
  650: }
  651: 
  652: /* Looking up routing table by netlink interface. */
  653: static int
  654: netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
  655: {
  656:   int len;
  657:   struct rtmsg *rtm;
  658:   struct rtattr *tb[RTA_MAX + 1];
  659:   u_char flags = 0;
  660: 
  661:   char anyaddr[16] = { 0 };
  662: 
  663:   int index;
  664:   int table;
  665:   int metric;
  666: 
  667:   void *dest;
  668:   void *gate;
  669:   void *src;
  670: 
  671:   rtm = NLMSG_DATA (h);
  672: 
  673:   if (h->nlmsg_type != RTM_NEWROUTE)
  674:     return 0;
  675:   if (rtm->rtm_type != RTN_UNICAST)
  676:     return 0;
  677: 
  678:   table = rtm->rtm_table;
  679: #if 0                           /* we weed them out later in rib_weed_tables () */
  680:   if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
  681:     return 0;
  682: #endif
  683: 
  684:   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
  685:   if (len < 0)
  686:     return -1;
  687: 
  688:   memset (tb, 0, sizeof tb);
  689:   netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
  690: 
  691:   if (rtm->rtm_flags & RTM_F_CLONED)
  692:     return 0;
  693:   if (rtm->rtm_protocol == RTPROT_REDIRECT)
  694:     return 0;
  695:   if (rtm->rtm_protocol == RTPROT_KERNEL)
  696:     return 0;
  697: 
  698:   if (rtm->rtm_src_len != 0)
  699:     return 0;
  700: 
  701:   /* Route which inserted by Zebra. */
  702:   if (rtm->rtm_protocol == RTPROT_ZEBRA)
  703:     flags |= ZEBRA_FLAG_SELFROUTE;
  704: 
  705:   index = 0;
  706:   metric = 0;
  707:   dest = NULL;
  708:   gate = NULL;
  709:   src = NULL;
  710: 
  711:   if (tb[RTA_OIF])
  712:     index = *(int *) RTA_DATA (tb[RTA_OIF]);
  713: 
  714:   if (tb[RTA_DST])
  715:     dest = RTA_DATA (tb[RTA_DST]);
  716:   else
  717:     dest = anyaddr;
  718: 
  719:   if (tb[RTA_PREFSRC])
  720:     src = RTA_DATA (tb[RTA_PREFSRC]);
  721: 
  722:   if (tb[RTA_GATEWAY])
  723:     gate = RTA_DATA (tb[RTA_GATEWAY]);
  724: 
  725:   if (tb[RTA_PRIORITY])
  726:     metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
  727: 
  728:   if (rtm->rtm_family == AF_INET)
  729:     {
  730:       struct prefix_ipv4 p;
  731:       p.family = AF_INET;
  732:       memcpy (&p.prefix, dest, 4);
  733:       p.prefixlen = rtm->rtm_dst_len;
  734: 
  735:       if (!tb[RTA_MULTIPATH])
  736:           rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
  737:                         table, metric, 0, SAFI_UNICAST);
  738:       else
  739:         {
  740:           /* This is a multipath route */
  741: 
  742:           struct rib *rib;
  743:           struct rtnexthop *rtnh =
  744:             (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
  745: 
  746:           len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
  747: 
  748:           rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
  749:           rib->type = ZEBRA_ROUTE_KERNEL;
  750:           rib->distance = 0;
  751:           rib->flags = flags;
  752:           rib->metric = metric;
  753:           rib->table = table;
  754:           rib->nexthop_num = 0;
  755:           rib->uptime = time (NULL);
  756: 
  757:           for (;;)
  758:             {
  759:               if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
  760:                 break;
  761: 
  762:               rib->nexthop_num++;
  763:               index = rtnh->rtnh_ifindex;
  764:               gate = 0;
  765:               if (rtnh->rtnh_len > sizeof (*rtnh))
  766:                 {
  767:                   memset (tb, 0, sizeof (tb));
  768:                   netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
  769:                                         rtnh->rtnh_len - sizeof (*rtnh));
  770:                   if (tb[RTA_GATEWAY])
  771:                     gate = RTA_DATA (tb[RTA_GATEWAY]);
  772:                 }
  773: 
  774:               if (gate)
  775:                 {
  776:                   if (index)
  777:                     nexthop_ipv4_ifindex_add (rib, gate, src, index);
  778:                   else
  779:                     nexthop_ipv4_add (rib, gate, src);
  780:                 }
  781:               else
  782:                 nexthop_ifindex_add (rib, index);
  783: 
  784:               len -= NLMSG_ALIGN(rtnh->rtnh_len);
  785:               rtnh = RTNH_NEXT(rtnh);
  786:             }
  787: 
  788:           if (rib->nexthop_num == 0)
  789:             XFREE (MTYPE_RIB, rib);
  790:           else
  791:             rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
  792:         }
  793:     }
  794: #ifdef HAVE_IPV6
  795:   if (rtm->rtm_family == AF_INET6)
  796:     {
  797:       struct prefix_ipv6 p;
  798:       p.family = AF_INET6;
  799:       memcpy (&p.prefix, dest, 16);
  800:       p.prefixlen = rtm->rtm_dst_len;
  801: 
  802:       rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table,
  803: 		    metric, 0, SAFI_UNICAST);
  804:     }
  805: #endif /* HAVE_IPV6 */
  806: 
  807:   return 0;
  808: }
  809: 
  810: static const struct message rtproto_str[] = {
  811:   {RTPROT_REDIRECT, "redirect"},
  812:   {RTPROT_KERNEL,   "kernel"},
  813:   {RTPROT_BOOT,     "boot"},
  814:   {RTPROT_STATIC,   "static"},
  815:   {RTPROT_GATED,    "GateD"},
  816:   {RTPROT_RA,       "router advertisement"},
  817:   {RTPROT_MRT,      "MRT"},
  818:   {RTPROT_ZEBRA,    "Zebra"},
  819: #ifdef RTPROT_BIRD
  820:   {RTPROT_BIRD,     "BIRD"},
  821: #endif /* RTPROT_BIRD */
  822:   {0,               NULL}
  823: };
  824: 
  825: /* Routing information change from the kernel. */
  826: static int
  827: netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
  828: {
  829:   int len;
  830:   struct rtmsg *rtm;
  831:   struct rtattr *tb[RTA_MAX + 1];
  832: 
  833:   char anyaddr[16] = { 0 };
  834: 
  835:   int index;
  836:   int table;
  837:   int metric;
  838: 
  839:   void *dest;
  840:   void *gate;
  841:   void *src;
  842: 
  843:   rtm = NLMSG_DATA (h);
  844: 
  845:   if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
  846:     {
  847:       /* If this is not route add/delete message print warning. */
  848:       zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
  849:       return 0;
  850:     }
  851: 
  852:   /* Connected route. */
  853:   if (IS_ZEBRA_DEBUG_KERNEL)
  854:     zlog_debug ("%s %s %s proto %s",
  855:                h->nlmsg_type ==
  856:                RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
  857:                rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
  858:                rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
  859:                lookup (rtproto_str, rtm->rtm_protocol));
  860: 
  861:   if (rtm->rtm_type != RTN_UNICAST)
  862:     {
  863:       return 0;
  864:     }
  865: 
  866:   table = rtm->rtm_table;
  867:   if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
  868:     {
  869:       return 0;
  870:     }
  871: 
  872:   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
  873:   if (len < 0)
  874:     return -1;
  875: 
  876:   memset (tb, 0, sizeof tb);
  877:   netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
  878: 
  879:   if (rtm->rtm_flags & RTM_F_CLONED)
  880:     return 0;
  881:   if (rtm->rtm_protocol == RTPROT_REDIRECT)
  882:     return 0;
  883:   if (rtm->rtm_protocol == RTPROT_KERNEL)
  884:     return 0;
  885: 
  886:   if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
  887:     return 0;
  888: 
  889:   if (rtm->rtm_src_len != 0)
  890:     {
  891:       zlog_warn ("netlink_route_change(): no src len");
  892:       return 0;
  893:     }
  894: 
  895:   index = 0;
  896:   metric = 0;
  897:   dest = NULL;
  898:   gate = NULL;
  899:   src = NULL;
  900: 
  901:   if (tb[RTA_OIF])
  902:     index = *(int *) RTA_DATA (tb[RTA_OIF]);
  903: 
  904:   if (tb[RTA_DST])
  905:     dest = RTA_DATA (tb[RTA_DST]);
  906:   else
  907:     dest = anyaddr;
  908: 
  909:   if (tb[RTA_GATEWAY])
  910:     gate = RTA_DATA (tb[RTA_GATEWAY]);
  911: 
  912:   if (tb[RTA_PREFSRC])
  913:     src = RTA_DATA (tb[RTA_PREFSRC]);
  914: 
  915:   if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
  916:     metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
  917: 
  918:   if (rtm->rtm_family == AF_INET)
  919:     {
  920:       struct prefix_ipv4 p;
  921:       p.family = AF_INET;
  922:       memcpy (&p.prefix, dest, 4);
  923:       p.prefixlen = rtm->rtm_dst_len;
  924: 
  925:       if (IS_ZEBRA_DEBUG_KERNEL)
  926:         {
  927:           if (h->nlmsg_type == RTM_NEWROUTE)
  928:             zlog_debug ("RTM_NEWROUTE %s/%d",
  929:                        inet_ntoa (p.prefix), p.prefixlen);
  930:           else
  931:             zlog_debug ("RTM_DELROUTE %s/%d",
  932:                        inet_ntoa (p.prefix), p.prefixlen);
  933:         }
  934: 
  935:       if (h->nlmsg_type == RTM_NEWROUTE)
  936:         {
  937:           if (!tb[RTA_MULTIPATH])
  938:             rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
  939:                           metric, 0, SAFI_UNICAST);
  940:           else
  941:             {
  942:               /* This is a multipath route */
  943: 
  944:               struct rib *rib;
  945:               struct rtnexthop *rtnh =
  946:                 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
  947: 
  948:               len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
  949: 
  950:               rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
  951:               rib->type = ZEBRA_ROUTE_KERNEL;
  952:               rib->distance = 0;
  953:               rib->flags = 0;
  954:               rib->metric = metric;
  955:               rib->table = table;
  956:               rib->nexthop_num = 0;
  957:               rib->uptime = time (NULL);
  958: 
  959:               for (;;)
  960:                 {
  961:                   if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
  962:                     break;
  963: 
  964:                   rib->nexthop_num++;
  965:                   index = rtnh->rtnh_ifindex;
  966:                   gate = 0;
  967:                   if (rtnh->rtnh_len > sizeof (*rtnh))
  968:                     {
  969:                       memset (tb, 0, sizeof (tb));
  970:                       netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
  971:                                             rtnh->rtnh_len - sizeof (*rtnh));
  972:                       if (tb[RTA_GATEWAY])
  973:                         gate = RTA_DATA (tb[RTA_GATEWAY]);
  974:                     }
  975: 
  976:                   if (gate)
  977:                     {
  978:                       if (index)
  979:                         nexthop_ipv4_ifindex_add (rib, gate, src, index);
  980:                       else
  981:                         nexthop_ipv4_add (rib, gate, src);
  982:                     }
  983:                   else
  984:                     nexthop_ifindex_add (rib, index);
  985: 
  986:                   len -= NLMSG_ALIGN(rtnh->rtnh_len);
  987:                   rtnh = RTNH_NEXT(rtnh);
  988:                 }
  989: 
  990:               if (rib->nexthop_num == 0)
  991:                 XFREE (MTYPE_RIB, rib);
  992:               else
  993:                 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
  994:             }
  995:         }
  996:       else
  997:         rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
  998:     }
  999: 
 1000: #ifdef HAVE_IPV6
 1001:   if (rtm->rtm_family == AF_INET6)
 1002:     {
 1003:       struct prefix_ipv6 p;
 1004:       char buf[BUFSIZ];
 1005: 
 1006:       p.family = AF_INET6;
 1007:       memcpy (&p.prefix, dest, 16);
 1008:       p.prefixlen = rtm->rtm_dst_len;
 1009: 
 1010:       if (IS_ZEBRA_DEBUG_KERNEL)
 1011:         {
 1012:           if (h->nlmsg_type == RTM_NEWROUTE)
 1013:             zlog_debug ("RTM_NEWROUTE %s/%d",
 1014:                        inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
 1015:                        p.prefixlen);
 1016:           else
 1017:             zlog_debug ("RTM_DELROUTE %s/%d",
 1018:                        inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
 1019:                        p.prefixlen);
 1020:         }
 1021: 
 1022:       if (h->nlmsg_type == RTM_NEWROUTE)
 1023:         rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST);
 1024:       else
 1025:         rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
 1026:     }
 1027: #endif /* HAVE_IPV6 */
 1028: 
 1029:   return 0;
 1030: }
 1031: 
 1032: static int
 1033: netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
 1034: {
 1035:   int len;
 1036:   struct ifinfomsg *ifi;
 1037:   struct rtattr *tb[IFLA_MAX + 1];
 1038:   struct interface *ifp;
 1039:   char *name;
 1040: 
 1041:   ifi = NLMSG_DATA (h);
 1042: 
 1043:   if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
 1044:     {
 1045:       /* If this is not link add/delete message so print warning. */
 1046:       zlog_warn ("netlink_link_change: wrong kernel message %d\n",
 1047:                  h->nlmsg_type);
 1048:       return 0;
 1049:     }
 1050: 
 1051:   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
 1052:   if (len < 0)
 1053:     return -1;
 1054: 
 1055:   /* Looking up interface name. */
 1056:   memset (tb, 0, sizeof tb);
 1057:   netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
 1058: 
 1059: #ifdef IFLA_WIRELESS
 1060:   /* check for wireless messages to ignore */
 1061:   if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
 1062:     {
 1063:       if (IS_ZEBRA_DEBUG_KERNEL)
 1064:         zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
 1065:       return 0;
 1066:     }
 1067: #endif /* IFLA_WIRELESS */
 1068:   
 1069:   if (tb[IFLA_IFNAME] == NULL)
 1070:     return -1;
 1071:   name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
 1072: 
 1073:   /* Add interface. */
 1074:   if (h->nlmsg_type == RTM_NEWLINK)
 1075:     {
 1076:       ifp = if_lookup_by_name (name);
 1077: 
 1078:       if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
 1079:         {
 1080:           if (ifp == NULL)
 1081:             ifp = if_get_by_name (name);
 1082: 
 1083:           set_ifindex(ifp, ifi->ifi_index);
 1084:           ifp->flags = ifi->ifi_flags & 0x0000fffff;
 1085:           ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
 1086:           ifp->metric = 1;
 1087: 
 1088:           netlink_interface_update_hw_addr (tb, ifp);
 1089: 
 1090:           /* If new link is added. */
 1091:           if_add_update (ifp);
 1092:         }
 1093:       else
 1094:         {
 1095:           /* Interface status change. */
 1096:           set_ifindex(ifp, ifi->ifi_index);
 1097:           ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
 1098:           ifp->metric = 1;
 1099: 
 1100:           netlink_interface_update_hw_addr (tb, ifp);
 1101: 
 1102:           if (if_is_operative (ifp))
 1103:             {
 1104:               ifp->flags = ifi->ifi_flags & 0x0000fffff;
 1105:               if (!if_is_operative (ifp))
 1106:                 if_down (ifp);
 1107: 	      else
 1108: 		/* Must notify client daemons of new interface status. */
 1109: 	        zebra_interface_up_update (ifp);
 1110:             }
 1111:           else
 1112:             {
 1113:               ifp->flags = ifi->ifi_flags & 0x0000fffff;
 1114:               if (if_is_operative (ifp))
 1115:                 if_up (ifp);
 1116:             }
 1117:         }
 1118:     }
 1119:   else
 1120:     {
 1121:       /* RTM_DELLINK. */
 1122:       ifp = if_lookup_by_name (name);
 1123: 
 1124:       if (ifp == NULL)
 1125:         {
 1126:           zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
 1127:                 name);
 1128:           return 0;
 1129:         }
 1130: 
 1131:       if_delete_update (ifp);
 1132:     }
 1133: 
 1134:   return 0;
 1135: }
 1136: 
 1137: static int
 1138: netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
 1139: {
 1140:   /* JF: Ignore messages that aren't from the kernel */
 1141:   if ( snl->nl_pid != 0 )
 1142:     {
 1143:       zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
 1144:       return 0;
 1145:     }
 1146: 
 1147:   switch (h->nlmsg_type)
 1148:     {
 1149:     case RTM_NEWROUTE:
 1150:       return netlink_route_change (snl, h);
 1151:       break;
 1152:     case RTM_DELROUTE:
 1153:       return netlink_route_change (snl, h);
 1154:       break;
 1155:     case RTM_NEWLINK:
 1156:       return netlink_link_change (snl, h);
 1157:       break;
 1158:     case RTM_DELLINK:
 1159:       return netlink_link_change (snl, h);
 1160:       break;
 1161:     case RTM_NEWADDR:
 1162:       return netlink_interface_addr (snl, h);
 1163:       break;
 1164:     case RTM_DELADDR:
 1165:       return netlink_interface_addr (snl, h);
 1166:       break;
 1167:     default:
 1168:       zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
 1169:       break;
 1170:     }
 1171:   return 0;
 1172: }
 1173: 
 1174: /* Interface lookup by netlink socket. */
 1175: int
 1176: interface_lookup_netlink (void)
 1177: {
 1178:   int ret;
 1179: 
 1180:   /* Get interface information. */
 1181:   ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
 1182:   if (ret < 0)
 1183:     return ret;
 1184:   ret = netlink_parse_info (netlink_interface, &netlink_cmd);
 1185:   if (ret < 0)
 1186:     return ret;
 1187: 
 1188:   /* Get IPv4 address of the interfaces. */
 1189:   ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
 1190:   if (ret < 0)
 1191:     return ret;
 1192:   ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
 1193:   if (ret < 0)
 1194:     return ret;
 1195: 
 1196: #ifdef HAVE_IPV6
 1197:   /* Get IPv6 address of the interfaces. */
 1198:   ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
 1199:   if (ret < 0)
 1200:     return ret;
 1201:   ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
 1202:   if (ret < 0)
 1203:     return ret;
 1204: #endif /* HAVE_IPV6 */
 1205: 
 1206:   return 0;
 1207: }
 1208: 
 1209: /* Routing table read function using netlink interface.  Only called
 1210:    bootstrap time. */
 1211: int
 1212: netlink_route_read (void)
 1213: {
 1214:   int ret;
 1215: 
 1216:   /* Get IPv4 routing table. */
 1217:   ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
 1218:   if (ret < 0)
 1219:     return ret;
 1220:   ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
 1221:   if (ret < 0)
 1222:     return ret;
 1223: 
 1224: #ifdef HAVE_IPV6
 1225:   /* Get IPv6 routing table. */
 1226:   ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
 1227:   if (ret < 0)
 1228:     return ret;
 1229:   ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
 1230:   if (ret < 0)
 1231:     return ret;
 1232: #endif /* HAVE_IPV6 */
 1233: 
 1234:   return 0;
 1235: }
 1236: 
 1237: /* Utility function  comes from iproute2. 
 1238:    Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
 1239: static int
 1240: addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
 1241: {
 1242:   int len;
 1243:   struct rtattr *rta;
 1244: 
 1245:   len = RTA_LENGTH (alen);
 1246: 
 1247:   if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
 1248:     return -1;
 1249: 
 1250:   rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
 1251:   rta->rta_type = type;
 1252:   rta->rta_len = len;
 1253:   memcpy (RTA_DATA (rta), data, alen);
 1254:   n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
 1255: 
 1256:   return 0;
 1257: }
 1258: 
 1259: static int
 1260: rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
 1261: {
 1262:   int len;
 1263:   struct rtattr *subrta;
 1264: 
 1265:   len = RTA_LENGTH (alen);
 1266: 
 1267:   if (RTA_ALIGN (rta->rta_len) + len > maxlen)
 1268:     return -1;
 1269: 
 1270:   subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
 1271:   subrta->rta_type = type;
 1272:   subrta->rta_len = len;
 1273:   memcpy (RTA_DATA (subrta), data, alen);
 1274:   rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
 1275: 
 1276:   return 0;
 1277: }
 1278: 
 1279: /* Utility function comes from iproute2. 
 1280:    Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
 1281: static int
 1282: addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
 1283: {
 1284:   int len;
 1285:   struct rtattr *rta;
 1286: 
 1287:   len = RTA_LENGTH (4);
 1288: 
 1289:   if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
 1290:     return -1;
 1291: 
 1292:   rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
 1293:   rta->rta_type = type;
 1294:   rta->rta_len = len;
 1295:   memcpy (RTA_DATA (rta), &data, 4);
 1296:   n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
 1297: 
 1298:   return 0;
 1299: }
 1300: 
 1301: static int
 1302: netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
 1303: {
 1304:   zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
 1305:   return 0;
 1306: }
 1307: 
 1308: /* sendmsg() to netlink socket then recvmsg(). */
 1309: static int
 1310: netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
 1311: {
 1312:   int status;
 1313:   struct sockaddr_nl snl;
 1314:   struct iovec iov = { (void *) n, n->nlmsg_len };
 1315:   struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
 1316:   int save_errno;
 1317: 
 1318:   memset (&snl, 0, sizeof snl);
 1319:   snl.nl_family = AF_NETLINK;
 1320: 
 1321:   n->nlmsg_seq = ++nl->seq;
 1322: 
 1323:   /* Request an acknowledgement by setting NLM_F_ACK */
 1324:   n->nlmsg_flags |= NLM_F_ACK;
 1325: 
 1326:   if (IS_ZEBRA_DEBUG_KERNEL)
 1327:     zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
 1328:                lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
 1329:                n->nlmsg_seq);
 1330: 
 1331:   /* Send message to netlink interface. */
 1332:   if (zserv_privs.change (ZPRIVS_RAISE))
 1333:     zlog (NULL, LOG_ERR, "Can't raise privileges");
 1334:   status = sendmsg (nl->sock, &msg, 0);
 1335:   save_errno = errno;
 1336:   if (zserv_privs.change (ZPRIVS_LOWER))
 1337:     zlog (NULL, LOG_ERR, "Can't lower privileges");
 1338: 
 1339:   if (status < 0)
 1340:     {
 1341:       zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
 1342:             safe_strerror (save_errno));
 1343:       return -1;
 1344:     }
 1345: 
 1346: 
 1347:   /* 
 1348:    * Get reply from netlink socket. 
 1349:    * The reply should either be an acknowlegement or an error.
 1350:    */
 1351:   return netlink_parse_info (netlink_talk_filter, nl);
 1352: }
 1353: 
 1354: /* Routing table change via netlink interface. */
 1355: static int
 1356: netlink_route (int cmd, int family, void *dest, int length, void *gate,
 1357:                int index, int zebra_flags, int table)
 1358: {
 1359:   int ret;
 1360:   int bytelen;
 1361:   struct sockaddr_nl snl;
 1362:   int discard;
 1363: 
 1364:   struct
 1365:   {
 1366:     struct nlmsghdr n;
 1367:     struct rtmsg r;
 1368:     char buf[NL_PKT_BUF_SIZE];
 1369:   } req;
 1370: 
 1371:   memset (&req, 0, sizeof req);
 1372: 
 1373:   bytelen = (family == AF_INET ? 4 : 16);
 1374: 
 1375:   req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
 1376:   req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
 1377:   req.n.nlmsg_type = cmd;
 1378:   req.r.rtm_family = family;
 1379:   req.r.rtm_table = table;
 1380:   req.r.rtm_dst_len = length;
 1381:   req.r.rtm_protocol = RTPROT_ZEBRA;
 1382:   req.r.rtm_scope = RT_SCOPE_UNIVERSE;
 1383: 
 1384:   if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
 1385:       || (zebra_flags & ZEBRA_FLAG_REJECT))
 1386:     discard = 1;
 1387:   else
 1388:     discard = 0;
 1389: 
 1390:   if (cmd == RTM_NEWROUTE)
 1391:     {
 1392:       if (discard)
 1393:         {
 1394:           if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
 1395:             req.r.rtm_type = RTN_BLACKHOLE;
 1396:           else if (zebra_flags & ZEBRA_FLAG_REJECT)
 1397:             req.r.rtm_type = RTN_UNREACHABLE;
 1398:           else
 1399:             assert (RTN_BLACKHOLE != RTN_UNREACHABLE);  /* false */
 1400:         }
 1401:       else
 1402:         req.r.rtm_type = RTN_UNICAST;
 1403:     }
 1404: 
 1405:   if (dest)
 1406:     addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
 1407: 
 1408:   if (!discard)
 1409:     {
 1410:       if (gate)
 1411:         addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
 1412:       if (index > 0)
 1413:         addattr32 (&req.n, sizeof req, RTA_OIF, index);
 1414:     }
 1415: 
 1416:   /* Destination netlink address. */
 1417:   memset (&snl, 0, sizeof snl);
 1418:   snl.nl_family = AF_NETLINK;
 1419: 
 1420:   /* Talk to netlink socket. */
 1421:   ret = netlink_talk (&req.n, &netlink_cmd);
 1422:   if (ret < 0)
 1423:     return -1;
 1424: 
 1425:   return 0;
 1426: }
 1427: 
 1428: /* Routing table change via netlink interface. */
 1429: static int
 1430: netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
 1431:                          int family)
 1432: {
 1433:   int bytelen;
 1434:   struct sockaddr_nl snl;
 1435:   struct nexthop *nexthop = NULL;
 1436:   int nexthop_num = 0;
 1437:   int discard;
 1438: 
 1439:   struct
 1440:   {
 1441:     struct nlmsghdr n;
 1442:     struct rtmsg r;
 1443:     char buf[NL_PKT_BUF_SIZE];
 1444:   } req;
 1445: 
 1446:   memset (&req, 0, sizeof req);
 1447: 
 1448:   bytelen = (family == AF_INET ? 4 : 16);
 1449: 
 1450:   req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
 1451:   req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
 1452:   req.n.nlmsg_type = cmd;
 1453:   req.r.rtm_family = family;
 1454:   req.r.rtm_table = rib->table;
 1455:   req.r.rtm_dst_len = p->prefixlen;
 1456:   req.r.rtm_protocol = RTPROT_ZEBRA;
 1457:   req.r.rtm_scope = RT_SCOPE_UNIVERSE;
 1458: 
 1459:   if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
 1460:     discard = 1;
 1461:   else
 1462:     discard = 0;
 1463: 
 1464:   if (cmd == RTM_NEWROUTE)
 1465:     {
 1466:       if (discard)
 1467:         {
 1468:           if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
 1469:             req.r.rtm_type = RTN_BLACKHOLE;
 1470:           else if (rib->flags & ZEBRA_FLAG_REJECT)
 1471:             req.r.rtm_type = RTN_UNREACHABLE;
 1472:           else
 1473:             assert (RTN_BLACKHOLE != RTN_UNREACHABLE);  /* false */
 1474:         }
 1475:       else
 1476:         req.r.rtm_type = RTN_UNICAST;
 1477:     }
 1478: 
 1479:   addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
 1480: 
 1481:   /* Metric. */
 1482:   addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
 1483: 
 1484:   if (discard)
 1485:     {
 1486:       if (cmd == RTM_NEWROUTE)
 1487:         for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 1488:           SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
 1489:       goto skip;
 1490:     }
 1491: 
 1492:   /* Multipath case. */
 1493:   if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
 1494:     {
 1495:       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 1496:         {
 1497: 
 1498:           if ((cmd == RTM_NEWROUTE
 1499:                && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
 1500:               || (cmd == RTM_DELROUTE
 1501:                   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
 1502:             {
 1503: 
 1504:               if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
 1505:                 {
 1506:                   if (IS_ZEBRA_DEBUG_KERNEL)
 1507:                     {
 1508:                       zlog_debug
 1509:                         ("netlink_route_multipath() (recursive, 1 hop): "
 1510:                          "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
 1511: #ifdef HAVE_IPV6
 1512: 			 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 1513: 			 inet6_ntoa (p->u.prefix6),
 1514: #else
 1515: 			 inet_ntoa (p->u.prefix4),
 1516: #endif /* HAVE_IPV6 */
 1517: 			 
 1518: 			 p->prefixlen, nexthop_types_desc[nexthop->rtype]);
 1519:                     }
 1520: 
 1521:                   if (nexthop->rtype == NEXTHOP_TYPE_IPV4
 1522:                       || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
 1523: 		    {
 1524: 		      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 1525: 				 &nexthop->rgate.ipv4, bytelen);
 1526:                       if (nexthop->src.ipv4.s_addr)
 1527: 		          addattr_l(&req.n, sizeof req, RTA_PREFSRC,
 1528: 				     &nexthop->src.ipv4, bytelen);
 1529: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1530: 			zlog_debug("netlink_route_multipath() (recursive, "
 1531: 				   "1 hop): nexthop via %s if %u",
 1532: 				   inet_ntoa (nexthop->rgate.ipv4),
 1533: 				   nexthop->rifindex);
 1534: 		    }
 1535: #ifdef HAVE_IPV6
 1536:                   if (nexthop->rtype == NEXTHOP_TYPE_IPV6
 1537:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
 1538:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
 1539: 		    {
 1540: 		      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 1541: 				 &nexthop->rgate.ipv6, bytelen);
 1542: 
 1543: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1544: 			zlog_debug("netlink_route_multipath() (recursive, "
 1545: 				   "1 hop): nexthop via %s if %u",
 1546: 				   inet6_ntoa (nexthop->rgate.ipv6),
 1547: 				   nexthop->rifindex);
 1548: 		    }
 1549: #endif /* HAVE_IPV6 */
 1550:                   if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
 1551:                       || nexthop->rtype == NEXTHOP_TYPE_IFNAME
 1552:                       || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
 1553:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
 1554:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
 1555: 		    {
 1556: 		      addattr32 (&req.n, sizeof req, RTA_OIF,
 1557: 				 nexthop->rifindex);
 1558:                       if ((nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
 1559:                            || nexthop->rtype == NEXTHOP_TYPE_IFINDEX)
 1560:                           && nexthop->src.ipv4.s_addr)
 1561:                         addattr_l (&req.n, sizeof req, RTA_PREFSRC,
 1562: 				 &nexthop->src.ipv4, bytelen);
 1563: 
 1564: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1565: 			zlog_debug("netlink_route_multipath() (recursive, "
 1566: 				   "1 hop): nexthop via if %u",
 1567: 				   nexthop->rifindex);
 1568: 		    }
 1569:                 }
 1570:               else
 1571:                 {
 1572:                   if (IS_ZEBRA_DEBUG_KERNEL)
 1573:                     {
 1574:                       zlog_debug
 1575:                         ("netlink_route_multipath() (single hop): "
 1576:                          "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
 1577: #ifdef HAVE_IPV6
 1578: 			 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 1579: 			 inet6_ntoa (p->u.prefix6),
 1580: #else
 1581: 			 inet_ntoa (p->u.prefix4),
 1582: #endif /* HAVE_IPV6 */
 1583: 			 p->prefixlen, nexthop_types_desc[nexthop->type]);
 1584:                     }
 1585: 
 1586:                   if (nexthop->type == NEXTHOP_TYPE_IPV4
 1587:                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 1588: 		    {
 1589: 		      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 1590: 				 &nexthop->gate.ipv4, bytelen);
 1591: 		      if (nexthop->src.ipv4.s_addr)
 1592:                         addattr_l (&req.n, sizeof req, RTA_PREFSRC,
 1593: 				 &nexthop->src.ipv4, bytelen);
 1594: 
 1595: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1596: 			zlog_debug("netlink_route_multipath() (single hop): "
 1597: 				   "nexthop via %s if %u",
 1598: 				   inet_ntoa (nexthop->gate.ipv4),
 1599: 				   nexthop->ifindex);
 1600: 		    }
 1601: #ifdef HAVE_IPV6
 1602:                   if (nexthop->type == NEXTHOP_TYPE_IPV6
 1603:                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
 1604:                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
 1605: 		    {
 1606: 		      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 1607: 				 &nexthop->gate.ipv6, bytelen);
 1608: 
 1609: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1610: 			zlog_debug("netlink_route_multipath() (single hop): "
 1611: 				   "nexthop via %s if %u",
 1612: 				   inet6_ntoa (nexthop->gate.ipv6),
 1613: 				   nexthop->ifindex);
 1614: 		    }
 1615: #endif /* HAVE_IPV6 */
 1616:                   if (nexthop->type == NEXTHOP_TYPE_IFINDEX
 1617:                       || nexthop->type == NEXTHOP_TYPE_IFNAME
 1618:                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 1619: 		    {
 1620: 		      addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
 1621: 
 1622: 		      if (nexthop->src.ipv4.s_addr)
 1623:                         addattr_l (&req.n, sizeof req, RTA_PREFSRC,
 1624: 				 &nexthop->src.ipv4, bytelen);
 1625: 
 1626: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1627: 			zlog_debug("netlink_route_multipath() (single hop): "
 1628: 				   "nexthop via if %u", nexthop->ifindex);
 1629: 		    }
 1630:                   else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
 1631:                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
 1632: 		    {
 1633: 		      addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
 1634: 
 1635: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1636: 			zlog_debug("netlink_route_multipath() (single hop): "
 1637: 				   "nexthop via if %u", nexthop->ifindex);
 1638: 		    }
 1639:                 }
 1640: 
 1641:               if (cmd == RTM_NEWROUTE)
 1642:                 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
 1643: 
 1644:               nexthop_num++;
 1645:               break;
 1646:             }
 1647:         }
 1648:     }
 1649:   else
 1650:     {
 1651:       char buf[NL_PKT_BUF_SIZE];
 1652:       struct rtattr *rta = (void *) buf;
 1653:       struct rtnexthop *rtnh;
 1654:       union g_addr *src = NULL;
 1655: 
 1656:       rta->rta_type = RTA_MULTIPATH;
 1657:       rta->rta_len = RTA_LENGTH (0);
 1658:       rtnh = RTA_DATA (rta);
 1659: 
 1660:       nexthop_num = 0;
 1661:       for (nexthop = rib->nexthop;
 1662:            nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
 1663:            nexthop = nexthop->next)
 1664:         {
 1665:           if ((cmd == RTM_NEWROUTE
 1666:                && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
 1667:               || (cmd == RTM_DELROUTE
 1668:                   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
 1669:             {
 1670:               nexthop_num++;
 1671: 
 1672:               rtnh->rtnh_len = sizeof (*rtnh);
 1673:               rtnh->rtnh_flags = 0;
 1674:               rtnh->rtnh_hops = 0;
 1675:               rta->rta_len += rtnh->rtnh_len;
 1676: 
 1677:               if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
 1678:                 {
 1679:                   if (IS_ZEBRA_DEBUG_KERNEL)
 1680:                     {
 1681:                       zlog_debug ("netlink_route_multipath() "
 1682:                          "(recursive, multihop): %s %s/%d type %s",
 1683: 			 lookup (nlmsg_str, cmd),
 1684: #ifdef HAVE_IPV6
 1685: 			 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 1686: 			 inet6_ntoa (p->u.prefix6),
 1687: #else
 1688: 			 inet_ntoa (p->u.prefix4),
 1689: #endif /* HAVE_IPV6 */
 1690:                          p->prefixlen, nexthop_types_desc[nexthop->rtype]);
 1691:                     }
 1692:                   if (nexthop->rtype == NEXTHOP_TYPE_IPV4
 1693:                       || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
 1694:                     {
 1695:                       rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
 1696:                                      &nexthop->rgate.ipv4, bytelen);
 1697:                       rtnh->rtnh_len += sizeof (struct rtattr) + 4;
 1698: 
 1699: 		      if (nexthop->src.ipv4.s_addr)
 1700:                         src = &nexthop->src;
 1701: 
 1702: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1703: 			zlog_debug("netlink_route_multipath() (recursive, "
 1704: 				   "multihop): nexthop via %s if %u",
 1705: 				   inet_ntoa (nexthop->rgate.ipv4),
 1706: 				   nexthop->rifindex);
 1707:                     }
 1708: #ifdef HAVE_IPV6
 1709:                   if (nexthop->rtype == NEXTHOP_TYPE_IPV6
 1710:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
 1711:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
 1712: 		    {
 1713: 		      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
 1714: 				     &nexthop->rgate.ipv6, bytelen);
 1715: 
 1716: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1717: 			zlog_debug("netlink_route_multipath() (recursive, "
 1718: 				   "multihop): nexthop via %s if %u",
 1719: 				   inet6_ntoa (nexthop->rgate.ipv6),
 1720: 				   nexthop->rifindex);
 1721: 		    }
 1722: #endif /* HAVE_IPV6 */
 1723:                   /* ifindex */
 1724:                   if (nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
 1725: 		      || nexthop->rtype == NEXTHOP_TYPE_IFINDEX
 1726:                       || nexthop->rtype == NEXTHOP_TYPE_IFNAME)
 1727: 		    {
 1728: 		      rtnh->rtnh_ifindex = nexthop->rifindex;
 1729:                       if (nexthop->src.ipv4.s_addr)
 1730:                         src = &nexthop->src;
 1731: 
 1732: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1733: 			zlog_debug("netlink_route_multipath() (recursive, "
 1734: 				   "multihop): nexthop via if %u",
 1735: 				   nexthop->rifindex);
 1736: 		    }
 1737: 		  else if (nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
 1738:                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
 1739: 		    {
 1740: 		      rtnh->rtnh_ifindex = nexthop->rifindex;
 1741: 
 1742: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1743: 			zlog_debug("netlink_route_multipath() (recursive, "
 1744: 				   "multihop): nexthop via if %u",
 1745: 				   nexthop->rifindex);
 1746: 		    }
 1747:                   else
 1748: 		    {
 1749: 		      rtnh->rtnh_ifindex = 0;
 1750: 		    }
 1751:                 }
 1752:               else
 1753:                 {
 1754:                   if (IS_ZEBRA_DEBUG_KERNEL)
 1755:                     {
 1756:                       zlog_debug ("netlink_route_multipath() (multihop): "
 1757:                          "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
 1758: #ifdef HAVE_IPV6
 1759: 			 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 1760: 			 inet6_ntoa (p->u.prefix6),
 1761: #else
 1762: 			 inet_ntoa (p->u.prefix4),
 1763: #endif /* HAVE_IPV6 */
 1764: 			 p->prefixlen, nexthop_types_desc[nexthop->type]);
 1765:                     }
 1766:                   if (nexthop->type == NEXTHOP_TYPE_IPV4
 1767:                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 1768:                     {
 1769: 		      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
 1770: 				     &nexthop->gate.ipv4, bytelen);
 1771: 		      rtnh->rtnh_len += sizeof (struct rtattr) + 4;
 1772: 
 1773: 		      if (nexthop->src.ipv4.s_addr)
 1774:                         src = &nexthop->src;
 1775: 
 1776:                       if (IS_ZEBRA_DEBUG_KERNEL)
 1777: 			zlog_debug("netlink_route_multipath() (multihop): "
 1778: 				   "nexthop via %s if %u",
 1779: 				   inet_ntoa (nexthop->gate.ipv4),
 1780: 				   nexthop->ifindex);
 1781:                     }
 1782: #ifdef HAVE_IPV6
 1783:                   if (nexthop->type == NEXTHOP_TYPE_IPV6
 1784:                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
 1785:                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
 1786: 		    { 
 1787: 		      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
 1788: 				     &nexthop->gate.ipv6, bytelen);
 1789: 
 1790: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1791: 			zlog_debug("netlink_route_multipath() (multihop): "
 1792: 				   "nexthop via %s if %u",
 1793: 				   inet6_ntoa (nexthop->gate.ipv6),
 1794: 				   nexthop->ifindex);
 1795: 		    }
 1796: #endif /* HAVE_IPV6 */
 1797:                   /* ifindex */
 1798:                   if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
 1799: 		      || nexthop->type == NEXTHOP_TYPE_IFINDEX
 1800:                       || nexthop->type == NEXTHOP_TYPE_IFNAME)
 1801:                     {
 1802: 		      rtnh->rtnh_ifindex = nexthop->ifindex;
 1803: 		      if (nexthop->src.ipv4.s_addr)
 1804: 			src = &nexthop->src;
 1805: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1806: 			zlog_debug("netlink_route_multipath() (multihop): "
 1807: 				   "nexthop via if %u", nexthop->ifindex);
 1808: 		    }
 1809:                   else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
 1810:                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
 1811: 		    {
 1812: 		      rtnh->rtnh_ifindex = nexthop->ifindex;
 1813: 
 1814: 		      if (IS_ZEBRA_DEBUG_KERNEL)
 1815: 			zlog_debug("netlink_route_multipath() (multihop): "
 1816: 				   "nexthop via if %u", nexthop->ifindex);
 1817: 		    }
 1818:                   else
 1819: 		    {
 1820: 		      rtnh->rtnh_ifindex = 0;
 1821: 		    }
 1822:                 }
 1823:               rtnh = RTNH_NEXT (rtnh);
 1824: 
 1825:               if (cmd == RTM_NEWROUTE)
 1826:                 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
 1827:             }
 1828:         }
 1829:       if (src)
 1830:         addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
 1831: 
 1832:       if (rta->rta_len > RTA_LENGTH (0))
 1833:         addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
 1834:                    RTA_PAYLOAD (rta));
 1835:     }
 1836: 
 1837:   /* If there is no useful nexthop then return. */
 1838:   if (nexthop_num == 0)
 1839:     {
 1840:       if (IS_ZEBRA_DEBUG_KERNEL)
 1841:         zlog_debug ("netlink_route_multipath(): No useful nexthop.");
 1842:       return 0;
 1843:     }
 1844: 
 1845: skip:
 1846: 
 1847:   /* Destination netlink address. */
 1848:   memset (&snl, 0, sizeof snl);
 1849:   snl.nl_family = AF_NETLINK;
 1850: 
 1851:   /* Talk to netlink socket. */
 1852:   return netlink_talk (&req.n, &netlink_cmd);
 1853: }
 1854: 
 1855: int
 1856: kernel_add_ipv4 (struct prefix *p, struct rib *rib)
 1857: {
 1858:   return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
 1859: }
 1860: 
 1861: int
 1862: kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
 1863: {
 1864:   return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
 1865: }
 1866: 
 1867: #ifdef HAVE_IPV6
 1868: int
 1869: kernel_add_ipv6 (struct prefix *p, struct rib *rib)
 1870: {
 1871:   return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
 1872: }
 1873: 
 1874: int
 1875: kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
 1876: {
 1877:   return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
 1878: }
 1879: 
 1880: /* Delete IPv6 route from the kernel. */
 1881: int
 1882: kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
 1883:                         unsigned int index, int flags, int table)
 1884: {
 1885:   return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
 1886:                         dest->prefixlen, gate, index, flags, table);
 1887: }
 1888: #endif /* HAVE_IPV6 */
 1889: 
 1890: /* Interface address modification. */
 1891: static int
 1892: netlink_address (int cmd, int family, struct interface *ifp,
 1893:                  struct connected *ifc)
 1894: {
 1895:   int bytelen;
 1896:   struct prefix *p;
 1897: 
 1898:   struct
 1899:   {
 1900:     struct nlmsghdr n;
 1901:     struct ifaddrmsg ifa;
 1902:     char buf[NL_PKT_BUF_SIZE];
 1903:   } req;
 1904: 
 1905:   p = ifc->address;
 1906:   memset (&req, 0, sizeof req);
 1907: 
 1908:   bytelen = (family == AF_INET ? 4 : 16);
 1909: 
 1910:   req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
 1911:   req.n.nlmsg_flags = NLM_F_REQUEST;
 1912:   req.n.nlmsg_type = cmd;
 1913:   req.ifa.ifa_family = family;
 1914: 
 1915:   req.ifa.ifa_index = ifp->ifindex;
 1916:   req.ifa.ifa_prefixlen = p->prefixlen;
 1917: 
 1918:   addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
 1919: 
 1920:   if (family == AF_INET && cmd == RTM_NEWADDR)
 1921:     {
 1922:       if (!CONNECTED_PEER(ifc) && ifc->destination)
 1923:         {
 1924:           p = ifc->destination;
 1925:           addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
 1926:                      bytelen);
 1927:         }
 1928:     }
 1929: 
 1930:   if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
 1931:     SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
 1932: 
 1933:   if (ifc->label)
 1934:     addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
 1935:                strlen (ifc->label) + 1);
 1936: 
 1937:   return netlink_talk (&req.n, &netlink_cmd);
 1938: }
 1939: 
 1940: int
 1941: kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
 1942: {
 1943:   return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
 1944: }
 1945: 
 1946: int
 1947: kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
 1948: {
 1949:   return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
 1950: }
 1951: 
 1952: 
 1953: extern struct thread_master *master;
 1954: 
 1955: /* Kernel route reflection. */
 1956: static int
 1957: kernel_read (struct thread *thread)
 1958: {
 1959:   netlink_parse_info (netlink_information_fetch, &netlink);
 1960:   thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
 1961: 
 1962:   return 0;
 1963: }
 1964: 
 1965: /* Filter out messages from self that occur on listener socket,
 1966:    caused by our actions on the command socket
 1967:  */
 1968: static void netlink_install_filter (int sock, __u32 pid)
 1969: {
 1970:   struct sock_filter filter[] = {
 1971:     /* 0: ldh [4]	          */
 1972:     BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
 1973:     /* 1: jeq 0x18 jt 3 jf 6  */
 1974:     BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
 1975:     /* 2: jeq 0x19 jt 3 jf 6  */
 1976:     BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
 1977:     /* 3: ldw [12]		  */
 1978:     BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
 1979:     /* 4: jeq XX  jt 5 jf 6   */
 1980:     BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
 1981:     /* 5: ret 0    (skip)     */
 1982:     BPF_STMT(BPF_RET|BPF_K, 0),
 1983:     /* 6: ret 0xffff (keep)   */
 1984:     BPF_STMT(BPF_RET|BPF_K, 0xffff),
 1985:   };
 1986: 
 1987:   struct sock_fprog prog = {
 1988:     .len = sizeof(filter) / sizeof(filter[0]),
 1989:     .filter = filter,
 1990:   };
 1991: 
 1992:   if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
 1993:     zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
 1994: }
 1995: 
 1996: /* Exported interface function.  This function simply calls
 1997:    netlink_socket (). */
 1998: void
 1999: kernel_init (void)
 2000: {
 2001:   unsigned long groups;
 2002: 
 2003:   groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
 2004: #ifdef HAVE_IPV6
 2005:   groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
 2006: #endif /* HAVE_IPV6 */
 2007:   netlink_socket (&netlink, groups);
 2008:   netlink_socket (&netlink_cmd, 0);
 2009: 
 2010:   /* Register kernel socket. */
 2011:   if (netlink.sock > 0)
 2012:     {
 2013:       /* Only want non-blocking on the netlink event socket */
 2014:       if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0)
 2015: 	zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name,
 2016: 		safe_strerror (errno));
 2017: 
 2018:       /* Set receive buffer size if it's set from command line */
 2019:       if (nl_rcvbufsize)
 2020: 	netlink_recvbuf (&netlink, nl_rcvbufsize);
 2021: 
 2022:       netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid);
 2023:       thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
 2024:     }
 2025: }

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