connman: add patch to create read-only device when using nfsroot
[opendreambox.git] / meta-opendreambox / recipes-connectivity / connman / connman / 0001-device-inet-Create-read-only-devices-instead-of-igno.patch
1 Upstream-Status: inappropriate
2
3 From 67bed4cf2d4733df514b7be7ffad29a10d1b81a2 Mon Sep 17 00:00:00 2001
4 From: Andreas Oberritter <obi@opendreambox.org>
5 Date: Wed, 29 Oct 2014 21:19:25 +0100
6 Subject: [PATCH 1/2] device/inet: Create read-only devices instead of ignoring
7  completely
8
9 Booting an nfsroot with connman requires passing -I eth0 to ignore
10 the interface. This isn't very nice, for at least the following
11 reasons:
12
13 * A User interface based on connman is led to believe that there's no
14   network interface and thus connman seems to be offline when it's not.
15 * The DHCP lease obtained by the kernel won't get renewed.
16 * DNS servers won't get obtained from DHCP, thus requiring a workaround
17   to copy /proc/net/pnp to /etc/resolv.conf and passing -r to connmand.
18
19 Therefore change behaviour to restrict interfaces passed with -I to
20 read-only ioctls.
21
22 Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
23 ---
24  Makefile.am      |   1 +
25  include/device.h |   3 ++
26  src/device.c     |  34 +++++++++++---
27  src/inet.c       | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
28  src/ipconfig.c   |  16 +++++++
29  src/rtnl.c       |  20 +-------
30  6 files changed, 178 insertions(+), 36 deletions(-)
31
32 diff --git a/Makefile.am b/Makefile.am
33 index a574170..47aa7b8 100644
34 --- a/Makefile.am
35 +++ b/Makefile.am
36 @@ -209,6 +209,7 @@ src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
37                                 -DSTORAGEDIR=\""$(storagedir)\"" \
38                                 -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
39                                 -DCONFIGDIR=\""$(configdir)\"" \
40 +                               -DCONNMAND \
41                                 -I$(builddir)/src
42  
43  EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \
44 diff --git a/include/device.h b/include/device.h
45 index 57b925c..3c9615f 100644
46 --- a/include/device.h
47 +++ b/include/device.h
48 @@ -93,6 +93,9 @@ int connman_device_set_string(struct connman_device *device,
49                                         const char *key, const char *value);
50  const char *connman_device_get_string(struct connman_device *device,
51                                                         const char *key);
52 +void connman_device_set_readonly(struct connman_device *device,
53 +                                               bool readonly);
54 +bool connman_device_get_readonly(struct connman_device *device);
55  
56  int connman_device_add_network(struct connman_device *device,
57                                         struct connman_network *network);
58 diff --git a/src/device.c b/src/device.c
59 index c0683ab..301e850 100644
60 --- a/src/device.c
61 +++ b/src/device.c
62 @@ -54,6 +54,7 @@ struct connman_device {
63         bool powered;
64         bool scanning;
65         bool disconnected;
66 +       bool readonly;
67         char *name;
68         char *node;
69         char *address;
70 @@ -782,6 +783,32 @@ bool connman_device_get_disconnected(struct connman_device *device)
71  }
72  
73  /**
74 + * connman_device_set_readonly:
75 + * @device: device structure
76 + * @readonly: read-only state
77 + *
78 + * Change read-only state of device
79 + */
80 +void connman_device_set_readonly(struct connman_device *device,
81 +                                               bool readonly)
82 +{
83 +       DBG("device %p readonly %d", device, readonly);
84 +
85 +       device->readonly = readonly;
86 +}
87 +
88 +/**
89 + * connman_device_get_readonly:
90 + * @device: device structure
91 + *
92 + * Get device read-only state
93 + */
94 +bool connman_device_get_readonly(struct connman_device *device)
95 +{
96 +       return device->readonly;
97 +}
98 +
99 +/**
100   * connman_device_set_string:
101   * @device: device structure
102   * @key: unique identifier
103 @@ -1246,12 +1273,6 @@ struct connman_device *connman_device_create_from_index(int index)
104         if (!devname)
105                 return NULL;
106  
107 -       if (__connman_device_isfiltered(devname)) {
108 -               connman_info("Ignoring interface %s (filtered)", devname);
109 -               g_free(devname);
110 -               return NULL;
111 -       }
112 -
113         type = __connman_rtnl_get_device_type(index);
114  
115         switch (type) {
116 @@ -1305,6 +1326,7 @@ struct connman_device *connman_device_create_from_index(int index)
117         }
118  
119         connman_device_set_string(device, "Address", addr);
120 +       connman_device_set_readonly(device, __connman_device_isfiltered(devname));
121  
122  done:
123         g_free(devname);
124 diff --git a/src/inet.c b/src/inet.c
125 index cd220ff..ac646c9 100644
126 --- a/src/inet.c
127 +++ b/src/inet.c
128 @@ -55,6 +55,21 @@
129         ((struct rtattr *) (((uint8_t*) (nmsg)) +       \
130         NLMSG_ALIGN((nmsg)->nlmsg_len)))
131  
132 +static inline int __connman_inet_check_write_perm(int ifindex)
133 +{
134 +    #if defined(CONNMAND)
135 +       struct connman_device *dev = connman_device_find_by_index(ifindex);
136 +
137 +       if (!dev)
138 +               return -ENODEV;
139 +
140 +       if (connman_device_get_readonly(dev))
141 +               return -EPERM;
142 +    #endif
143 +
144 +       return 0;
145 +}
146 +
147  int __connman_inet_rtnl_addattr_l(struct nlmsghdr *n, size_t max_length,
148                                 int type, const void *data, size_t data_length)
149  {
150 @@ -104,6 +119,11 @@ int __connman_inet_modify_address(int cmd, int flags,
151         if (family != AF_INET && family != AF_INET6)
152                 return -EINVAL;
153  
154 +       if (__connman_inet_check_write_perm(index) < 0) {
155 +               DBG("insufficient permission, ignoring request");
156 +               return 0;
157 +       }
158 +
159         memset(&request, 0, sizeof(request));
160  
161         header = (struct nlmsghdr *)request;
162 @@ -245,6 +265,12 @@ int connman_inet_ifup(int index)
163         struct ifreq ifr;
164         int sk, err;
165  
166 +       err = __connman_inet_check_write_perm(index);
167 +       if (err < 0) {
168 +               DBG("insufficient permission");
169 +               return err;
170 +       }
171 +
172         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
173         if (sk < 0)
174                 return -errno;
175 @@ -288,6 +314,12 @@ int connman_inet_ifdown(int index)
176         struct sockaddr_in *addr;
177         int sk, err;
178  
179 +       err = __connman_inet_check_write_perm(index);
180 +       if (err < 0) {
181 +               DBG("insufficient permission");
182 +               return err;
183 +       }
184 +
185         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
186         if (sk < 0)
187                 return -errno;
188 @@ -454,11 +486,17 @@ int connman_inet_add_network_route(int index, const char *host,
189         struct ifreq ifr;
190         struct rtentry rt;
191         struct sockaddr_in addr;
192 -       int sk, err = 0;
193 +       int sk, err;
194  
195         DBG("index %d host %s gateway %s netmask %s", index,
196                 host, gateway, netmask);
197  
198 +       err = __connman_inet_check_write_perm(index);
199 +       if (err < 0) {
200 +               DBG("insufficient permission");
201 +               return err;
202 +       }
203 +
204         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
205         if (sk < 0) {
206                 err = -errno;
207 @@ -525,10 +563,16 @@ int connman_inet_del_network_route(int index, const char *host)
208         struct ifreq ifr;
209         struct rtentry rt;
210         struct sockaddr_in addr;
211 -       int sk, err = 0;
212 +       int sk, err;
213  
214         DBG("index %d host %s", index, host);
215  
216 +       err = __connman_inet_check_write_perm(index);
217 +       if (err < 0) {
218 +               DBG("insufficient permission");
219 +               return err;
220 +       }
221 +
222         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
223         if (sk < 0) {
224                 err = -errno;
225 @@ -573,13 +617,19 @@ int connman_inet_del_ipv6_network_route(int index, const char *host,
226                                                 unsigned char prefix_len)
227  {
228         struct in6_rtmsg rt;
229 -       int sk, err = 0;
230 +       int sk, err;
231  
232         DBG("index %d host %s", index, host);
233  
234         if (!host)
235                 return -EINVAL;
236  
237 +       err = __connman_inet_check_write_perm(index);
238 +       if (err < 0) {
239 +               DBG("insufficient permission");
240 +               return err;
241 +       }
242 +
243         memset(&rt, 0, sizeof(rt));
244  
245         rt.rtmsg_dst_len = prefix_len;
246 @@ -623,13 +673,19 @@ int connman_inet_add_ipv6_network_route(int index, const char *host,
247                                         unsigned char prefix_len)
248  {
249         struct in6_rtmsg rt;
250 -       int sk, err = 0;
251 +       int sk, err;
252  
253         DBG("index %d host %s gateway %s", index, host, gateway);
254  
255         if (!host)
256                 return -EINVAL;
257  
258 +       err = __connman_inet_check_write_perm(index);
259 +       if (err < 0) {
260 +               DBG("insufficient permission");
261 +               return err;
262 +       }
263 +
264         memset(&rt, 0, sizeof(rt));
265  
266         rt.rtmsg_dst_len = prefix_len;
267 @@ -677,13 +733,19 @@ int connman_inet_add_ipv6_host_route(int index, const char *host,
268  int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
269  {
270         struct in6_rtmsg rt;
271 -       int sk, err = 0;
272 +       int sk, err;
273  
274         DBG("index %d gateway %s", index, gateway);
275  
276         if (!gateway)
277                 return -EINVAL;
278  
279 +       err = __connman_inet_check_write_perm(index);
280 +       if (err < 0) {
281 +               DBG("insufficient permission");
282 +               return err;
283 +       }
284 +
285         memset(&rt, 0, sizeof(rt));
286  
287         if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
288 @@ -720,10 +782,16 @@ int connman_inet_set_gateway_interface(int index)
289         struct ifreq ifr;
290         struct rtentry rt;
291         struct sockaddr_in addr;
292 -       int sk, err = 0;
293 +       int sk, err;
294  
295         DBG("index %d", index);
296  
297 +       err = __connman_inet_check_write_perm(index);
298 +       if (err < 0) {
299 +               DBG("insufficient permission");
300 +               return err;
301 +       }
302 +
303         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
304         if (sk < 0) {
305                 err = -errno;
306 @@ -773,10 +841,16 @@ int connman_inet_set_ipv6_gateway_interface(int index)
307         struct rtentry rt;
308         struct sockaddr_in6 addr;
309         const struct in6_addr any = IN6ADDR_ANY_INIT;
310 -       int sk, err = 0;
311 +       int sk, err;
312  
313         DBG("index %d", index);
314  
315 +       err = __connman_inet_check_write_perm(index);
316 +       if (err < 0) {
317 +               DBG("insufficient permission");
318 +               return err;
319 +       }
320 +
321         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
322         if (sk < 0) {
323                 err = -errno;
324 @@ -825,10 +899,16 @@ int connman_inet_clear_gateway_address(int index, const char *gateway)
325         struct ifreq ifr;
326         struct rtentry rt;
327         struct sockaddr_in addr;
328 -       int sk, err = 0;
329 +       int sk, err;
330  
331         DBG("index %d gateway %s", index, gateway);
332  
333 +       err = __connman_inet_check_write_perm(index);
334 +       if (err < 0) {
335 +               DBG("insufficient permission");
336 +               return err;
337 +       }
338 +
339         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
340         if (sk < 0) {
341                 err = -errno;
342 @@ -882,10 +962,16 @@ int connman_inet_clear_gateway_interface(int index)
343         struct ifreq ifr;
344         struct rtentry rt;
345         struct sockaddr_in addr;
346 -       int sk, err = 0;
347 +       int sk, err;
348  
349         DBG("index %d", index);
350  
351 +       err = __connman_inet_check_write_perm(index);
352 +       if (err < 0) {
353 +               DBG("insufficient permission");
354 +               return err;
355 +       }
356 +
357         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
358         if (sk < 0) {
359                 err = -errno;
360 @@ -935,10 +1021,16 @@ int connman_inet_clear_ipv6_gateway_interface(int index)
361         struct rtentry rt;
362         struct sockaddr_in6 addr;
363         const struct in6_addr any = IN6ADDR_ANY_INIT;
364 -       int sk, err = 0;
365 +       int sk, err;
366  
367         DBG("index %d", index);
368  
369 +       err = __connman_inet_check_write_perm(index);
370 +       if (err < 0) {
371 +               DBG("insufficient permission");
372 +               return err;
373 +       }
374 +
375         sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
376         if (sk < 0) {
377                 err = -errno;
378 @@ -1035,11 +1127,17 @@ bool connman_inet_compare_subnet(int index, const char *host)
379  int connman_inet_remove_from_bridge(int index, const char *bridge)
380  {
381         struct ifreq ifr;
382 -       int sk, err = 0;
383 +       int sk, err;
384  
385         if (!bridge)
386                 return -EINVAL;
387  
388 +       err = __connman_inet_check_write_perm(index);
389 +       if (err < 0) {
390 +               DBG("insufficient permission");
391 +               return err;
392 +       }
393 +
394         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
395         if (sk < 0) {
396                 err = -errno;
397 @@ -1066,11 +1164,17 @@ out:
398  int connman_inet_add_to_bridge(int index, const char *bridge)
399  {
400         struct ifreq ifr;
401 -       int sk, err = 0;
402 +       int sk, err;
403  
404         if (!bridge)
405                 return -EINVAL;
406  
407 +       err = __connman_inet_check_write_perm(index);
408 +       if (err < 0) {
409 +               DBG("insufficient permission");
410 +               return err;
411 +       }
412 +
413         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
414         if (sk < 0) {
415                 err = -errno;
416 @@ -1099,6 +1203,12 @@ int connman_inet_set_mtu(int index, int mtu)
417         struct ifreq ifr;
418         int sk, err;
419  
420 +       err = __connman_inet_check_write_perm(index);
421 +       if (err < 0) {
422 +               DBG("insufficient permission");
423 +               return err;
424 +       }
425 +
426         sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
427         if (sk < 0)
428                 return sk;
429 @@ -2812,6 +2922,12 @@ static int iproute_default_modify(int cmd, uint32_t table_id, int ifindex,
430         if (ret <= 0)
431                 return -EINVAL;
432  
433 +       ret = __connman_inet_check_write_perm(ifindex);
434 +       if (ret < 0) {
435 +               DBG("insufficient permission");
436 +               return ret;
437 +       }
438 +
439         memset(&rth, 0, sizeof(rth));
440  
441         rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
442 diff --git a/src/ipconfig.c b/src/ipconfig.c
443 index 2e840a6..a353112 100644
444 --- a/src/ipconfig.c
445 +++ b/src/ipconfig.c
446 @@ -92,6 +92,17 @@ static GHashTable *ipdevice_hash = NULL;
447  static GList *ipconfig_list = NULL;
448  static bool is_ipv6_supported = false;
449  
450 +static int __connman_ipconfig_check_write_perm(const gchar *ifname)
451 +{
452 +       int index = connman_inet_ifindex(ifname);
453 +       struct connman_device *dev = connman_device_find_by_index(index);
454 +
455 +       if (!dev)
456 +               return -ENODEV;
457 +
458 +       return connman_device_get_readonly(dev) ? -EPERM : 0;
459 +}
460 +
461  void __connman_ipconfig_clear_address(struct connman_ipconfig *ipconfig)
462  {
463         if (!ipconfig)
464 @@ -211,6 +222,8 @@ static void set_ipv6_state(gchar *ifname, bool enable)
465  
466         if (!ifname)
467                 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
468 +       else if (__connman_ipconfig_check_write_perm(ifname) < 0)
469 +               return;
470         else
471                 path = g_strdup_printf(
472                         "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
473 @@ -274,6 +287,9 @@ static void set_ipv6_privacy(gchar *ifname, int value)
474         if (!ifname)
475                 return;
476  
477 +       if (__connman_ipconfig_check_write_perm(ifname) < 0)
478 +               return;
479 +
480         path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
481                                                                 ifname);
482  
483 diff --git a/src/rtnl.c b/src/rtnl.c
484 index a46aa28..b5a6dfa 100644
485 --- a/src/rtnl.c
486 +++ b/src/rtnl.c
487 @@ -83,17 +83,6 @@ static void free_interface(gpointer data)
488         g_free(interface);
489  }
490  
491 -static bool ether_blacklisted(const char *name)
492 -{
493 -       if (!name)
494 -               return true;
495 -
496 -       if (__connman_device_isfiltered(name))
497 -               return true;
498 -
499 -       return false;
500 -}
501 -
502  static bool wext_interface(char *ifname)
503  {
504         struct iwreq wrq;
505 @@ -124,13 +113,8 @@ static void read_uevent(struct interface_data *interface)
506  
507         name = connman_inet_ifname(interface->index);
508  
509 -       if (ether_blacklisted(name)) {
510 -               interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
511 -               interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
512 -       } else {
513 -               interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
514 -               interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
515 -       }
516 +       interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
517 +       interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
518  
519         filename = g_strdup_printf("/sys/class/net/%s/uevent", name);
520  
521 -- 
522 1.9.1
523