Imported Upstream version 1.38
[platform/upstream/connman.git] / src / tethering.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2011  ProFUSION embedded systems
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <sys/ioctl.h>
33 #include <net/if.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <netinet/in.h>
37 #include <linux/sockios.h>
38 #include <linux/if_tun.h>
39 #include <linux/if_bridge.h>
40
41 #include "connman.h"
42
43 #include <gdhcp/gdhcp.h>
44
45 #include <gdbus.h>
46
47 #ifndef DBUS_TYPE_UNIX_FD
48 #define DBUS_TYPE_UNIX_FD -1
49 #endif
50
51 #define BRIDGE_NAME "tether"
52
53 #define DEFAULT_MTU     1500
54
55 static char *private_network_primary_dns = NULL;
56 static char *private_network_secondary_dns = NULL;
57
58 static volatile int tethering_enabled;
59 static GDHCPServer *tethering_dhcp_server = NULL;
60 static struct connman_ippool *dhcp_ippool = NULL;
61 static DBusConnection *connection;
62 static GHashTable *pn_hash;
63
64 static GHashTable *clients_table;
65
66 struct _clients_notify {
67         int id;
68         GHashTable *remove;
69 } *clients_notify;
70
71 struct connman_private_network {
72         char *owner;
73         char *path;
74         guint watch;
75         DBusMessage *msg;
76         DBusMessage *reply;
77         int fd;
78         char *interface;
79         int index;
80         guint iface_watch;
81         struct connman_ippool *pool;
82         char *primary_dns;
83         char *secondary_dns;
84 };
85
86 const char *__connman_tethering_get_bridge(void)
87 {
88         int sk, err;
89         unsigned long args[3];
90
91         sk = socket(AF_INET, SOCK_STREAM, 0);
92         if (sk < 0)
93                 return NULL;
94
95         args[0] = BRCTL_GET_VERSION;
96         args[1] = args[2] = 0;
97         err = ioctl(sk, SIOCGIFBR, &args);
98         close(sk);
99         if (err == -1) {
100                 connman_error("Missing support for 802.1d ethernet bridging");
101                 return NULL;
102         }
103
104         return BRIDGE_NAME;
105 }
106
107 static void dhcp_server_debug(const char *str, void *data)
108 {
109         connman_info("%s: %s\n", (const char *) data, str);
110 }
111
112 static void dhcp_server_error(GDHCPServerError error)
113 {
114         switch (error) {
115         case G_DHCP_SERVER_ERROR_NONE:
116                 connman_error("OK");
117                 break;
118         case G_DHCP_SERVER_ERROR_INTERFACE_UNAVAILABLE:
119                 connman_error("Interface unavailable");
120                 break;
121         case G_DHCP_SERVER_ERROR_INTERFACE_IN_USE:
122                 connman_error("Interface in use");
123                 break;
124         case G_DHCP_SERVER_ERROR_INTERFACE_DOWN:
125                 connman_error("Interface down");
126                 break;
127         case G_DHCP_SERVER_ERROR_NOMEM:
128                 connman_error("No memory");
129                 break;
130         case G_DHCP_SERVER_ERROR_INVALID_INDEX:
131                 connman_error("Invalid index");
132                 break;
133         case G_DHCP_SERVER_ERROR_INVALID_OPTION:
134                 connman_error("Invalid option");
135                 break;
136         case G_DHCP_SERVER_ERROR_IP_ADDRESS_INVALID:
137                 connman_error("Invalid address");
138                 break;
139         }
140 }
141
142 static GDHCPServer *dhcp_server_start(const char *bridge,
143                                 const char *router, const char *subnet,
144                                 const char *start_ip, const char *end_ip,
145                                 unsigned int lease_time, const char *dns)
146 {
147         GDHCPServerError error;
148         GDHCPServer *dhcp_server;
149         int index;
150
151         DBG("");
152
153         index = connman_inet_ifindex(bridge);
154         if (index < 0)
155                 return NULL;
156
157         dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &error);
158         if (!dhcp_server) {
159                 dhcp_server_error(error);
160                 return NULL;
161         }
162
163         g_dhcp_server_set_debug(dhcp_server, dhcp_server_debug, "DHCP server");
164
165         g_dhcp_server_set_lease_time(dhcp_server, lease_time);
166         g_dhcp_server_set_option(dhcp_server, G_DHCP_SUBNET, subnet);
167         g_dhcp_server_set_option(dhcp_server, G_DHCP_ROUTER, router);
168         g_dhcp_server_set_option(dhcp_server, G_DHCP_DNS_SERVER, dns);
169         g_dhcp_server_set_ip_range(dhcp_server, start_ip, end_ip);
170
171         g_dhcp_server_start(dhcp_server);
172
173         return dhcp_server;
174 }
175
176 static void dhcp_server_stop(GDHCPServer *server)
177 {
178         if (!server)
179                 return;
180
181         g_dhcp_server_unref(server);
182 }
183
184 static void tethering_restart(struct connman_ippool *pool, void *user_data)
185 {
186         DBG("pool %p", pool);
187         __connman_tethering_set_disabled();
188         __connman_tethering_set_enabled();
189 }
190
191 static void unregister_client(gpointer key,
192                                         gpointer value, gpointer user_data)
193 {
194         const char *addr = key;
195         __connman_tethering_client_unregister(addr);
196 }
197
198 static void unregister_all_clients(void)
199 {
200         g_hash_table_foreach(clients_table, unregister_client, NULL);
201 }
202
203 int __connman_tethering_set_enabled(void)
204 {
205         int index;
206         int err;
207         const char *gateway;
208         const char *broadcast;
209         const char *subnet_mask;
210         const char *start_ip;
211         const char *end_ip;
212         const char *dns;
213         unsigned char prefixlen;
214         char **ns;
215
216         DBG("enabled %d", tethering_enabled + 1);
217
218         if (__sync_fetch_and_add(&tethering_enabled, 1) != 0)
219                 return 0;
220
221         err = __connman_bridge_create(BRIDGE_NAME);
222         if (err < 0) {
223                 __sync_fetch_and_sub(&tethering_enabled, 1);
224                 return -EOPNOTSUPP;
225         }
226
227         index = connman_inet_ifindex(BRIDGE_NAME);
228         dhcp_ippool = __connman_ippool_create(index, 2, 252,
229                                                 tethering_restart, NULL);
230         if (!dhcp_ippool) {
231                 connman_error("Fail to create IP pool");
232                 __connman_bridge_remove(BRIDGE_NAME);
233                 __sync_fetch_and_sub(&tethering_enabled, 1);
234                 return -EADDRNOTAVAIL;
235         }
236
237         gateway = __connman_ippool_get_gateway(dhcp_ippool);
238         broadcast = __connman_ippool_get_broadcast(dhcp_ippool);
239         subnet_mask = __connman_ippool_get_subnet_mask(dhcp_ippool);
240         start_ip = __connman_ippool_get_start_ip(dhcp_ippool);
241         end_ip = __connman_ippool_get_end_ip(dhcp_ippool);
242
243         err = __connman_bridge_enable(BRIDGE_NAME, gateway,
244                         connman_ipaddress_calc_netmask_len(subnet_mask),
245                         broadcast);
246         if (err < 0 && err != -EALREADY) {
247                 __connman_ippool_free(dhcp_ippool);
248                 dhcp_ippool = NULL;
249                 __connman_bridge_remove(BRIDGE_NAME);
250                 __sync_fetch_and_sub(&tethering_enabled, 1);
251                 return -EADDRNOTAVAIL;
252         }
253
254         ns = connman_setting_get_string_list("FallbackNameservers");
255         if (ns) {
256                 if (ns[0]) {
257                         g_free(private_network_primary_dns);
258                         private_network_primary_dns = g_strdup(ns[0]);
259                 }
260                 if (ns[1]) {
261                         g_free(private_network_secondary_dns);
262                         private_network_secondary_dns = g_strdup(ns[1]);
263                 }
264
265                 DBG("Fallback ns primary %s secondary %s",
266                         private_network_primary_dns,
267                         private_network_secondary_dns);
268         }
269
270         dns = gateway;
271         if (__connman_dnsproxy_add_listener(index) < 0) {
272                 connman_error("Can't add listener %s to DNS proxy",
273                                                                 BRIDGE_NAME);
274                 dns = private_network_primary_dns;
275                 DBG("Serving %s nameserver to clients", dns);
276         }
277
278         tethering_dhcp_server = dhcp_server_start(BRIDGE_NAME,
279                                                 gateway, subnet_mask,
280                                                 start_ip, end_ip,
281                                                 24 * 3600, dns);
282         if (!tethering_dhcp_server) {
283                 __connman_bridge_disable(BRIDGE_NAME);
284                 __connman_ippool_free(dhcp_ippool);
285                 dhcp_ippool = NULL;
286                 __connman_bridge_remove(BRIDGE_NAME);
287                 __sync_fetch_and_sub(&tethering_enabled, 1);
288                 return -EOPNOTSUPP;
289         }
290
291         prefixlen = connman_ipaddress_calc_netmask_len(subnet_mask);
292         err = __connman_nat_enable(BRIDGE_NAME, start_ip, prefixlen);
293         if (err < 0) {
294                 connman_error("Cannot enable NAT %d/%s", err, strerror(-err));
295                 dhcp_server_stop(tethering_dhcp_server);
296                 __connman_bridge_disable(BRIDGE_NAME);
297                 __connman_ippool_free(dhcp_ippool);
298                 dhcp_ippool = NULL;
299                 __connman_bridge_remove(BRIDGE_NAME);
300                 __sync_fetch_and_sub(&tethering_enabled, 1);
301                 return -EOPNOTSUPP;
302         }
303
304         err = __connman_ipv6pd_setup(BRIDGE_NAME);
305         if (err < 0 && err != -EINPROGRESS)
306                 DBG("Cannot setup IPv6 prefix delegation %d/%s", err,
307                         strerror(-err));
308
309         DBG("tethering started");
310
311         return 0;
312 }
313
314 void __connman_tethering_set_disabled(void)
315 {
316         int index;
317
318         DBG("enabled %d", tethering_enabled - 1);
319
320         if (__sync_fetch_and_sub(&tethering_enabled, 1) != 1)
321                 return;
322
323         unregister_all_clients();
324
325         __connman_ipv6pd_cleanup();
326
327         index = connman_inet_ifindex(BRIDGE_NAME);
328         __connman_dnsproxy_remove_listener(index);
329
330         __connman_nat_disable(BRIDGE_NAME);
331
332         dhcp_server_stop(tethering_dhcp_server);
333
334         tethering_dhcp_server = NULL;
335
336         __connman_bridge_disable(BRIDGE_NAME);
337
338         __connman_ippool_free(dhcp_ippool);
339         dhcp_ippool = NULL;
340
341         __connman_bridge_remove(BRIDGE_NAME);
342
343         g_free(private_network_primary_dns);
344         private_network_primary_dns = NULL;
345         g_free(private_network_secondary_dns);
346         private_network_secondary_dns = NULL;
347
348         DBG("tethering stopped");
349 }
350
351 static void append_client(gpointer key, gpointer value,
352                                                 gpointer user_data)
353 {
354         const char *addr = key;
355         DBusMessageIter *array = user_data;
356
357         dbus_message_iter_append_basic(array, DBUS_TYPE_STRING,
358                                                         &addr);
359 }
360
361 void __connman_tethering_list_clients(DBusMessageIter *array)
362 {
363         g_hash_table_foreach(clients_table, append_client, array);
364 }
365
366 static void setup_tun_interface(unsigned int flags, unsigned change,
367                 void *data)
368 {
369         struct connman_private_network *pn = data;
370         unsigned char prefixlen;
371         DBusMessageIter array, dict;
372         const char *server_ip;
373         const char *peer_ip;
374         const char *subnet_mask;
375         int err;
376
377         DBG("index %d flags %d change %d", pn->index,  flags, change);
378
379         if (flags & IFF_UP)
380                 return;
381
382         subnet_mask = __connman_ippool_get_subnet_mask(pn->pool);
383         server_ip = __connman_ippool_get_start_ip(pn->pool);
384         peer_ip = __connman_ippool_get_end_ip(pn->pool);
385         prefixlen = connman_ipaddress_calc_netmask_len(subnet_mask);
386
387         if ((__connman_inet_modify_address(RTM_NEWADDR,
388                                 NLM_F_REPLACE | NLM_F_ACK, pn->index, AF_INET,
389                                 server_ip, peer_ip, prefixlen, NULL)) < 0) {
390                 DBG("address setting failed");
391                 return;
392         }
393
394         connman_inet_ifup(pn->index);
395
396         err = __connman_nat_enable(BRIDGE_NAME, server_ip, prefixlen);
397         if (err < 0) {
398                 connman_error("failed to enable NAT");
399                 goto error;
400         }
401
402         dbus_message_iter_init_append(pn->reply, &array);
403
404         dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
405                                                 &pn->path);
406
407         connman_dbus_dict_open(&array, &dict);
408
409         connman_dbus_dict_append_basic(&dict, "ServerIPv4",
410                                         DBUS_TYPE_STRING, &server_ip);
411         connman_dbus_dict_append_basic(&dict, "PeerIPv4",
412                                         DBUS_TYPE_STRING, &peer_ip);
413         if (pn->primary_dns)
414                 connman_dbus_dict_append_basic(&dict, "PrimaryDNS",
415                                         DBUS_TYPE_STRING, &pn->primary_dns);
416
417         if (pn->secondary_dns)
418                 connman_dbus_dict_append_basic(&dict, "SecondaryDNS",
419                                         DBUS_TYPE_STRING, &pn->secondary_dns);
420
421         connman_dbus_dict_close(&array, &dict);
422
423         dbus_message_iter_append_basic(&array, DBUS_TYPE_UNIX_FD, &pn->fd);
424
425         g_dbus_send_message(connection, pn->reply);
426
427         return;
428
429 error:
430         pn->reply = __connman_error_failed(pn->msg, -err);
431         g_dbus_send_message(connection, pn->reply);
432
433         g_hash_table_remove(pn_hash, pn->path);
434 }
435
436 static void remove_private_network(gpointer user_data)
437 {
438         struct connman_private_network *pn = user_data;
439
440         __connman_nat_disable(BRIDGE_NAME);
441         connman_rtnl_remove_watch(pn->iface_watch);
442         __connman_ippool_free(pn->pool);
443
444         if (pn->watch > 0) {
445                 g_dbus_remove_watch(connection, pn->watch);
446                 pn->watch = 0;
447         }
448
449         close(pn->fd);
450
451         g_free(pn->interface);
452         g_free(pn->owner);
453         g_free(pn->path);
454         g_free(pn->primary_dns);
455         g_free(pn->secondary_dns);
456         g_free(pn);
457 }
458
459 static void owner_disconnect(DBusConnection *conn, void *user_data)
460 {
461         struct connman_private_network *pn = user_data;
462
463         DBG("%s died", pn->owner);
464
465         pn->watch = 0;
466
467         g_hash_table_remove(pn_hash, pn->path);
468 }
469
470 static void ippool_disconnect(struct connman_ippool *pool, void *user_data)
471 {
472         struct connman_private_network *pn = user_data;
473
474         DBG("block used externally");
475
476         g_hash_table_remove(pn_hash, pn->path);
477 }
478
479 static gboolean client_send_changed(gpointer data)
480 {
481         DBusMessage *signal;
482         DBusMessageIter iter, array;
483
484         DBG("");
485
486         clients_notify->id = 0;
487
488         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
489                                 CONNMAN_MANAGER_INTERFACE, "TetheringClientsChanged");
490         if (!signal)
491                 return FALSE;
492
493         dbus_message_iter_init_append(signal, &iter);
494         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
495                                 DBUS_TYPE_STRING_AS_STRING, &array);
496
497         g_hash_table_foreach(clients_table, append_client, &array);
498
499         dbus_message_iter_close_container(&iter, &array);
500
501         dbus_message_iter_init_append(signal, &iter);
502         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
503                                 DBUS_TYPE_STRING_AS_STRING, &array);
504
505         g_hash_table_foreach(clients_notify->remove, append_client, &array);
506
507         dbus_message_iter_close_container(&iter, &array);
508
509         dbus_connection_send(connection, signal, NULL);
510         dbus_message_unref(signal);
511
512         g_hash_table_remove_all(clients_notify->remove);
513
514         return FALSE;
515 }
516
517 static void client_schedule_changed(void)
518 {
519         if (clients_notify->id != 0)
520                 return;
521
522         clients_notify->id = g_timeout_add(100, client_send_changed, NULL);
523 }
524
525 static void client_added(const char *addr)
526 {
527         DBG("client %s", addr);
528
529         g_hash_table_remove(clients_notify->remove, addr);
530
531         client_schedule_changed();
532 }
533
534 static void client_removed(const char *addr)
535 {
536         DBG("client %s", addr);
537
538         g_hash_table_replace(clients_notify->remove, g_strdup(addr), NULL);
539
540         client_schedule_changed();
541 }
542
543 int __connman_private_network_request(DBusMessage *msg, const char *owner)
544 {
545         struct connman_private_network *pn;
546         char *iface = NULL;
547         char *path = NULL;
548         int index, fd, err;
549
550         if (DBUS_TYPE_UNIX_FD < 0)
551                 return -EINVAL;
552
553         fd = connman_inet_create_tunnel(&iface);
554         if (fd < 0)
555                 return fd;
556
557         path = g_strdup_printf("/tethering/%s", iface);
558
559         pn = g_hash_table_lookup(pn_hash, path);
560         if (pn) {
561                 g_free(path);
562                 g_free(iface);
563                 close(fd);
564                 return -EEXIST;
565         }
566
567         index = connman_inet_ifindex(iface);
568         if (index < 0) {
569                 err = -ENODEV;
570                 goto error;
571         }
572         DBG("interface %s", iface);
573
574         err = connman_inet_set_mtu(index, DEFAULT_MTU);
575
576         pn = g_try_new0(struct connman_private_network, 1);
577         if (!pn) {
578                 err = -ENOMEM;
579                 goto error;
580         }
581
582         pn->owner = g_strdup(owner);
583         pn->path = path;
584         pn->watch = g_dbus_add_disconnect_watch(connection, pn->owner,
585                                         owner_disconnect, pn, NULL);
586         pn->msg = msg;
587         pn->reply = dbus_message_new_method_return(pn->msg);
588         if (!pn->reply)
589                 goto error;
590
591         pn->fd = fd;
592         pn->interface = iface;
593         pn->index = index;
594         pn->pool = __connman_ippool_create(pn->index, 1, 1, ippool_disconnect, pn);
595         if (!pn->pool) {
596                 errno = -ENOMEM;
597                 goto error;
598         }
599
600         pn->primary_dns = g_strdup(private_network_primary_dns);
601         pn->secondary_dns = g_strdup(private_network_secondary_dns);
602
603         pn->iface_watch = connman_rtnl_add_newlink_watch(index,
604                                                 setup_tun_interface, pn);
605
606         g_hash_table_insert(pn_hash, pn->path, pn);
607
608         return 0;
609
610 error:
611         close(fd);
612         g_free(iface);
613         g_free(path);
614         if (pn)
615                 g_free(pn->owner);
616         g_free(pn);
617         return err;
618 }
619
620 int __connman_private_network_release(const char *path)
621 {
622         struct connman_private_network *pn;
623
624         pn = g_hash_table_lookup(pn_hash, path);
625         if (!pn)
626                 return -EACCES;
627
628         g_hash_table_remove(pn_hash, path);
629         return 0;
630 }
631
632 void __connman_tethering_client_register(const char *addr)
633 {
634         g_hash_table_insert(clients_table, g_strdup(addr), NULL);
635         client_added(addr);
636 }
637
638 void __connman_tethering_client_unregister(const char *addr)
639 {
640         client_removed(addr);
641         g_hash_table_remove(clients_table, addr);
642 }
643
644 int __connman_tethering_init(void)
645 {
646         DBG("");
647
648         tethering_enabled = 0;
649
650         connection = connman_dbus_get_connection();
651         if (!connection)
652                 return -EFAULT;
653
654         pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
655                                                 NULL, remove_private_network);
656
657         clients_table = g_hash_table_new_full(g_str_hash, g_str_equal,
658                                                         g_free, NULL);
659
660         clients_notify = g_new0(struct _clients_notify, 1);
661         clients_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal,
662                                                         g_free, NULL);
663         return 0;
664 }
665
666 void __connman_tethering_cleanup(void)
667 {
668         DBG("enabled %d", tethering_enabled);
669
670         __sync_synchronize();
671         if (tethering_enabled > 0) {
672                 if (tethering_dhcp_server)
673                         dhcp_server_stop(tethering_dhcp_server);
674                 __connman_bridge_disable(BRIDGE_NAME);
675                 __connman_bridge_remove(BRIDGE_NAME);
676                 __connman_nat_disable(BRIDGE_NAME);
677         }
678
679         if (!connection)
680                 return;
681
682         g_hash_table_destroy(pn_hash);
683
684         g_hash_table_destroy(clients_notify->remove);
685         g_free(clients_notify);
686         clients_notify = NULL;
687
688         g_hash_table_destroy(clients_table);
689         clients_table = NULL;
690
691         dbus_connection_unref(connection);
692 }