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 char *default_interface = NULL;
45 static volatile gint tethering_enabled;
46 static GDHCPServer *tethering_dhcp_server = NULL;
48 const char *__connman_tethering_get_bridge(void)
53 static void dhcp_server_debug(const char *str, void *data)
55 connman_info("%s: %s\n", (const char *) data, str);
58 static void dhcp_server_error(GDHCPServerError error)
61 case G_DHCP_SERVER_ERROR_NONE:
64 case G_DHCP_SERVER_ERROR_INTERFACE_UNAVAILABLE:
65 connman_error("Interface unavailable");
67 case G_DHCP_SERVER_ERROR_INTERFACE_IN_USE:
68 connman_error("Interface in use");
70 case G_DHCP_SERVER_ERROR_INTERFACE_DOWN:
71 connman_error("Interface down");
73 case G_DHCP_SERVER_ERROR_NOMEM:
74 connman_error("No memory");
76 case G_DHCP_SERVER_ERROR_INVALID_INDEX:
77 connman_error("Invalid index");
79 case G_DHCP_SERVER_ERROR_INVALID_OPTION:
80 connman_error("Invalid option");
82 case G_DHCP_SERVER_ERROR_IP_ADDRESS_INVALID:
83 connman_error("Invalid address");
88 static GDHCPServer *dhcp_server_start(const char *bridge,
89 const char *router, const char* subnet,
90 const char *start_ip, const char *end_ip,
91 unsigned int lease_time, const char *dns)
93 GDHCPServerError error;
94 GDHCPServer *dhcp_server;
99 index = connman_inet_ifindex(bridge);
103 dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &error);
104 if (dhcp_server == NULL) {
105 dhcp_server_error(error);
109 g_dhcp_server_set_debug(dhcp_server, dhcp_server_debug, "DHCP server");
111 g_dhcp_server_set_lease_time(dhcp_server, lease_time);
112 g_dhcp_server_set_option(dhcp_server, G_DHCP_SUBNET, subnet);
113 g_dhcp_server_set_option(dhcp_server, G_DHCP_ROUTER, router);
114 g_dhcp_server_set_option(dhcp_server, G_DHCP_DNS_SERVER, dns);
115 g_dhcp_server_set_ip_range(dhcp_server, start_ip, end_ip);
117 g_dhcp_server_start(dhcp_server);
122 static void dhcp_server_stop(GDHCPServer *server)
127 g_dhcp_server_unref(server);
130 static int set_forward_delay(const char *name, unsigned int delay)
133 char *forward_delay_path;
136 g_strdup_printf("/sys/class/net/%s/bridge/forward_delay", name);
138 if (forward_delay_path == NULL)
141 f = fopen(forward_delay_path, "r+");
143 g_free(forward_delay_path);
148 fprintf(f, "%d", delay);
155 static int create_bridge(const char *name)
159 DBG("name %s", name);
161 sk = socket(AF_INET, SOCK_STREAM, 0);
165 err = ioctl(sk, SIOCBRADDBR, name);
170 err = set_forward_delay(name, 0);
173 ioctl(sk, SIOCBRDELBR, name);
180 static int remove_bridge(const char *name)
184 DBG("name %s", name);
186 sk = socket(AF_INET, SOCK_STREAM, 0);
190 err = ioctl(sk, SIOCBRDELBR, name);
200 static int enable_bridge(const char *name)
204 index = connman_inet_ifindex(name);
208 err = __connman_inet_modify_address(RTM_NEWADDR,
209 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
210 BRIDGE_IP, NULL, 24, BRIDGE_BCAST);
214 return connman_inet_ifup(index);
217 static int disable_bridge(const char *name)
221 index = connman_inet_ifindex(name);
225 return connman_inet_ifdown(index);
228 static int enable_ip_forward(connman_bool_t enable)
233 f = fopen("/proc/sys/net/ipv4/ip_forward", "r+");
247 static int enable_nat(const char *interface)
251 if (interface == NULL)
254 /* Enable IPv4 forwarding */
255 err = enable_ip_forward(TRUE);
259 /* POSTROUTING flush */
260 err = __connman_iptables_command("-t nat -F POSTROUTING");
264 /* Enable masquerading */
265 err = __connman_iptables_command("-t nat -A POSTROUTING "
266 "-o %s -j MASQUERADE", interface);
270 return __connman_iptables_commit("nat");
273 static void disable_nat(const char *interface)
277 /* Disable IPv4 forwarding */
278 enable_ip_forward(FALSE);
280 /* POSTROUTING flush */
281 err = __connman_iptables_command("-t nat -F POSTROUTING");
285 __connman_iptables_commit("nat");
288 void __connman_tethering_set_enabled(void)
292 DBG("enabled %d", tethering_enabled + 1);
294 if (g_atomic_int_exchange_and_add(&tethering_enabled, 1) == 0) {
295 err = create_bridge(BRIDGE_NAME);
299 err = enable_bridge(BRIDGE_NAME);
301 remove_bridge(BRIDGE_NAME);
305 tethering_dhcp_server =
306 dhcp_server_start(BRIDGE_NAME,
307 BRIDGE_IP, BRIDGE_SUBNET,
308 BRIDGE_IP_START, BRIDGE_IP_END,
309 24 * 3600, BRIDGE_DNS);
310 if (tethering_dhcp_server == NULL) {
311 disable_bridge(BRIDGE_NAME);
312 remove_bridge(BRIDGE_NAME);
316 enable_nat(default_interface);
318 DBG("tethering started");
322 void __connman_tethering_set_disabled(void)
324 DBG("enabled %d", tethering_enabled - 1);
326 if (g_atomic_int_dec_and_test(&tethering_enabled) == TRUE) {
327 disable_nat(default_interface);
329 dhcp_server_stop(tethering_dhcp_server);
331 disable_bridge(BRIDGE_NAME);
333 remove_bridge(BRIDGE_NAME);
335 DBG("tethering stopped");
339 void __connman_tethering_update_interface(const char *interface)
341 DBG("interface %s", interface);
343 g_free(default_interface);
345 if (interface == NULL) {
346 disable_nat(interface);
347 default_interface = NULL;
352 default_interface = g_strdup(interface);
354 if (!g_atomic_int_get(&tethering_enabled))
357 enable_nat(interface);
360 int __connman_tethering_init(void)
364 tethering_enabled = 0;
369 void __connman_tethering_cleanup(void)
373 if (g_atomic_int_get(&tethering_enabled)) {
374 if (tethering_dhcp_server)
375 dhcp_server_stop(tethering_dhcp_server);
376 disable_bridge(BRIDGE_NAME);
377 remove_bridge(BRIDGE_NAME);