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

Reply via email to