summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2021-06-19 08:55:10 +0200
committerFelix Fietkau <nbd@nbd.name>2021-06-19 09:16:51 +0200
commit013a1171e9b0df4f458fb87bbfb3bf8c9602ce6b (patch)
tree5fd6de9bf2af2dbdd650d8e9f5a5883c85914da9
parent7f30b02013f2fcd69bef52d12597b232aaefcfed (diff)
downloadnetifd-013a1171e9b0df4f458fb87bbfb3bf8c9602ce6b.tar.gz
device: do not treat devices with non-digit characters after . as vlan devices
Fixes corner cases related to AP WDS station interfaces Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--device.c4
-rw-r--r--device.h10
-rw-r--r--vlan.c26
3 files changed, 24 insertions, 16 deletions
diff --git a/device.c b/device.c
index d8617fc..c6b0b5f 100644
--- 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] == '@')
diff --git a/device.h b/device.h
index 7d6c48b..1da6e3f 100644
--- 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 459c907..401cc94 100644
--- 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;