Annotation of embedaddon/quagga/zebra/rt_netlink.c, revision 1.1.1.3

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

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