Diff for /embedaddon/quagga/zebra/rt_netlink.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 17:26:11 version 1.1.1.2, 2012/10/09 09:22:29
Line 32 Line 32
 #include "prefix.h"  #include "prefix.h"
 #include "connected.h"  #include "connected.h"
 #include "table.h"  #include "table.h"
   #include "memory.h"
 #include "rib.h"  #include "rib.h"
 #include "thread.h"  #include "thread.h"
 #include "privs.h"  #include "privs.h"
Line 42 Line 43
 #include "zebra/interface.h"  #include "zebra/interface.h"
 #include "zebra/debug.h"  #include "zebra/debug.h"
   
   #define NL_PKT_BUF_SIZE 4096
   
 /* Socket interface to kernel */  /* Socket interface to kernel */
 struct nlsock  struct nlsock
 {  {
Line 280  netlink_parse_info (int (*filter) (struct sockaddr_nl  Line 283  netlink_parse_info (int (*filter) (struct sockaddr_nl 
   
   while (1)    while (1)
     {      {
      char buf[4096];      char buf[NL_PKT_BUF_SIZE];
       struct iovec iov = { buf, sizeof buf };        struct iovec iov = { buf, sizeof buf };
       struct sockaddr_nl snl;        struct sockaddr_nl snl;
       struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };        struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
Line 426  netlink_parse_rtattr (struct rtattr **tb, int max, str Line 429  netlink_parse_rtattr (struct rtattr **tb, int max, str
     }      }
 }  }
   
   /* Utility function to parse hardware link-layer address and update ifp */
   static void
   netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
   {
     int i;
   
     if (tb[IFLA_ADDRESS])
       {
         int hw_addr_len;
   
         hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
   
         if (hw_addr_len > INTERFACE_HWADDR_MAX)
           zlog_warn ("Hardware address is too large: %d", hw_addr_len);
         else
           {
             ifp->hw_addr_len = hw_addr_len;
             memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
   
             for (i = 0; i < hw_addr_len; i++)
               if (ifp->hw_addr[i] != 0)
                 break;
   
             if (i == hw_addr_len)
               ifp->hw_addr_len = 0;
             else
               ifp->hw_addr_len = hw_addr_len;
           }
       }
   }
   
 /* Called from interface_lookup_netlink().  This function is only used  /* Called from interface_lookup_netlink().  This function is only used
    during bootstrap. */     during bootstrap. */
 static int  static int
Line 436  netlink_interface (struct sockaddr_nl *snl, struct nlm Line 470  netlink_interface (struct sockaddr_nl *snl, struct nlm
   struct rtattr *tb[IFLA_MAX + 1];    struct rtattr *tb[IFLA_MAX + 1];
   struct interface *ifp;    struct interface *ifp;
   char *name;    char *name;
   int i;  
   
   ifi = NLMSG_DATA (h);    ifi = NLMSG_DATA (h);
   
Line 474  netlink_interface (struct sockaddr_nl *snl, struct nlm Line 507  netlink_interface (struct sockaddr_nl *snl, struct nlm
   
   /* Hardware type and address. */    /* Hardware type and address. */
   ifp->hw_type = ifi->ifi_type;    ifp->hw_type = ifi->ifi_type;
     netlink_interface_update_hw_addr (tb, ifp);
   
   if (tb[IFLA_ADDRESS])  
     {  
       int hw_addr_len;  
   
       hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);  
   
       if (hw_addr_len > INTERFACE_HWADDR_MAX)  
         zlog_warn ("Hardware address is too large: %d", hw_addr_len);  
       else  
         {  
           ifp->hw_addr_len = hw_addr_len;  
           memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);  
   
           for (i = 0; i < hw_addr_len; i++)  
             if (ifp->hw_addr[i] != 0)  
               break;  
   
           if (i == hw_addr_len)  
             ifp->hw_addr_len = 0;  
           else  
             ifp->hw_addr_len = hw_addr_len;  
         }  
     }  
   
   if_add_update (ifp);    if_add_update (ifp);
   
   return 0;    return 0;
Line 709  netlink_routing_table (struct sockaddr_nl *snl, struct Line 719  netlink_routing_table (struct sockaddr_nl *snl, struct
   if (tb[RTA_PREFSRC])    if (tb[RTA_PREFSRC])
     src = RTA_DATA (tb[RTA_PREFSRC]);      src = RTA_DATA (tb[RTA_PREFSRC]);
   
   /* Multipath treatment is needed. */  
   if (tb[RTA_GATEWAY])    if (tb[RTA_GATEWAY])
     gate = RTA_DATA (tb[RTA_GATEWAY]);      gate = RTA_DATA (tb[RTA_GATEWAY]);
   
Line 723  netlink_routing_table (struct sockaddr_nl *snl, struct Line 732  netlink_routing_table (struct sockaddr_nl *snl, struct
       memcpy (&p.prefix, dest, 4);        memcpy (&p.prefix, dest, 4);
       p.prefixlen = rtm->rtm_dst_len;        p.prefixlen = rtm->rtm_dst_len;
   
      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0);      if (!tb[RTA_MULTIPATH])
           rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
                         table, metric, 0, SAFI_UNICAST);
       else
         {
           /* This is a multipath route */
 
           struct rib *rib;
           struct rtnexthop *rtnh =
             (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
 
           len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
 
           rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
           rib->type = ZEBRA_ROUTE_KERNEL;
           rib->distance = 0;
           rib->flags = flags;
           rib->metric = metric;
           rib->table = table;
           rib->nexthop_num = 0;
           rib->uptime = time (NULL);
 
           for (;;)
             {
               if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
                 break;
 
               rib->nexthop_num++;
               index = rtnh->rtnh_ifindex;
               gate = 0;
               if (rtnh->rtnh_len > sizeof (*rtnh))
                 {
                   memset (tb, 0, sizeof (tb));
                   netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
                                         rtnh->rtnh_len - sizeof (*rtnh));
                   if (tb[RTA_GATEWAY])
                     gate = RTA_DATA (tb[RTA_GATEWAY]);
                 }
 
               if (gate)
                 {
                   if (index)
                     nexthop_ipv4_ifindex_add (rib, gate, src, index);
                   else
                     nexthop_ipv4_add (rib, gate, src);
                 }
               else
                 nexthop_ifindex_add (rib, index);
 
               len -= NLMSG_ALIGN(rtnh->rtnh_len);
               rtnh = RTNH_NEXT(rtnh);
             }
 
           if (rib->nexthop_num == 0)
             XFREE (MTYPE_RIB, rib);
           else
             rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
         }
     }      }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   if (rtm->rtm_family == AF_INET6)    if (rtm->rtm_family == AF_INET6)
Line 734  netlink_routing_table (struct sockaddr_nl *snl, struct Line 800  netlink_routing_table (struct sockaddr_nl *snl, struct
       p.prefixlen = rtm->rtm_dst_len;        p.prefixlen = rtm->rtm_dst_len;
   
       rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table,        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table,
                    metric, 0);                    metric, 0, SAFI_UNICAST);
     }      }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
   
Line 867  netlink_route_change (struct sockaddr_nl *snl, struct  Line 933  netlink_route_change (struct sockaddr_nl *snl, struct 
         }          }
   
       if (h->nlmsg_type == RTM_NEWROUTE)        if (h->nlmsg_type == RTM_NEWROUTE)
        rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, metric, 0);        {
           if (!tb[RTA_MULTIPATH])
             rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
                           metric, 0, SAFI_UNICAST);
           else
             {
               /* This is a multipath route */
 
               struct rib *rib;
               struct rtnexthop *rtnh =
                 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
 
               len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
 
               rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
               rib->type = ZEBRA_ROUTE_KERNEL;
               rib->distance = 0;
               rib->flags = 0;
               rib->metric = metric;
               rib->table = table;
               rib->nexthop_num = 0;
               rib->uptime = time (NULL);
 
               for (;;)
                 {
                   if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
                     break;
 
                   rib->nexthop_num++;
                   index = rtnh->rtnh_ifindex;
                   gate = 0;
                   if (rtnh->rtnh_len > sizeof (*rtnh))
                     {
                       memset (tb, 0, sizeof (tb));
                       netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
                                             rtnh->rtnh_len - sizeof (*rtnh));
                       if (tb[RTA_GATEWAY])
                         gate = RTA_DATA (tb[RTA_GATEWAY]);
                     }
 
                   if (gate)
                     {
                       if (index)
                         nexthop_ipv4_ifindex_add (rib, gate, src, index);
                       else
                         nexthop_ipv4_add (rib, gate, src);
                     }
                   else
                     nexthop_ifindex_add (rib, index);
 
                   len -= NLMSG_ALIGN(rtnh->rtnh_len);
                   rtnh = RTNH_NEXT(rtnh);
                 }
 
               if (rib->nexthop_num == 0)
                 XFREE (MTYPE_RIB, rib);
               else
                 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
             }
         }
       else        else
        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
     }      }
   
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
Line 895  netlink_route_change (struct sockaddr_nl *snl, struct  Line 1020  netlink_route_change (struct sockaddr_nl *snl, struct 
         }          }
   
       if (h->nlmsg_type == RTM_NEWROUTE)        if (h->nlmsg_type == RTM_NEWROUTE)
        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, metric, 0);        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST);
       else        else
        rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);        rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
     }      }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
   
