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

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

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