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.n, 1024, RTA_MULTIPATH, RTA_DATA (rta), | addattr_l (&req.n, NL_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; |