1 From cd7e1a841d50f0a975e7c2c3af9bfec08823f6f4 Mon Sep 17 00:00:00 2001
2 From: Andreas Oberritter <obi@opendreambox.org>
3 Date: Wed, 29 Oct 2014 21:19:25 +0100
4 Subject: [PATCH] device/inet: Create read-only devices instead of ignoring
7 Booting an nfsroot with connman requires passing -I eth0 to ignore
8 the interface. This isn't very nice, for at least the following
11 * A User interface based on connman is led to believe that there's no
12 network interface and thus connman seems to be offline when it's not.
13 * The DHCP lease obtained by the kernel won't get renewed.
14 * DNS servers won't get obtained from DHCP, thus requiring a workaround
15 to copy /proc/net/pnp to /etc/resolv.conf and passing -r to connmand.
17 Therefore change behaviour to restrict interfaces passed with -I to
20 Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
23 include/device.h | 3 ++
24 src/device.c | 34 +++++++++++---
25 src/inet.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
26 src/ipconfig.c | 16 +++++++
27 src/rtnl.c | 20 +-------
28 6 files changed, 178 insertions(+), 36 deletions(-)
30 diff --git a/Makefile.am b/Makefile.am
31 index fb7c74e..90cae75 100644
34 @@ -227,6 +227,7 @@ src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
35 -DSTORAGEDIR=\""$(storagedir)\"" \
36 -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
37 -DCONFIGDIR=\""$(configdir)\"" \
41 EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \
42 diff --git a/include/device.h b/include/device.h
43 index 9ac800a..62753db 100644
44 --- a/include/device.h
45 +++ b/include/device.h
46 @@ -89,6 +89,9 @@ int connman_device_set_string(struct connman_device *device,
47 const char *key, const char *value);
48 const char *connman_device_get_string(struct connman_device *device,
50 +void connman_device_set_readonly(struct connman_device *device,
52 +bool connman_device_get_readonly(struct connman_device *device);
54 int connman_device_add_network(struct connman_device *device,
55 struct connman_network *network);
56 diff --git a/src/device.c b/src/device.c
57 index 188106c..3e00001 100644
60 @@ -53,6 +53,7 @@ struct connman_device {
68 @@ -747,6 +748,32 @@ int connman_device_set_scanning(struct connman_device *device,
72 + * connman_device_set_readonly:
73 + * @device: device structure
74 + * @readonly: read-only state
76 + * Change read-only state of device
78 +void connman_device_set_readonly(struct connman_device *device,
81 + DBG("device %p readonly %d", device, readonly);
83 + device->readonly = readonly;
87 + * connman_device_get_readonly:
88 + * @device: device structure
90 + * Get device read-only state
92 +bool connman_device_get_readonly(struct connman_device *device)
94 + return device->readonly;
98 * connman_device_set_string:
99 * @device: device structure
100 * @key: unique identifier
101 @@ -1211,12 +1238,6 @@ struct connman_device *connman_device_create_from_index(int index)
105 - if (__connman_device_isfiltered(devname)) {
106 - connman_info("Ignoring interface %s (filtered)", devname);
111 type = __connman_rtnl_get_device_type(index);
114 @@ -1270,6 +1291,7 @@ struct connman_device *connman_device_create_from_index(int index)
117 connman_device_set_string(device, "Address", addr);
118 + connman_device_set_readonly(device, __connman_device_isfiltered(devname));
122 diff --git a/src/inet.c b/src/inet.c
123 index dc788ea..d72605f 100644
127 ((struct rtattr *) (((uint8_t*) (nmsg)) + \
128 NLMSG_ALIGN((nmsg)->nlmsg_len)))
130 +static inline int __connman_inet_check_write_perm(int ifindex)
132 + #if defined(CONNMAND)
133 + struct connman_device *dev = connman_device_find_by_index(ifindex);
138 + if (connman_device_get_readonly(dev))
145 int __connman_inet_rtnl_addattr_l(struct nlmsghdr *n, size_t max_length,
146 int type, const void *data, size_t data_length)
148 @@ -104,6 +119,11 @@ int __connman_inet_modify_address(int cmd, int flags,
149 if (family != AF_INET && family != AF_INET6)
152 + if (__connman_inet_check_write_perm(index) < 0) {
153 + DBG("insufficient permission, ignoring request");
157 memset(&request, 0, sizeof(request));
159 header = (struct nlmsghdr *)request;
160 @@ -245,6 +265,12 @@ int connman_inet_ifup(int index)
164 + err = __connman_inet_check_write_perm(index);
166 + DBG("insufficient permission");
170 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
173 @@ -288,6 +314,12 @@ int connman_inet_ifdown(int index)
174 struct sockaddr_in *addr;
177 + err = __connman_inet_check_write_perm(index);
179 + DBG("insufficient permission");
183 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
186 @@ -454,11 +486,17 @@ int connman_inet_add_network_route(int index, const char *host,
189 struct sockaddr_in addr;
193 DBG("index %d host %s gateway %s netmask %s", index,
194 host, gateway, netmask);
196 + err = __connman_inet_check_write_perm(index);
198 + DBG("insufficient permission");
202 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
205 @@ -525,10 +563,16 @@ int connman_inet_del_network_route(int index, const char *host)
208 struct sockaddr_in addr;
212 DBG("index %d host %s", index, host);
214 + err = __connman_inet_check_write_perm(index);
216 + DBG("insufficient permission");
220 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
223 @@ -573,13 +617,19 @@ int connman_inet_del_ipv6_network_route(int index, const char *host,
224 unsigned char prefix_len)
230 DBG("index %d host %s", index, host);
235 + err = __connman_inet_check_write_perm(index);
237 + DBG("insufficient permission");
241 memset(&rt, 0, sizeof(rt));
243 rt.rtmsg_dst_len = prefix_len;
244 @@ -623,13 +673,19 @@ int connman_inet_add_ipv6_network_route(int index, const char *host,
245 unsigned char prefix_len)
251 DBG("index %d host %s gateway %s", index, host, gateway);
256 + err = __connman_inet_check_write_perm(index);
258 + DBG("insufficient permission");
262 memset(&rt, 0, sizeof(rt));
264 rt.rtmsg_dst_len = prefix_len;
265 @@ -677,13 +733,19 @@ int connman_inet_add_ipv6_host_route(int index, const char *host,
266 int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
272 DBG("index %d gateway %s", index, gateway);
277 + err = __connman_inet_check_write_perm(index);
279 + DBG("insufficient permission");
283 memset(&rt, 0, sizeof(rt));
285 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
286 @@ -720,10 +782,16 @@ int connman_inet_set_gateway_interface(int index)
289 struct sockaddr_in addr;
293 DBG("index %d", index);
295 + err = __connman_inet_check_write_perm(index);
297 + DBG("insufficient permission");
301 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
304 @@ -773,10 +841,16 @@ int connman_inet_set_ipv6_gateway_interface(int index)
306 struct sockaddr_in6 addr;
307 const struct in6_addr any = IN6ADDR_ANY_INIT;
311 DBG("index %d", index);
313 + err = __connman_inet_check_write_perm(index);
315 + DBG("insufficient permission");
319 sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
322 @@ -825,10 +899,16 @@ int connman_inet_clear_gateway_address(int index, const char *gateway)
325 struct sockaddr_in addr;
329 DBG("index %d gateway %s", index, gateway);
331 + err = __connman_inet_check_write_perm(index);
333 + DBG("insufficient permission");
337 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
340 @@ -882,10 +962,16 @@ int connman_inet_clear_gateway_interface(int index)
343 struct sockaddr_in addr;
347 DBG("index %d", index);
349 + err = __connman_inet_check_write_perm(index);
351 + DBG("insufficient permission");
355 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
358 @@ -935,10 +1021,16 @@ int connman_inet_clear_ipv6_gateway_interface(int index)
360 struct sockaddr_in6 addr;
361 const struct in6_addr any = IN6ADDR_ANY_INIT;
365 DBG("index %d", index);
367 + err = __connman_inet_check_write_perm(index);
369 + DBG("insufficient permission");
373 sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
376 @@ -1035,11 +1127,17 @@ bool connman_inet_compare_subnet(int index, const char *host)
377 int connman_inet_remove_from_bridge(int index, const char *bridge)
386 + err = __connman_inet_check_write_perm(index);
388 + DBG("insufficient permission");
392 sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
395 @@ -1066,11 +1164,17 @@ out:
396 int connman_inet_add_to_bridge(int index, const char *bridge)
405 + err = __connman_inet_check_write_perm(index);
407 + DBG("insufficient permission");
411 sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
414 @@ -1099,6 +1203,12 @@ int connman_inet_set_mtu(int index, int mtu)
418 + err = __connman_inet_check_write_perm(index);
420 + DBG("insufficient permission");
424 sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
427 @@ -2809,6 +2919,12 @@ static int iproute_default_modify(int cmd, uint32_t table_id, int ifindex,
431 + ret = __connman_inet_check_write_perm(ifindex);
433 + DBG("insufficient permission");
437 memset(&rth, 0, sizeof(rth));
439 rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
440 diff --git a/src/ipconfig.c b/src/ipconfig.c
441 index 0dc702b..64866ba 100644
444 @@ -89,6 +89,17 @@ static GHashTable *ipdevice_hash = NULL;
445 static GList *ipconfig_list = NULL;
446 static bool is_ipv6_supported = false;
448 +static int __connman_ipconfig_check_write_perm(const gchar *ifname)
450 + int index = connman_inet_ifindex(ifname);
451 + struct connman_device *dev = connman_device_find_by_index(index);
456 + return connman_device_get_readonly(dev) ? -EPERM : 0;
459 void __connman_ipconfig_clear_address(struct connman_ipconfig *ipconfig)
462 @@ -209,6 +220,8 @@ static void set_ipv6_state(gchar *ifname, bool enable)
465 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
466 + else if (__connman_ipconfig_check_write_perm(ifname) < 0)
469 path = g_strdup_printf(
470 "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
471 @@ -272,6 +285,9 @@ static void set_ipv6_privacy(gchar *ifname, int value)
475 + if (__connman_ipconfig_check_write_perm(ifname) < 0)
478 path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
481 diff --git a/src/rtnl.c b/src/rtnl.c
482 index d1b851f..82e97dc 100644
485 @@ -83,17 +83,6 @@ static void free_interface(gpointer data)
489 -static bool ether_blacklisted(const char *name)
494 - if (__connman_device_isfiltered(name))
500 static bool wext_interface(char *ifname)
503 @@ -124,13 +113,8 @@ static void read_uevent(struct interface_data *interface)
505 name = connman_inet_ifname(interface->index);
507 - if (ether_blacklisted(name)) {
508 - interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
509 - interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
511 - interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
512 - interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
514 + interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
515 + interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
517 filename = g_strdup_printf("/sys/class/net/%s/uevent", name);