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

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