system-linux: restore reading flags from netlink messages master
authorFelix Fietkau <nbd@nbd.name>
Wed, 27 Nov 2024 20:02:04 +0000 (21:02 +0100)
committerFelix Fietkau <nbd@nbd.name>
Wed, 27 Nov 2024 20:02:06 +0000 (21:02 +0100)
The SIOCGIFFLAGS ioctl truncates returned flags to u16, and the IFF_LOWER_UP
flag exceeds that size. Because of that, the carrier status needs to be pulled
from the netlink message.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
system-linux.c

index af2052314c8536d0aff41840171730a990325511..3fff641072377a6210ea8eba840946acdf34983b 100644 (file)
@@ -705,25 +705,14 @@ system_device_ifreq(struct ifreq *ifr, const char *ifname, int cmd)
        return ioctl(sock_ioctl, cmd, ifr);
 }
 
-static int system_if_get_flags(const char *ifname)
-{
-       struct ifreq ifr;
-
-       if (system_device_ifreq(&ifr, ifname, SIOCGIFFLAGS))
-               return 0;
-
-       return ifr.ifr_flags;
-}
-
 #ifndef IFF_LOWER_UP
 #define IFF_LOWER_UP   0x10000
 #endif
 
 static void
-system_device_update_state(struct device *dev)
+system_device_update_state(struct device *dev, unsigned int flags)
 {
        unsigned int ifindex = system_if_resolve(dev);
-       int flags = system_if_get_flags(dev->ifname);
 
        if (dev->type == &simple_device_type) {
                if (dev->external)
@@ -738,6 +727,7 @@ system_device_update_state(struct device *dev)
 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
 {
        struct nlmsghdr *nh = nlmsg_hdr(msg);
+       struct ifinfomsg *ifi = NLMSG_DATA(nh);
        struct nlattr *nla[__IFLA_MAX];
        struct device *dev;
 
@@ -752,7 +742,7 @@ static int cb_rtnl_event(struct nl_msg *msg, void *arg)
        if (!dev)
                return 0;
 
-       system_device_update_state(dev);
+       system_device_update_state(dev, ifi->ifi_flags);
        return 0;
 }
 
@@ -2388,12 +2378,13 @@ struct if_check_data {
 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
 {
        struct nlmsghdr *nh = nlmsg_hdr(msg);
+       struct ifinfomsg *ifi = NLMSG_DATA(nh);
        struct if_check_data *chk = (struct if_check_data *)arg;
 
        if (nh->nlmsg_type != RTM_NEWLINK)
                return NL_SKIP;
 
-       system_device_update_state(chk->dev);
+       system_device_update_state(chk->dev, ifi->ifi_flags);
        return NL_OK;
 }