[PATCH][odhcp6c] ra: exit on RTM_DELLINK event
Alin Nastac
alin.nastac at gmail.com
Wed Oct 14 06:46:09 EDT 2020
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.nastac at 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
More information about the openwrt-devel
mailing list