device: do not treat devices with non-digit characters after . as vlan devices
authorFelix Fietkau <nbd@nbd.name>
Sat, 19 Jun 2021 06:55:10 +0000 (08:55 +0200)
committerFelix Fietkau <nbd@nbd.name>
Sat, 19 Jun 2021 07:16:51 +0000 (09:16 +0200)
Fixes corner cases related to AP WDS station interfaces

Signed-off-by: Felix Fietkau <nbd@nbd.name>
device.c
device.h
vlan.c

index d8617fcab67e5451f1ed46247c83f0b70bb5bb12..c6b0b5f8de1b4a20279c44231ffecc45d942b419 100644 (file)
--- a/device.c
+++ b/device.c
@@ -650,13 +650,13 @@ device_find(const char *name)
 }
 
 struct device *
-device_get(const char *name, int create)
+__device_get(const char *name, int create, bool check_vlan)
 {
        struct device *dev;
 
        dev = avl_find_element(&devices, name, dev, avl);
 
-       if (!dev && strchr(name, '.'))
+       if (!dev && check_vlan && strchr(name, '.'))
                return get_vlan_device_chain(name, create);
 
        if (name[0] == '@')
index 7d6c48ba9469e260f14f34b8db79f22e240f541d..1da6e3ff866038a5e15d9623ce445d61dd0265cb 100644 (file)
--- a/device.h
+++ b/device.h
@@ -309,7 +309,13 @@ int device_init_virtual(struct device *dev, struct device_type *type, const char
 int device_init(struct device *dev, struct device_type *type, const char *ifname);
 void device_cleanup(struct device *dev);
 struct device *device_find(const char *name);
-struct device *device_get(const char *name, int create);
+
+struct device *__device_get(const char *name, int create, bool check_vlan);
+static inline struct device *device_get(const char *name, int create)
+{
+       return __device_get(name, create, true);
+}
+
 void device_add_user(struct device_user *dep, struct device *dev);
 void device_remove_user(struct device_user *dep);
 void device_broadcast_event(struct device *dev, enum device_event ev);
@@ -326,7 +332,7 @@ void device_dump_status(struct blob_buf *b, struct device *dev);
 
 void device_free_unused(struct device *dev);
 
-struct device *get_vlan_device_chain(const char *ifname, bool create);
+struct device *get_vlan_device_chain(const char *ifname, int create);
 void alias_notify_device(const char *name, struct device *dev);
 struct device *device_alias_get(const char *name);
 
diff --git a/vlan.c b/vlan.c
index 459c9077a085cf15a73399a3d543674fcc6f7935..401cc94b7808d629211e3429eac2dc83f8e4e302 100644 (file)
--- a/vlan.c
+++ b/vlan.c
@@ -14,6 +14,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <ctype.h>
 
 #include "netifd.h"
 #include "system.h"
@@ -238,18 +239,23 @@ error:
 
 static char *split_vlan(char *s)
 {
+retry:
        s = strchr(s, '.');
        if (!s)
-               goto out;
+               return NULL;
+
+       if (!isdigit(s[1])) {
+               s++;
+               goto retry;
+       }
 
        *s = 0;
        s++;
 
-out:
        return s;
 }
 
-struct device *get_vlan_device_chain(const char *ifname, bool create)
+struct device *get_vlan_device_chain(const char *ifname, int create)
 {
        struct device *dev = NULL;
        char *buf, *s, *next;
@@ -259,23 +265,19 @@ struct device *get_vlan_device_chain(const char *ifname, bool create)
                return NULL;
 
        s = split_vlan(buf);
-       dev = device_get(buf, create);
+       dev = __device_get(buf, create, false);
        if (!dev)
-               goto error;
+               goto out;
 
-       do {
+       while (s) {
                next = split_vlan(s);
                dev = get_vlan_device(dev, s, create);
                if (!dev)
-                       goto error;
+                       break;
 
                s = next;
-               if (!s)
-                       goto out;
-       } while (1);
+       }
 
-error:
-       dev = NULL;
 out:
        free(buf);
        return dev;