Also handle the netlink message correctly (the current code assumes that the entire buffer returned by recv contains just one netlink message).
This fixes a timing issue that occurs when wan interface proto is pppoe, wan6 proto is dhcpv6 and PPP session is closed by the peer. Because odhpc6c doesn't react to pppoe-wan device deletion, sometimes netifd device created by the old pppd instance doesn't get released before new pppd instance execute the ppp-up script (pppoe-wan device is reffered by wan6 device alias), so device_claim() doesn't trigger device_set_ifindex(). That will impede default route creation for wan interface (pppoe-wan device will store the incorrect ifindex). Signed-off-by: Alin Nastac <alin.nas...@gmail.com> --- src/dhcpv6.c | 6 +++++- src/ra.c | 54 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index bd8a2dc..4cd1abc 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -560,7 +560,11 @@ int dhcpv6_request(enum dhcpv6_msg type) struct timespec ts = {0, 0}; ts.tv_nsec = (dhcpv6_rand_delay((10000 * DHCPV6_REQ_DELAY) / 2) + (1000 * DHCPV6_REQ_DELAY) / 2) * 1000000; - while (nanosleep(&ts, &ts) < 0 && errno == EINTR); + while (nanosleep(&ts, &ts) < 0 && errno == EINTR) { + // Check for pending signal + if (odhcp6c_signal_process()) + return -1; + } } if (type == DHCPV6_MSG_UNKNOWN) diff --git a/src/ra.c b/src/ra.c index 337c0bd..9af48a2 100644 --- a/src/ra.c +++ b/src/ra.c @@ -16,6 +16,7 @@ #include <errno.h> #include <fcntl.h> #include <stdio.h> +#include <stdlib.h> #include <signal.h> #include <string.h> #include <stddef.h> @@ -208,37 +209,42 @@ static int16_t pref_to_priority(uint8_t flags) bool ra_link_up(void) { static bool firstcall = true; - struct { - struct nlmsghdr hdr; - struct ifinfomsg msg; - uint8_t pad[4000]; - } resp; + char buf[4096]; bool ret = false; ssize_t read; - do { - read = recv(rtnl, &resp, sizeof(resp), MSG_DONTWAIT); + while ((read = recv(rtnl, &buf, sizeof(buf), MSG_DONTWAIT)) > 0) { + for (struct nlmsghdr *nlh = (struct nlmsghdr *)buf; + NLMSG_OK (nlh, read) && nlh->nlmsg_type != NLMSG_DONE; + nlh = NLMSG_NEXT(nlh, read)) { + if (nlh->nlmsg_type != RTM_NEWLINK && nlh->nlmsg_type != RTM_DELLINK) + continue; - if (read < 0 || !NLMSG_OK(&resp.hdr, (size_t)read) || - resp.hdr.nlmsg_type != RTM_NEWLINK || - resp.msg.ifi_index != if_index) - continue; + struct ifinfomsg *ifi = NLMSG_DATA(nlh); + if (ifi->ifi_index != if_index) + continue; - ssize_t alen = NLMSG_PAYLOAD(&resp.hdr, sizeof(resp.msg)); - for (struct rtattr *rta = (struct rtattr*)(resp.pad); - RTA_OK(rta, alen); rta = RTA_NEXT(rta, alen)) { - if (rta->rta_type == IFLA_ADDRESS && - RTA_PAYLOAD(rta) >= sizeof(rs.lladdr.data)) - memcpy(rs.lladdr.data, RTA_DATA(rta), sizeof(rs.lladdr.data)); - } + if (nlh->nlmsg_type == RTM_DELLINK) { + syslog(LOG_ERR, "Interface %s has been deleted, exiting", if_name); + exit(1); + } - bool hascarrier = resp.msg.ifi_flags & IFF_LOWER_UP; - if (!firstcall && nocarrier != !hascarrier) - ret = true; + ssize_t alen = IFLA_PAYLOAD(nlh); + for (struct rtattr *rta = IFLA_RTA(nlh); + RTA_OK(rta, alen); rta = RTA_NEXT(rta, alen)) { + if (rta->rta_type == IFLA_ADDRESS && + RTA_PAYLOAD(rta) >= sizeof(rs.lladdr.data)) + memcpy(rs.lladdr.data, RTA_DATA(rta), sizeof(rs.lladdr.data)); + } + + bool hascarrier = ifi->ifi_flags & IFF_LOWER_UP; + if (!firstcall && nocarrier != !hascarrier) + ret = true; - nocarrier = !hascarrier; - firstcall = false; - } while (read > 0); + nocarrier = !hascarrier; + firstcall = false; + } + } if (ret) { syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name); -- 2.7.4 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel