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

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