5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <sys/ioctl.h>
30 #include <linux/sockios.h>
34 #include <gdhcp/gdhcp.h>
36 #define BRIDGE_NAME "tether"
37 #define BRIDGE_IP "192.168.218.1"
38 #define BRIDGE_BCAST "192.168.218.255"
39 #define BRIDGE_SUBNET "255.255.255.0"
40 #define BRIDGE_IP_START "192.168.218.100"
41 #define BRIDGE_IP_END "192.168.218.200"
42 #define BRIDGE_DNS "8.8.8.8"
44 static connman_bool_t tethering_status = FALSE;
45 static char *default_interface = NULL;
46 static volatile gint tethering_enabled;
47 static GDHCPServer *tethering_dhcp_server = NULL;
49 connman_bool_t __connman_tethering_get_status(void)
51 return tethering_status;
55 static void dhcp_server_debug(const char *str, void *data)
57 connman_info("%s: %s\n", (const char *) data, str);
60 static void dhcp_server_error(GDHCPServerError error)
63 case G_DHCP_SERVER_ERROR_NONE:
66 case G_DHCP_SERVER_ERROR_INTERFACE_UNAVAILABLE:
67 connman_error("Interface unavailable");
69 case G_DHCP_SERVER_ERROR_INTERFACE_IN_USE:
70 connman_error("Interface in use");
72 case G_DHCP_SERVER_ERROR_INTERFACE_DOWN:
73 connman_error("Interface down");
75 case G_DHCP_SERVER_ERROR_NOMEM:
76 connman_error("No memory");
78 case G_DHCP_SERVER_ERROR_INVALID_INDEX:
79 connman_error("Invalid index");
81 case G_DHCP_SERVER_ERROR_INVALID_OPTION:
82 connman_error("Invalid option");
84 case G_DHCP_SERVER_ERROR_IP_ADDRESS_INVALID:
85 connman_error("Invalid address");
90 static GDHCPServer *dhcp_server_start(const char *bridge,
91 const char *router, const char* subnet,
92 const char *start_ip, const char *end_ip,
93 unsigned int lease_time, const char *dns)
95 GDHCPServerError error;
96 GDHCPServer *dhcp_server;
101 index = connman_inet_ifindex(bridge);
105 dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &error);
106 if (dhcp_server == NULL) {
107 dhcp_server_error(error);
111 g_dhcp_server_set_debug(dhcp_server, dhcp_server_debug, "DHCP server");
113 g_dhcp_server_set_lease_time(dhcp_server, lease_time);
114 g_dhcp_server_set_option(dhcp_server, G_DHCP_SUBNET, subnet);
115 g_dhcp_server_set_option(dhcp_server, G_DHCP_ROUTER, router);
116 g_dhcp_server_set_option(dhcp_server, G_DHCP_DNS_SERVER, dns);
117 g_dhcp_server_set_ip_range(dhcp_server, start_ip, end_ip);
119 g_dhcp_server_start(dhcp_server);
124 static void dhcp_server_stop(GDHCPServer *server)
129 g_dhcp_server_unref(server);
132 static int set_forward_delay(const char *name, unsigned int delay)
135 char *forward_delay_path;
138 g_strdup_printf("/sys/class/net/%s/bridge/forward_delay", name);
140 if (forward_delay_path == NULL)
143 f = fopen(forward_delay_path, "r+");
145 g_free(forward_delay_path);
150 fprintf(f, "%d", delay);
157 static int create_bridge(const char *name)
161 DBG("name %s", name);
163 sk = socket(AF_INET, SOCK_STREAM, 0);
167 err = ioctl(sk, SIOCBRADDBR, name);
172 err = set_forward_delay(name, 0);
175 ioctl(sk, SIOCBRDELBR, name);
182 static int remove_bridge(const char *name)
186 DBG("name %s", name);
188 sk = socket(AF_INET, SOCK_STREAM, 0);
192 err = ioctl(sk, SIOCBRDELBR, name);
202 static int enable_bridge(const char *name)
206 index = connman_inet_ifindex(name);
210 err = __connman_inet_modify_address(RTM_NEWADDR,
211 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
212 BRIDGE_IP, NULL, 24, BRIDGE_BCAST);
216 return connman_inet_ifup(index);
219 static int disable_bridge(const char *name)
223 index = connman_inet_ifindex(name);
227 return connman_inet_ifdown(index);
230 static int enable_ip_forward(connman_bool_t enable)
235 f = fopen("/proc/sys/net/ipv4/ip_forward", "r+");
249 static int enable_nat(const char *interface)
253 if (interface == NULL)
256 /* Enable IPv4 forwarding */
257 err = enable_ip_forward(TRUE);
261 /* POSTROUTING flush */
262 err = __connman_iptables_command("-t nat -F POSTROUTING");
266 /* Enable masquerading */
267 err = __connman_iptables_command("-t nat -A POSTROUTING "
268 "-o %s -j MASQUERADE", interface);
272 return __connman_iptables_commit("nat");
275 static void disable_nat(const char *interface)
279 /* Disable IPv4 forwarding */
280 enable_ip_forward(FALSE);
282 /* POSTROUTING flush */
283 err = __connman_iptables_command("-t nat -F POSTROUTING");
287 __connman_iptables_commit("nat");
290 void __connman_tethering_set_enabled(void)
294 if (tethering_status == FALSE)
297 DBG("enabled %d", tethering_enabled + 1);
299 if (g_atomic_int_exchange_and_add(&tethering_enabled, 1) == 0) {
300 err = create_bridge(BRIDGE_NAME);
304 err = enable_bridge(BRIDGE_NAME);
306 remove_bridge(BRIDGE_NAME);
310 tethering_dhcp_server =
311 dhcp_server_start(BRIDGE_NAME,
312 BRIDGE_IP, BRIDGE_SUBNET,
313 BRIDGE_IP_START, BRIDGE_IP_END,
314 24 * 3600, BRIDGE_DNS);
315 if (tethering_dhcp_server == NULL) {
316 disable_bridge(BRIDGE_NAME);
317 remove_bridge(BRIDGE_NAME);
321 enable_nat(default_interface);
323 DBG("tethering started");
327 void __connman_tethering_set_disabled(void)
329 if (tethering_status == TRUE)
332 DBG("enabled %d", tethering_enabled - 1);
334 if (g_atomic_int_dec_and_test(&tethering_enabled) == TRUE) {
335 disable_nat(default_interface);
337 dhcp_server_stop(tethering_dhcp_server);
339 disable_bridge(BRIDGE_NAME);
341 remove_bridge(BRIDGE_NAME);
343 DBG("tethering stopped");
347 int __connman_tethering_set_status(connman_bool_t status)
349 if (status == tethering_status)
352 tethering_status = status;
355 __connman_technology_enable_tethering(BRIDGE_NAME);
357 __connman_technology_disable_tethering(BRIDGE_NAME);
362 void __connman_tethering_update_interface(const char *interface)
364 DBG("interface %s", interface);
366 g_free(default_interface);
368 if (interface == NULL) {
369 disable_nat(interface);
370 default_interface = NULL;
375 default_interface = g_strdup(interface);
377 if (tethering_status == FALSE ||
378 !g_atomic_int_get(&tethering_enabled))
381 enable_nat(interface);
384 int __connman_tethering_init(void)
388 tethering_enabled = 0;
393 void __connman_tethering_cleanup(void)
397 if (tethering_status == TRUE) {
398 if (tethering_dhcp_server)
399 dhcp_server_stop(tethering_dhcp_server);
400 disable_bridge(BRIDGE_NAME);
401 remove_bridge(BRIDGE_NAME);