From 27b472533bc8bb0fdb37dcda7596c385d3b9f414 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Sun, 2 Jul 2006 16:38:54 +0000 Subject: [zebra] Fix CID #104, check addr for null, and #18, check nexthop type args 2006-07-02 Paul Jakma * rt_netlink.c: (netlink_interface_addr) Fix CID #104, can not proceed if addr is NULL. * zebra_rib.c: (static_add_ipv6) Fix CID #18, double check required arguments are supplied for the given nexthop type. --- zebra/rt_netlink.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index f1c1a300..216625e9 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -673,6 +673,13 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) broad = NULL; } + /* addr is primary key, SOL if we don't have one */ + if (addr == NULL) + { + zlog_debug ("%s: NULL address", __func__); + return -1; + } + /* Flags. */ if (ifa->ifa_flags & IFA_F_SECONDARY) SET_FLAG (flags, ZEBRA_IFA_SECONDARY); -- cgit v1.2.3 From e4529636b77124285cca96a62799d0ff6a7addeb Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Tue, 12 Dec 2006 19:18:21 +0000 Subject: [PtP over ethernet] New peer flag allows much more addressing flexibility 2006-12-12 Andrew J. Schorr * if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating whether a peer address has been configured. Comment now shows the new interpretation of the destination addr: if ZEBRA_IFA_PEER is set, then it must contain the destination address, otherwise it may contain the broadcast address or be NULL. (CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete macros that were specific to IPv4 and not fully general. (CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag. (CONNECTED_PREFIX) New macro giving the prefix to insert into the RIB: if CONNECTED_PEER, then use the destination (peer) address, else use the address field. (CONNECTED_ID) New macro to come up with an identifying address for the struct connected. * if.c: (if_lookup_address, connected_lookup_address) Streamline logic with new CONNECTED_PREFIX macro. * prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros for better performance than the general prefix_copy function. * zclient.c: (zebra_interface_address_read) For non-null destination addresses, set prefixlen to equal the address prefixlen. This is needed to get the new CONNECTED_PREFIX macro to work properly. * connected.c: (connected_up_ipv4, connected_down_ipv4, connected_up_ipv6, connected_down_ipv6) Simplify logic using the new CONNECTED_PREFIX macro. (connected_add_ipv4) Set prefixlen in destination addresses (required by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead of testing for IFF_POINTOPOINT. Delete invalid warning message. Warn about cases where the ZEBRA_IFA_PEER is set but no destination address has been supplied (and turn off the flag). (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning. Set prefixlen in destination address so CONNECTED_PREFIX will work. * connected.h: (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. * interface.c: (connected_dump_vty) Use CONNECTED_PEER macro to decide whether the destination address is a peer or broadcast address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT). * if_ioctl.c: (if_getaddrs) Instead of setting a peer address only when the IFF_POINTOPOINT is set, we now accept a peer address whenever it is available and not the same as the local address. Otherwise (no peer address assigned), we check for a broadcast address (regardless of the IFF_BROADCAST flag). And must now pass a flags value of ZEBRA_IFA_PEER to connected_add_ipv4 when a peer address is assigned. The same new logic is used with the IPv6 code as well (and we pass the new flags argument to connected_add_ipv6). (if_get_addr) Do not bother to check IFF_POINTOPOINT: just issue the SIOCGIFDSTADDR ioctl and see if we get back a peer address not matching the local address (and set the ZEBRA_IFA_PEER in that case). If there's no peer address, try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set. * if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl without bothering to check the IFF_POINTOPOINT flag. And if no peer address was found, just try the SIOCGLIFBRDADDR ioctl without checking the IFF_BROADCAST flag. Call connected_add_ipv4 and connected_add_ipv6 with appropriate flags. * if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to connected_add_ipv6. * kernel_socket.c: (ifam_read) Must pass new flags argument to connected_add_ipv6. * rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2 to determine local and possible peer address (so there's no longer a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately. Pass new flags argument to connected_add_ipv6. (netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast to determine whether the connected destination address is a broadcast address. * bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete) Simplify logic by using new CONNECTED_PREFIX macro. * ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix, ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX macro. * ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX macro, both options collapse into the same code. * ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new CONNECTED_ID macro. (ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX macro. * ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro instead of testing the IFF_POINTOPOINT flag. * ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro instead of testing with if_is_pointopoint. And add commented-out code to implement alternative (in my opinion) more elegant behavior that has no special-case treatment for PtP addresses. (ospf_network_run) Use new CONNECTED_ID macro to simplify logic. * rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID macro to simplify logic. (rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does not give a useful result if prefixlen is 32 (we require a peer address in such cases). * ripd.c: (rip_update_interface) Fix same bug as above. --- zebra/rt_netlink.c | 54 +++++++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 216625e9..e2f1f9d9 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -577,8 +577,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) struct ifaddrmsg *ifa; struct rtattr *tb[IFA_MAX + 1]; struct interface *ifp; - void *addr = NULL; - void *broad = NULL; + void *addr; + void *broad; u_char flags = 0; char *label = NULL; @@ -637,41 +637,29 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) } } + /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ + if (tb[IFA_LOCAL] == NULL) + tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (tb[IFA_ADDRESS] == NULL) tb[IFA_ADDRESS] = tb[IFA_LOCAL]; - if (ifp->flags & IFF_POINTOPOINT) + /* local interface address */ + addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); + + /* is there a peer address? */ + /* N.B. I do not understand why the memcmp compares 4 bytes regardless + of address family, but this is exactly how it appears in + print_addrinfo. I wonder if it should be RTA_PAYLOAD(tb[IFA_ADDRESS]) + instead of 4... */ + if (tb[IFA_ADDRESS] && + memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), 4)) { - if (tb[IFA_LOCAL]) - { - addr = RTA_DATA (tb[IFA_LOCAL]); - if (tb[IFA_ADDRESS] && - memcmp(RTA_DATA(tb[IFA_ADDRESS]),RTA_DATA(tb[IFA_LOCAL]),4)) - /* if IFA_ADDRESS != IFA_LOCAL, then it's the peer address */ - broad = RTA_DATA (tb[IFA_ADDRESS]); - else - broad = NULL; - } - else - { - if (tb[IFA_ADDRESS]) - addr = RTA_DATA (tb[IFA_ADDRESS]); - else - addr = NULL; - } + broad = RTA_DATA(tb[IFA_ADDRESS]); + SET_FLAG (flags, ZEBRA_IFA_PEER); } else - { - if (tb[IFA_ADDRESS]) - addr = RTA_DATA (tb[IFA_ADDRESS]); - else - addr = NULL; - - if (tb[IFA_BROADCAST]) - broad = RTA_DATA(tb[IFA_BROADCAST]); - else - broad = NULL; - } + /* seeking a broadcast address */ + broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL); /* addr is primary key, SOL if we don't have one */ if (addr == NULL) @@ -707,7 +695,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) if (ifa->ifa_family == AF_INET6) { if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv6 (ifp, + connected_add_ipv6 (ifp, flags, (struct in6_addr *) addr, ifa->ifa_prefixlen, (struct in6_addr *) broad, label); else @@ -1849,7 +1837,7 @@ netlink_address (int cmd, int family, struct interface *ifp, if (family == AF_INET && cmd == RTM_NEWADDR) { - if (if_is_broadcast (ifp) && ifc->destination) + if (!CONNECTED_PEER(ifc) && ifc->destination) { p = ifc->destination; addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, -- cgit v1.2.3 From 7514fb7739f74311830e9ddd1381d0d228224f61 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Wed, 2 May 2007 16:05:35 +0000 Subject: [zebra] Routemap support on received routes, with 'set src' command (linux) 2007-05-01 David L Stevens * (general) These changes collectively add route-map and prefix-list support to zebra and fix a bug in "show route-map" (with no argument). * doc/main.texi: added route-map, prefix-list, ip protocol and set src documentation * lib/command.h: added PROTOCOL_NODE type * lib/log.c: (proto_name2num) new function, protocol name to number translation. * lib/routemap.c: (vty_show_route_map) fixed "show route-map" without route-map name * lib/routemap.h: added RMAP_ZEBRA type * lib/zebra.h: added proto_name2num() prototype * vtysh/extract.pl.in: added VTYSH_ZEBRA flag for route-map and plist * vtysh/Makefile.am: added zebra_routemap.c * vtysh/vtysh.h: added VTYSH_ZEBRA flag to VTYSH_RMAP * zebra/connected.c: (connected_up_ipv4) added src preference argument to rib_add_ipv4() * zebra/kernel_socket.c: (rtm_read) ditto * zebra/main.c: added prefix list initialization * zebra/Makefile.am: added zebra_routemap.c source file * zebra/rib.h: added generic address union "g_addr" and use in existing places that had an explicit union. Added "src" to struct nexthop. Added preferred src arg to nexthop_ipv4_add and rib_add_ipv4. * zebra/rt_netlink.c: (netlink_routing_table) set preferred source on netlink messages. (netlink_route_change) ditto (netlink_route_multipath) ditto. * zebra/rtread_getmsg.c: (handle_route_entry) added (NULL) src to rib_add_ipv4() call. * zebra/rtread_proc.c: (proc_route_read) ditto * zebra/zebra_rib.c: (nexthop_ipv4_add) add src argument. (nexthop_ipv4_ifindex_add) ditto (rib_add_ipv4) ditto (nexthop_active_check) Add route-map processing. * zebra/zebra_routemap.c: new file for zebra route-map commands. * zebra/zebra_vty.c: (ip_protocol_cmd) Apply route-map to protocol (vty_show_ip_route_detail) added "src" printing (vty_show_ip_route) ditto (show_ip_protocol_cmd) new command, list routemaps. (config_write_protocol) write out routemap protocl config. (zebra_vty_init) Install the new routemap protocol commands. * zebra/zserv.c: (zread_ipv4_add) added (NULL) src arg (zebra_init) init zebra route-maps. * zebra/zserv.h: add zebra_route_map_init --- zebra/rt_netlink.c | 84 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 13 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e2f1f9d9..3b602c45 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -725,6 +725,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) void *dest; void *gate; + void *src; rtm = NLMSG_DATA (h); @@ -764,6 +765,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) metric = 0; dest = NULL; gate = NULL; + src = NULL; if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -773,6 +775,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) else dest = anyaddr; + if (tb[RTA_PREFSRC]) + src = RTA_DATA (tb[RTA_PREFSRC]); + /* Multipath treatment is needed. */ if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); @@ -787,7 +792,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 4); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); } #ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) @@ -834,6 +839,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) int table; void *dest; void *gate; + void *src; rtm = NLMSG_DATA (h); @@ -890,6 +896,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) index = 0; dest = NULL; gate = NULL; + src = NULL; if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -902,6 +909,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); + if (tb[RTA_PREFSRC]) + src = RTA_DATA (tb[RTA_PREFSRC]); + if (rtm->rtm_family == AF_INET) { struct prefix_ipv4 p; @@ -920,7 +930,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); } @@ -1489,7 +1499,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { addattr_l (&req.n, sizeof req, RTA_GATEWAY, &nexthop->rgate.ipv4, bytelen); - + if (nexthop->src.ipv4.s_addr) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (recursive, " "1 hop): nexthop via %s if %u", @@ -1519,6 +1531,11 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->rifindex); + if ((nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IFINDEX) + && nexthop->src.ipv4.s_addr) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (recursive, " @@ -1547,6 +1564,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { addattr_l (&req.n, sizeof req, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); + if (nexthop->src.ipv4.s_addr) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (single hop): " @@ -1571,8 +1591,19 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, #endif /* HAVE_IPV6 */ if (nexthop->type == NEXTHOP_TYPE_IFINDEX || nexthop->type == NEXTHOP_TYPE_IFNAME - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + { + addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex); + + if (nexthop->src.ipv4.s_addr) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_route_multipath() (single hop): " + "nexthop via if %u", nexthop->ifindex); + } + else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) { addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex); @@ -1596,6 +1627,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, char buf[1024]; struct rtattr *rta = (void *) buf; struct rtnexthop *rtnh; + union g_addr *src = NULL; rta->rta_type = RTA_MULTIPATH; rta->rta_len = RTA_LENGTH (0); @@ -1640,6 +1672,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, &nexthop->rgate.ipv4, bytelen); rtnh->rtnh_len += sizeof (struct rtattr) + 4; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (recursive, " "multihop): nexthop via %s if %u", @@ -1662,10 +1697,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } #endif /* HAVE_IPV6 */ /* ifindex */ - if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX - || nexthop->rtype == NEXTHOP_TYPE_IFNAME - || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX + if (nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IFNAME) + { + rtnh->rtnh_ifindex = nexthop->rifindex; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_route_multipath() (recursive, " + "multihop): nexthop via if %u", + nexthop->rifindex); + } + else if (nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME) { rtnh->rtnh_ifindex = nexthop->rifindex; @@ -1701,6 +1746,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, &nexthop->gate.ipv4, bytelen); rtnh->rtnh_len += sizeof (struct rtattr) + 4; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (multihop): " "nexthop via %s if %u", @@ -1723,10 +1771,18 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } #endif /* HAVE_IPV6 */ /* ifindex */ - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IFNAME - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IFNAME) + { + rtnh->rtnh_ifindex = nexthop->ifindex; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_route_multipath() (multihop): " + "nexthop via if %u", nexthop->ifindex); + } + else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { rtnh->rtnh_ifindex = nexthop->ifindex; @@ -1746,6 +1802,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); } } + if (src) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen); if (rta->rta_len > RTA_LENGTH (0)) addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA (rta), -- cgit v1.2.3 From 068fd77cff0ce09b6390641abd84fc09a89c49db Mon Sep 17 00:00:00 2001 From: vize Date: Fri, 10 Aug 2007 06:25:20 +0000 Subject: Use the proper field length for the peer's address (netlink_interface_addr) --- zebra/rt_netlink.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 3b602c45..5b592f94 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -647,12 +647,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); /* is there a peer address? */ - /* N.B. I do not understand why the memcmp compares 4 bytes regardless - of address family, but this is exactly how it appears in - print_addrinfo. I wonder if it should be RTA_PAYLOAD(tb[IFA_ADDRESS]) - instead of 4... */ if (tb[IFA_ADDRESS] && - memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), 4)) + memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS]))) { broad = RTA_DATA(tb[IFA_ADDRESS]); SET_FLAG (flags, ZEBRA_IFA_PEER); -- cgit v1.2.3 From 768a27ea7ba25257c79689af83ab37945dc1cc3c Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 29 May 2008 18:23:08 +0000 Subject: [zebra/linux] Use BPF to filter out responses, to try avoid netlink overruns 2008-05-29 Stephen Hemminger * rt_netlink.c: (netlink_install_filter) BPF filter to catch and drop responses to zebra's own route messages. (kernel_init) add BPF filter on the netlink socket. --- zebra/rt_netlink.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 5b592f94..0bf2d9eb 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1938,6 +1938,56 @@ kernel_read (struct thread *thread) return 0; } +/* Filter out messages from self that occur on listener socket */ +static void netlink_install_filter (int sock) +{ + /* + * Filter is equivalent to netlink_route_change + * + * if (h->nlmsg_type == RTM_DELROUTE || h->nlmsg_type == RTM_NEWROUTE) { + * if (rtm->rtm_type != RTM_UNICAST) + * return 0; + * if (rtm->rtm_flags & RTM_F_CLONED) + * return 0; + * if (rtm->rtm_protocol == RTPROT_REDIRECT) + * return 0; + * if (rtm->rtm_protocol == RTPROT_KERNEL) + * return 0; + * if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) + * return 0; + * } + * return 0xffff; + */ + struct sock_filter filter[] = { + /* 0*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), + /* 1*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 1, 0), + /* 2*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 11), + /* 3*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, + sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_type)), + /* 4*/ BPF_JUMP(BPF_JMP|BPF_B, RTN_UNICAST, 0, 8), + /* 5*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, + sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_flags)), + /* 6*/ BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, RTM_F_CLONED, 6, 0), + /* 7*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, + sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_protocol)), + /* 8*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_REDIRECT, 4, 0), + /* 9*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_KERNEL, 0, 1), + /*10*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_ZEBRA, 0, 3), + /*11*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), + /*12*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 1), + /*13*/ BPF_STMT(BPF_RET|BPF_K, 0), /* drop */ + /*14*/ BPF_STMT(BPF_RET|BPF_K, 0xffff), /* keep */ + }; + + struct sock_fprog prog = { + .len = sizeof(filter) / sizeof(filter[0]), + .filter = filter, + }; + + if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0) + zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno)); +} + /* Exported interface function. This function simply calls netlink_socket (). */ void @@ -1954,5 +2004,8 @@ kernel_init (void) /* Register kernel socket. */ if (netlink.sock > 0) - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); + { + netlink_install_filter (netlink.sock); + thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); + } } -- cgit v1.2.3 From 40da22166ff29753a65b7947ed5fa7261fee1d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 13 Aug 2008 17:37:14 +0100 Subject: [zebra:netlink] Set proto/scope on all route update messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2008-08-13 Timo Teräs * zebra/rt_netlink.c: (netlink_route{,_multipath) Set protocol and scope appropriately for both NEW and DELROUTE messages, to avoid wiping out non-zebra routes on delete. Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0bf2d9eb..4234a445 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1348,6 +1348,8 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, req.r.rtm_family = family; req.r.rtm_table = table; req.r.rtm_dst_len = length; + req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_scope = RT_SCOPE_UNIVERSE; if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE) || (zebra_flags & ZEBRA_FLAG_REJECT)) @@ -1357,9 +1359,6 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, if (cmd == RTM_NEWROUTE) { - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - if (discard) { if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) @@ -1424,6 +1423,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, req.r.rtm_family = family; req.r.rtm_table = rib->table; req.r.rtm_dst_len = p->prefixlen; + req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_scope = RT_SCOPE_UNIVERSE; if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT)) discard = 1; @@ -1432,9 +1433,6 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, if (cmd == RTM_NEWROUTE) { - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - if (discard) { if (rib->flags & ZEBRA_FLAG_BLACKHOLE) -- cgit v1.2.3 From 6072b24eb776e6486f076b1762d3650e803954c2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 14 Aug 2008 16:52:26 +0100 Subject: [zebra] mark some rt_netlink functions static 2008-08-14 Stephen Hemminger * zebra/rt_netlink.c: local functions should be static. Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4234a445..0a6b8dde 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -52,7 +52,7 @@ struct nlsock } netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */ netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */ -struct message nlmsg_str[] = { +static struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_GETROUTE, "RTM_GETROUTE"}, @@ -65,7 +65,7 @@ struct message nlmsg_str[] = { {0, NULL} }; -const char *nexthop_types_desc[] = +static const char *nexthop_types_desc[] = { "none", "Directly connected", @@ -79,7 +79,6 @@ const char *nexthop_types_desc[] = "Null0 nexthop", }; - extern struct zebra_t zebrad; extern struct zebra_privs_t zserv_privs; @@ -222,7 +221,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return ret; } -int +static int set_netlink_blocking (struct nlsock *nl, int *flags) { @@ -243,7 +242,7 @@ set_netlink_blocking (struct nlsock *nl, int *flags) return 0; } -int +static int set_netlink_nonblocking (struct nlsock *nl, int *flags) { /* Restore socket flags for nonblocking I/O */ @@ -493,7 +492,7 @@ netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ -int +static int netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -570,7 +569,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) } /* Lookup interface IPv4/IPv6 address. */ -int +static int netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -705,7 +704,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) } /* Looking up routing table by netlink interface. */ -int +static int netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -822,7 +821,7 @@ struct message rtproto_str[] = { }; /* Routing information change from the kernel. */ -int +static int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -963,7 +962,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) return 0; } -int +static int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -1064,7 +1063,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) return 0; } -int +static int netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) { switch (h->nlmsg_type) @@ -1189,7 +1188,7 @@ netlink_route_read (void) /* Utility function comes from iproute2. Authors: Alexey Kuznetsov, */ -int +static int addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen) { int len; @@ -1209,7 +1208,7 @@ addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen) return 0; } -int +static int rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen) { int len; @@ -1231,7 +1230,7 @@ rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen) /* Utility function comes from iproute2. Authors: Alexey Kuznetsov, */ -int +static int addattr32 (struct nlmsghdr *n, int maxlen, int type, int data) { int len; @@ -1259,7 +1258,7 @@ netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h) } /* sendmsg() to netlink socket then recvmsg(). */ -int +static int netlink_talk (struct nlmsghdr *n, struct nlsock *nl) { int status; @@ -1322,7 +1321,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) } /* Routing table change via netlink interface. */ -int +static int netlink_route (int cmd, int family, void *dest, int length, void *gate, int index, int zebra_flags, int table) { @@ -1396,7 +1395,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, } /* Routing table change via netlink interface. */ -int +static int netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, int family) { @@ -1858,7 +1857,7 @@ kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, #endif /* HAVE_IPV6 */ /* Interface address modification. */ -int +static int netlink_address (int cmd, int family, struct interface *ifp, struct connected *ifc) { @@ -1923,7 +1922,7 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) extern struct thread_master *master; /* Kernel route reflection. */ -int +static int kernel_read (struct thread *thread) { int ret; -- cgit v1.2.3 From 1423c809cc4ddc2e013ba6264c49a11e5719c6f2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 14 Aug 2008 17:59:25 +0100 Subject: [lib] mes_lookup string lookup table argument should be marked const 2008-08-14 Stephen Hemminger * lib/log.{c,h}: struct message argument should point to const * */*.c: adjust to suit, Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0a6b8dde..395f1ca6 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -52,7 +52,7 @@ struct nlsock } netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */ netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */ -static struct message nlmsg_str[] = { +static const struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_GETROUTE, "RTM_GETROUTE"}, @@ -805,7 +805,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) return 0; } -struct message rtproto_str[] = { +static const struct message rtproto_str[] = { {RTPROT_REDIRECT, "redirect"}, {RTPROT_KERNEL, "kernel"}, {RTPROT_BOOT, "boot"}, -- cgit v1.2.3 From 3d265b4d9d748bf4c92aefebc2ca0c04fd607945 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 16 Aug 2008 17:30:39 +0100 Subject: [zebra:linux] Filter out unwanted netlink messages by PID 2008-08-16 Stephen Hemminger * zebra/rt_netlink.c: Update the netlink socket BPF to cancel out unwanted ACKs on the listen socket by matching on the PID. Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 73 ++++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 395f1ca6..592dfe2e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -285,7 +285,7 @@ netlink_request (int family, int type, struct nlsock *nl) req.nlh.nlmsg_len = sizeof req; req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_pid = nl->snl.nl_pid; req.nlh.nlmsg_seq = ++nl->seq; req.g.rtgen_family = family; @@ -367,13 +367,6 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return -1; } - /* JF: Ignore messages that aren't from the kernel */ - if ( snl.nl_pid != 0 ) - { - zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl.nl_pid ); - continue; - } - for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); h = NLMSG_NEXT (h, status)) { @@ -1066,6 +1059,13 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) static int netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) { + /* JF: Ignore messages that aren't from the kernel */ + if ( snl->nl_pid != 0 ) + { + zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid ); + return 0; + } + switch (h->nlmsg_type) { case RTM_NEWROUTE: @@ -1935,45 +1935,26 @@ kernel_read (struct thread *thread) return 0; } -/* Filter out messages from self that occur on listener socket */ -static void netlink_install_filter (int sock) +/* Filter out messages from self that occur on listener socket, + caused by our actions on the command socket + */ +static void netlink_install_filter (int sock, __u32 pid) { - /* - * Filter is equivalent to netlink_route_change - * - * if (h->nlmsg_type == RTM_DELROUTE || h->nlmsg_type == RTM_NEWROUTE) { - * if (rtm->rtm_type != RTM_UNICAST) - * return 0; - * if (rtm->rtm_flags & RTM_F_CLONED) - * return 0; - * if (rtm->rtm_protocol == RTPROT_REDIRECT) - * return 0; - * if (rtm->rtm_protocol == RTPROT_KERNEL) - * return 0; - * if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) - * return 0; - * } - * return 0xffff; - */ struct sock_filter filter[] = { - /* 0*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 1, 0), - /* 2*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 11), - /* 3*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_type)), - /* 4*/ BPF_JUMP(BPF_JMP|BPF_B, RTN_UNICAST, 0, 8), - /* 5*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_flags)), - /* 6*/ BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, RTM_F_CLONED, 6, 0), - /* 7*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_protocol)), - /* 8*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_REDIRECT, 4, 0), - /* 9*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_KERNEL, 0, 1), - /*10*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_ZEBRA, 0, 3), - /*11*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /*12*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 1), - /*13*/ BPF_STMT(BPF_RET|BPF_K, 0), /* drop */ - /*14*/ BPF_STMT(BPF_RET|BPF_K, 0xffff), /* keep */ + /* 0: ldh [4] */ + BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), + /* 1: jeq 0x18 jt 3 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0), + /* 2: jeq 0x19 jt 3 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3), + /* 3: ldw [12] */ + BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), + /* 4: jeq XX jt 5 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), + /* 5: ret 0 (skip) */ + BPF_STMT(BPF_RET|BPF_K, 0), + /* 6: ret 0xffff (keep) */ + BPF_STMT(BPF_RET|BPF_K, 0xffff), }; struct sock_fprog prog = { @@ -2002,7 +1983,7 @@ kernel_init (void) /* Register kernel socket. */ if (netlink.sock > 0) { - netlink_install_filter (netlink.sock); + netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } } -- cgit v1.2.3 From 4cde931e2d5a83708cf55e63eae7b629e8e4296a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 16 Aug 2008 17:51:27 +0100 Subject: [zebra:linux] clean up blocking setting of netlink sockets 2008-08-16 Stephen Hemminger * zebra/rt_netlink.c: This change removes the overhead of twiddling the socket twice on every route change. The netlink support has two sockets, one is used for request/response and should always block. The other is used for asynchronous notification and should always be non-blocking. Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 97 ++++-------------------------------------------------- 1 file changed, 6 insertions(+), 91 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 592dfe2e..fe55d43e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -130,14 +130,6 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return -1; } - ret = fcntl (sock, F_SETFL, O_NONBLOCK); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } /* Set receive buffer size if it's set from command line */ if (nl_rcvbufsize) @@ -221,41 +213,6 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return ret; } -static int -set_netlink_blocking (struct nlsock *nl, int *flags) -{ - - /* Change socket flags for blocking I/O. */ - if ((*flags = fcntl (nl->sock, F_GETFL, 0)) < 0) - { - zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s", - __FUNCTION__, __LINE__, safe_strerror (errno)); - return -1; - } - *flags &= ~O_NONBLOCK; - if (fcntl (nl->sock, F_SETFL, *flags) < 0) - { - zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s", - __FUNCTION__, __LINE__, safe_strerror (errno)); - return -1; - } - return 0; -} - -static int -set_netlink_nonblocking (struct nlsock *nl, int *flags) -{ - /* Restore socket flags for nonblocking I/O */ - *flags |= O_NONBLOCK; - if (fcntl (nl->sock, F_SETFL, *flags) < 0) - { - zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s", - __FUNCTION__, __LINE__, safe_strerror (errno)); - return -1; - } - return 0; -} - /* Get type specified information from netlink. */ static int netlink_request (int family, int type, struct nlsock *nl) @@ -1098,18 +1055,6 @@ int interface_lookup_netlink (void) { int ret; - int flags; - int snb_ret; - - /* - * Change netlink socket flags to blocking to ensure we get - * a reply via nelink_parse_info - */ - snb_ret = set_netlink_blocking (&netlink_cmd, &flags); - if (snb_ret < 0) - zlog (NULL, LOG_WARNING, - "%s:%i Warning: Could not set netlink socket to blocking.", - __FUNCTION__, __LINE__); /* Get interface information. */ ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd); @@ -1137,9 +1082,6 @@ interface_lookup_netlink (void) return ret; #endif /* HAVE_IPV6 */ - /* restore socket flags */ - if (snb_ret == 0) - set_netlink_nonblocking (&netlink_cmd, &flags); return 0; } @@ -1149,18 +1091,6 @@ int netlink_route_read (void) { int ret; - int flags; - int snb_ret; - - /* - * Change netlink socket flags to blocking to ensure we get - * a reply via nelink_parse_info - */ - snb_ret = set_netlink_blocking (&netlink_cmd, &flags); - if (snb_ret < 0) - zlog (NULL, LOG_WARNING, - "%s:%i Warning: Could not set netlink socket to blocking.", - __FUNCTION__, __LINE__); /* Get IPv4 routing table. */ ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd); @@ -1180,9 +1110,6 @@ netlink_route_read (void) return ret; #endif /* HAVE_IPV6 */ - /* restore flags */ - if (snb_ret == 0) - set_netlink_nonblocking (&netlink_cmd, &flags); return 0; } @@ -1265,8 +1192,6 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) struct sockaddr_nl snl; struct iovec iov = { (void *) n, n->nlmsg_len }; struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 }; - int flags = 0; - int snb_ret; int save_errno; memset (&snl, 0, sizeof snl); @@ -1297,27 +1222,12 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) return -1; } - /* - * Change socket flags for blocking I/O. - * This ensures we wait for a reply in netlink_parse_info(). - */ - snb_ret = set_netlink_blocking (nl, &flags); - if (snb_ret < 0) - zlog (NULL, LOG_WARNING, - "%s:%i Warning: Could not set netlink socket to blocking.", - __FUNCTION__, __LINE__); /* * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - status = netlink_parse_info (netlink_talk_filter, nl); - - /* Restore socket flags for nonblocking I/O */ - if (snb_ret == 0) - set_netlink_nonblocking (nl, &flags); - - return status; + return netlink_parse_info (netlink_talk_filter, nl); } /* Routing table change via netlink interface. */ @@ -1983,6 +1893,11 @@ kernel_init (void) /* Register kernel socket. */ if (netlink.sock > 0) { + /* Only want non-blocking on the netlink event socket */ + if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, + safe_strerror (errno)); + netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } -- cgit v1.2.3 From 30afea3b584515ba19b38fcde6f562a550c1fcab Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 16 Aug 2008 18:25:47 +0100 Subject: [zebra:linux] netlink buffer size tweaking only needed on receive socket 2008-08-16 Stephen Hemminger * rt_netlink.c: (netlink_recvbuf) consolidate recvbuf setting (netlink_socket) no need to set receive buffer on netlink sockets generally (kernel_init) set recvbuffer on the listen socket Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 86 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index fe55d43e..a0dad997 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -112,6 +112,45 @@ set_ifindex(struct interface *ifp, unsigned int ifi_index) ifp->ifindex = ifi_index; } +static int +netlink_recvbuf (struct nlsock *nl, uint32_t newsize) +{ + u_int32_t oldsize; + socklen_t newlen = sizeof(newsize); + socklen_t oldlen = sizeof(oldsize); + int ret; + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); + if (ret < 0) + { + zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, + safe_strerror (errno)); + return -1; + } + + ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize, + sizeof(nl_rcvbufsize)); + if (ret < 0) + { + zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name, + safe_strerror (errno)); + return -1; + } + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); + if (ret < 0) + { + zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, + safe_strerror (errno)); + return -1; + } + + zlog (NULL, LOG_INFO, + "Setting netlink socket receive buffer size: %u -> %u", + oldsize, newsize); + return 0; +} + /* Make socket for Linux netlink interface. */ static int netlink_socket (struct nlsock *nl, unsigned long groups) @@ -130,49 +169,6 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return -1; } - - /* Set receive buffer size if it's set from command line */ - if (nl_rcvbufsize) - { - u_int32_t oldsize, oldlen; - u_int32_t newsize, newlen; - - oldlen = sizeof(oldsize); - newlen = sizeof(newsize); - - ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize, - sizeof(nl_rcvbufsize)); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - zlog (NULL, LOG_INFO, - "Setting netlink socket receive buffer size: %u -> %u", - oldsize, newsize); - } - memset (&snl, 0, sizeof snl); snl.nl_family = AF_NETLINK; snl.nl_groups = groups; @@ -1898,6 +1894,10 @@ kernel_init (void) zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, safe_strerror (errno)); + /* Set receive buffer size if it's set from command line */ + if (nl_rcvbufsize) + netlink_recvbuf (&netlink, nl_rcvbufsize); + netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } -- cgit v1.2.3 From 898987e976e8f7a50a4549475ab4970a85895f31 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 17 Aug 2008 16:56:15 +0100 Subject: [zebra:linux] netlink: quiet harmless errors 2008-06-17 Stephen Hemminger * rt_netlink.c: (netlink_parse_info) There can be harmless races such as adding an existing route, or deleting an already deleted route. Don't bother logging these unless debugging is turned on. Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a0dad997..904367e0 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -331,6 +331,8 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), if (h->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h); + int errnum = err->error; + int msg_type = err->msg.nlmsg_type; /* If the error field is zero, then this is an ACK */ if (err->error == 0) @@ -359,27 +361,24 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return -1; } - /* Deal with Error Noise - MAG */ - { - int loglvl = LOG_ERR; - int errnum = err->error; - int msg_type = err->msg.nlmsg_type; - - if (nl == &netlink_cmd - && (-errnum == ENODEV || -errnum == ESRCH) - && (msg_type == RTM_NEWROUTE || msg_type == RTM_DELROUTE)) - loglvl = LOG_DEBUG; - - zlog (NULL, loglvl, "%s error: %s, type=%s(%u), " - "seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - lookup (nlmsg_str, msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - } - /* - ret = -1; - continue; - */ + /* Deal with errors that occur because of races in link handling */ + if (nl == &netlink_cmd + && ((msg_type == RTM_DELROUTE && + (-errnum == ENODEV || -errnum == ESRCH)) + || (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u", + nl->name, safe_strerror (-errnum), + lookup (nlmsg_str, msg_type), + msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); + return 0; + } + + zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u", + nl->name, safe_strerror (-errnum), + lookup (nlmsg_str, msg_type), + msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); return -1; } -- cgit v1.2.3 From 4c699477d24e7104893130d072963df5cea17214 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 17 Aug 2008 17:01:44 +0100 Subject: [zebra:linux] netlink: no need to change privs for receive 2008-06-17 Stephen Hemminger * rt_netlink.c: (netlink_parse_info) Linux doesn't check privledges on receive, so avoid the overhead of lowering and raising the priviledges on each received message Signed-off-by: Paul Jakma --- zebra/rt_netlink.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 904367e0..05254498 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -285,25 +285,16 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), struct sockaddr_nl snl; struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 }; struct nlmsghdr *h; - int save_errno; - - if (zserv_privs.change (ZPRIVS_RAISE)) - zlog (NULL, LOG_ERR, "Can't raise privileges"); status = recvmsg (nl->sock, &msg, 0); - save_errno = errno; - - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog (NULL, LOG_ERR, "Can't lower privileges"); - if (status < 0) { - if (save_errno == EINTR) + if (errno == EINTR) continue; - if (save_errno == EWOULDBLOCK || save_errno == EAGAIN) + if (errno == EWOULDBLOCK || errno == EAGAIN) break; zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s", - nl->name, safe_strerror(save_errno)); + nl->name, safe_strerror(errno)); continue; } -- cgit v1.2.3