While matching on the MAC address is working for plain interfaces, it
wont work for managing VLAN interfaces. The VLAN interfaces share the
same MAC address with the parent interface.
The argument that the MAC address is the only stable way to identify a
device is a bit weak because the MAC can be changed via udev or other
means.
Furthermore, with systemd's feature of stable interface name it makes
things a lot easier for embedded system with a pre-provisioning
rootfs. Such devices have different MAC address but all of them have
the same interface name.
---
doc/config-format.txt | 2 ++
doc/connman-service.config.5.in | 9 +++++++++
src/config.c | 27 +++++++++++++++++++++++++++
3 files changed, 38 insertions(+)
diff --git a/doc/config-format.txt b/doc/config-format.txt
index 584220f0bf0e..cdde9cbcf676 100644
--- a/doc/config-format.txt
+++ b/doc/config-format.txt
@@ -59,6 +59,8 @@ an identifier unique to the config file.
interface is used. The byte values must have prefix 0 added,
the bytes must be separated by ":" char and its length must be
exactly 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 = 17 characters.
+- DeviceName: The interface name where this setting should be applied, e.g.
+ eth0. The MAC address will take preference over DeviceName in matching.
- Nameservers: Comma separated list of nameservers
- SearchDomains: Comma separated list of DNS search domains
- Timeservers: Comma separated list of timeservers
diff --git a/doc/connman-service.config.5.in b/doc/connman-service.config.5.in
index eb63f225b515..701f61f9ea13 100644
--- a/doc/connman-service.config.5.in
+++ b/doc/connman-service.config.5.in
@@ -59,6 +59,10 @@ IPv6 privacy settings as per RFC3041.
MAC address of the interface to be used. If not specified, the first
found interface is used. Must be in format ab:cd:ef:01:23:45.
.TP
+.BI DeviceName= ifname
+Device name the interface to be used, e.g. eth0. MAC takes preference
+over DeviceName.
+.TP
.BI Nameservers= servers
Comma separated list of nameservers.
.TP
@@ -209,6 +213,11 @@ Name = my_home_wifi
Passphrase = password
IPv4 = 192.168.2.2/255.255.255.0/192.168.2.1
MAC = 06:05:04:03:02:01
+
+[service_vlan]
+Type = ethernet
+DeviceName = enp4s0.1
+IPv4 = 192.168.1.42/255.255.255.0/192.168.1.1
.fi
.SH "SEE ALSO"
.BR connman (8)
diff --git a/src/config.c b/src/config.c
index af4f07e1e578..62023b1072da 100644
--- a/src/config.c
+++ b/src/config.c
@@ -72,6 +72,7 @@ struct connman_config_service {
char *ipv6_gateway;
char *ipv6_privacy;
char *mac;
+ char *devname;
bool mdns;
char **nameservers;
char **search_domains;
@@ -119,6 +120,7 @@ static bool cleanup = false;
#define SERVICE_KEY_IPv6 "IPv6"
#define SERVICE_KEY_IPv6_PRIVACY "IPv6.Privacy"
#define SERVICE_KEY_MAC "MAC"
+#define SERVICE_KEY_DEVICE_NAME "DeviceName"
#define SERVICE_KEY_NAMESERVERS "Nameservers"
#define SERVICE_KEY_SEARCH_DOMAINS "SearchDomains"
#define SERVICE_KEY_TIMESERVERS "Timeservers"
@@ -154,6 +156,7 @@ static const char *service_possible_keys[] = {
SERVICE_KEY_IPv6,
SERVICE_KEY_IPv6_PRIVACY,
SERVICE_KEY_MAC,
+ SERVICE_KEY_DEVICE_NAME,
SERVICE_KEY_MDNS,
SERVICE_KEY_NAMESERVERS,
SERVICE_KEY_SEARCH_DOMAINS,
@@ -257,6 +260,7 @@ static void unregister_service(gpointer data)
g_free(config_service->ipv6_gateway);
g_free(config_service->ipv6_privacy);
g_free(config_service->mac);
+ g_free(config_service->devname);
g_strfreev(config_service->nameservers);
g_strfreev(config_service->search_domains);
g_strfreev(config_service->timeservers);
@@ -478,6 +482,12 @@ static bool load_service_generic(GKeyFile *keyfile,
service->mac = str;
}
+ str = __connman_config_get_string(keyfile, group, SERVICE_KEY_DEVICE_NAME, NULL);
+ if (str) {
+ g_free(service->devname);
+ service->devname = str;
+ }
+
str = __connman_config_get_string(keyfile, group, SERVICE_KEY_DOMAIN, NULL);
if (str) {
g_free(service->domain_name);
@@ -531,6 +541,7 @@ static bool load_service_generic(GKeyFile *keyfile,
g_free(service->ipv6_address);
g_free(service->ipv6_gateway);
g_free(service->mac);
+ g_free(service->devname);
g_free(service);
return false;
@@ -1271,6 +1282,22 @@ static int try_provision_service(struct connman_config_service
*config,
if (g_ascii_strcasecmp(device_addr, config->mac) != 0)
return -ENOENT;
+ } else if (config->devname) {
+ struct connman_device *device;
+ const char *devname;
+
+ device = connman_network_get_device(network);
+ if (!device) {
+ connman_error("Network device is missing");
+ return -ENODEV;
+ }
+
+ devname = connman_device_get_string(device, "Interface");
+
+ DBG("wants %s has %s", config->devname, devname);
+
+ if (g_ascii_strcasecmp(devname, config->devname) != 0)
+ return -ENOENT;
}
if (!config->ipv6_address) {
--
2.20.1