Line 960  netlink_link_change (struct sockaddr_nl *snl, struct n Line 1085  netlink_link_change (struct sockaddr_nl *snl, struct n
           ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);            ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
           ifp->metric = 1;            ifp->metric = 1;
   
             netlink_interface_update_hw_addr (tb, ifp);
   
           /* If new link is added. */            /* If new link is added. */
           if_add_update (ifp);            if_add_update (ifp);
         }          }
Line 970  netlink_link_change (struct sockaddr_nl *snl, struct n Line 1097  netlink_link_change (struct sockaddr_nl *snl, struct n
           ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);            ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
           ifp->metric = 1;            ifp->metric = 1;
   
             netlink_interface_update_hw_addr (tb, ifp);
   
           if (if_is_operative (ifp))            if (if_is_operative (ifp))
             {              {
               ifp->flags = ifi->ifi_flags & 0x0000fffff;                ifp->flags = ifi->ifi_flags & 0x0000fffff;
Line 1236  netlink_route (int cmd, int family, void *dest, int le Line 1365  netlink_route (int cmd, int family, void *dest, int le
   {    {
     struct nlmsghdr n;      struct nlmsghdr n;
     struct rtmsg r;      struct rtmsg r;
    char buf[1024];    char buf[NL_PKT_BUF_SIZE];
   } req;    } req;
   
   memset (&req, 0, sizeof req);    memset (&req, 0, sizeof req);
Line 1311  netlink_route_multipath (int cmd, struct prefix *p, st Line 1440  netlink_route_multipath (int cmd, struct prefix *p, st
   {    {
     struct nlmsghdr n;      struct nlmsghdr n;
     struct rtmsg r;      struct rtmsg r;
    char buf[1024];    char buf[NL_PKT_BUF_SIZE];
   } req;    } req;
   
   memset (&req, 0, sizeof req);    memset (&req, 0, sizeof req);
Line 1519  netlink_route_multipath (int cmd, struct prefix *p, st Line 1648  netlink_route_multipath (int cmd, struct prefix *p, st
     }      }
   else    else
     {      {
      char buf[1024];      char buf[NL_PKT_BUF_SIZE];
       struct rtattr *rta = (void *) buf;        struct rtattr *rta = (void *) buf;
       struct rtnexthop *rtnh;        struct rtnexthop *rtnh;
       union g_addr *src = NULL;        union g_addr *src = NULL;
Line 1563  netlink_route_multipath (int cmd, struct prefix *p, st Line 1692  netlink_route_multipath (int cmd, struct prefix *p, st
                   if (nexthop->rtype == NEXTHOP_TYPE_IPV4                    if (nexthop->rtype == NEXTHOP_TYPE_IPV4
                       || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)                        || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
                     {                      {
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,                      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
                                      &nexthop->rgate.ipv4, bytelen);                                       &nexthop->rgate.ipv4, bytelen);
                       rtnh->rtnh_len += sizeof (struct rtattr) + 4;                        rtnh->rtnh_len += sizeof (struct rtattr) + 4;
   
Line 1581  netlink_route_multipath (int cmd, struct prefix *p, st Line 1710  netlink_route_multipath (int cmd, struct prefix *p, st
                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME                        || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
                       || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)                        || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
                     {                      {
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,                      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
                                      &nexthop->rgate.ipv6, bytelen);                                       &nexthop->rgate.ipv6, bytelen);
   
                       if (IS_ZEBRA_DEBUG_KERNEL)                        if (IS_ZEBRA_DEBUG_KERNEL)
Line 1637  netlink_route_multipath (int cmd, struct prefix *p, st Line 1766  netlink_route_multipath (int cmd, struct prefix *p, st
                   if (nexthop->type == NEXTHOP_TYPE_IPV4                    if (nexthop->type == NEXTHOP_TYPE_IPV4
                       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)                        || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
                     {                      {
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,                      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
                                      &nexthop->gate.ipv4, bytelen);                                       &nexthop->gate.ipv4, bytelen);
                       rtnh->rtnh_len += sizeof (struct rtattr) + 4;                        rtnh->rtnh_len += sizeof (struct rtattr) + 4;
   
Line 1655  netlink_route_multipath (int cmd, struct prefix *p, st Line 1784  netlink_route_multipath (int cmd, struct prefix *p, st
                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME                        || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
                       || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)                        || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
                     {                       { 
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,                      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
                                      &nexthop->gate.ipv6, bytelen);                                       &nexthop->gate.ipv6, bytelen);
   
                       if (IS_ZEBRA_DEBUG_KERNEL)                        if (IS_ZEBRA_DEBUG_KERNEL)
Line 1701  netlink_route_multipath (int cmd, struct prefix *p, st Line 1830  netlink_route_multipath (int cmd, struct prefix *p, st
         addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);          addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
   
       if (rta->rta_len > RTA_LENGTH (0))        if (rta->rta_len > RTA_LENGTH (0))
        addattr_l (&req.n1024, RTA_MULTIPATH, RTA_DATA (rta),        addattr_l (&req.nNL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
                    RTA_PAYLOAD (rta));                     RTA_PAYLOAD (rta));
     }      }
   
Line 1770  netlink_address (int cmd, int family, struct interface Line 1899  netlink_address (int cmd, int family, struct interface
   {    {
     struct nlmsghdr n;      struct nlmsghdr n;
     struct ifaddrmsg ifa;      struct ifaddrmsg ifa;
    char buf[1024];    char buf[NL_PKT_BUF_SIZE];
   } req;    } req;
   
   p = ifc->address;    p = ifc->address;
Line 1827  extern struct thread_master *master; Line 1956  extern struct thread_master *master;
 static int  static int
 kernel_read (struct thread *thread)  kernel_read (struct thread *thread)
 {  {
  int ret;  netlink_parse_info (netlink_information_fetch, &netlink);
  int sock; 
 
  sock = THREAD_FD (thread); 
  ret = netlink_parse_info (netlink_information_fetch, &netlink); 
   thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);    thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
   
   return 0;    return 0;

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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