LCOV - code coverage report
Current view: top level - zebra - rt_netlink.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 563 906 62.1 %
Date: 2015-11-19 Functions: 31 38 81.6 %

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

Generated by: LCOV version 1.10