[PATCH 3/3] rtnl: Use FallbackDeviceTypes configuration option

Jussi Laakkonen <[email protected]> Tue, 12 May 2026 18:36:24 +0300
Newsgroups dev.linux.lists.connman
Message-ID <[email protected]>
From: Simo Piiroinen <[email protected]>

If /sys/class/net/<interface>/uevent file exists but does not specify
DEVTYPE, check whether fallback device type has been defined in main
configuration.

Co-authored-by: Jussi Laakkonen <[email protected]>
---
 src/rtnl.c | 123 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 72 insertions(+), 51 deletions(-)

diff --git a/src/rtnl.c b/src/rtnl.c
index d49ea4d4..0e556a3a 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -116,90 +116,111 @@ static bool wext_interface(char *ifname)
 	return true;
 }
 
-static void read_uevent(struct interface_data *interface)
+static bool read_devtype(const char *filename, char **devtype)
 {
-	char *filename, *name, line[128];
-	bool found_devtype;
-	FILE *f;
+	FILE *file;
+	char buf[128];
 
-	name = connman_inet_ifname(interface->index);
+	*devtype = NULL;
 
-	if (ether_blacklisted(name)) {
-		interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
-		interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
-		goto out;
-	} else {
-		interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
-		interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
+	if (!(file = fopen(filename, "re")))
+		return false;
+
+	while (fgets(buf, sizeof(buf), file)) {
+		static const char key[] = "DEVTYPE=";
+		const char *val;
+
+		if (strncmp(buf, key, sizeof(key) - 1))
+			continue;
+
+		val = buf + sizeof(key) - 1;
+		*devtype = g_strndup(val, strcspn(val, "\r\n"));
+
+		break;
 	}
 
-	filename = g_strdup_printf("/sys/class/net/%s/uevent", name);
+	fclose(file);
 
-	f = fopen(filename, "re");
+	return true;
+}
 
-	g_free(filename);
+static void read_uevent(struct interface_data *interface)
+{
+	char *name;
+	char *filename = NULL;
+	char *devtype = NULL;
+
+	interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
+	interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
 
-	if (!f) {
-		interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
-		interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
+	name = connman_inet_ifname(interface->index);
+
+	if (ether_blacklisted(name))
 		goto out;
-	}
 
-	found_devtype = false;
-	while (fgets(line, sizeof(line), f)) {
-		char *pos;
+	filename = g_strdup_printf("/sys/class/net/%s/uevent", name);
 
-		pos = strchr(line, '\n');
-		if (!pos)
-			continue;
-		pos[0] = '\0';
+	if (!read_devtype(filename, &devtype))
+		goto out;
 
-		if (strncmp(line, "DEVTYPE=", 8) != 0)
-			continue;
+	if (!devtype) {
+		const char *fallback =
+			__connman_setting_get_fallback_device_type(name);
 
-		found_devtype = true;
+		if (fallback) {
+			connman_warn("%s no DEVTYPE, using fallback: %s",
+					name, fallback);
+			devtype = g_strdup(fallback);
+		}
+	}
 
-		if (strcmp(line + 8, "wlan") == 0) {
+	if (devtype) {
+		if (strcmp(devtype, "wlan") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
 			interface->device_type = CONNMAN_DEVICE_TYPE_WIFI;
-		} else if (strcmp(line + 8, "wwan") == 0) {
+		} else if (strcmp(devtype, "wwan") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_CELLULAR;
 			interface->device_type = CONNMAN_DEVICE_TYPE_CELLULAR;
-		} else if (strcmp(line + 8, "bluetooth") == 0) {
+		} else if (strcmp(devtype, "bluetooth") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
 			interface->device_type = CONNMAN_DEVICE_TYPE_BLUETOOTH;
-		} else if (strcmp(line + 8, "gadget") == 0) {
+		} else if (strcmp(devtype, "gadget") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_GADGET;
 			interface->device_type = CONNMAN_DEVICE_TYPE_GADGET;
-		} else if (strcmp(line + 8, "vlan") == 0) {
+		} else if (strcmp(devtype, "vlan") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
 			interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
-		} else if (strcmp(line + 8, "bond") == 0) {
+		} else if (strcmp(devtype, "bond") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
 			interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
-		} else if (strcmp(line + 8, "dsa") == 0) {
+		} else if (strcmp(devtype, "dsa") == 0) {
 			interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
 			interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
 		} else {
-			interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
-			interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
+			connman_warn("%s DEVTYPE=%s not supported, ignoring",
+					name, devtype);
+		}
+	} else {
+		/*
+		 * We haven't got a DEVTYPE, let's check if it's a wireless
+		 * device
+		 */
+		if (wext_interface(name)) {
+			interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
+			interface->device_type = CONNMAN_DEVICE_TYPE_WIFI;
+			connman_error("%s runs an unsupported 802.11 driver",
+					name);
+		} else {
+			interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
+			interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
+			connman_warn("%s no DEVTYPE, defaulting to ethernet",
+					name);
 		}
-	}
-
-	fclose(f);
-
-	if (found_devtype)
-		goto out;
-
-	/* We haven't got a DEVTYPE, let's check if it's a wireless device */
-	if (wext_interface(name)) {
-		interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
-		interface->device_type = CONNMAN_DEVICE_TYPE_WIFI;
-
-		connman_error("%s runs an unsupported 802.11 driver", name);
 	}
 
 out:
+	g_free(devtype);
+	g_free(filename);
 	g_free(name);
 }
 
-- 
2.47.3