From aa939f614bab24c96bf1df784efcee5bcd80cbf9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 25 Apr 2013 14:47:51 +0300 Subject: [PATCH] ethernet: Add tethering support --- include/technology.h | 1 + plugins/ethernet.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/technology.c | 31 ++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/include/technology.h b/include/technology.h index 71314f2..9fe994c 100644 --- a/include/technology.h +++ b/include/technology.h @@ -44,6 +44,7 @@ void connman_technology_regdom_notify(struct connman_technology *technology, connman_bool_t connman_technology_get_wifi_tethering(const char **ssid, const char **psk); +connman_bool_t connman_technology_is_tethering_allowed(enum connman_service_type type); struct connman_technology_driver { const char *name; diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 6a20eb2..bafc75d 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -39,6 +39,9 @@ #include #include #include +#include + +static connman_bool_t eth_tethering = FALSE; struct ethernet_data { int index; @@ -107,7 +110,13 @@ static void add_network(struct connman_device *device, return; } - connman_network_set_group(network, "cable"); + if (eth_tethering == FALSE) + /* + * Prevent service from starting the reconnect + * procedure as we do not want the DHCP client + * to run when tethering. + */ + connman_network_set_group(network, "cable"); ethernet->network = network; } @@ -319,11 +328,102 @@ static void eth_remove(struct connman_technology *technology) DBG(""); } +static GList *eth_interface_list = NULL; + +static void eth_add_interface(struct connman_technology *technology, + int index, const char *name, const char *ident) +{ + DBG("index %d name %s ident %s", index, name, ident); + + if (g_list_find(eth_interface_list, + GINT_TO_POINTER((int) index)) != NULL) + return; + + eth_interface_list = g_list_prepend(eth_interface_list, + (GINT_TO_POINTER((int) index))); +} + +static void eth_remove_interface(struct connman_technology *technology, + int index) +{ + DBG("index %d", index); + + eth_interface_list = g_list_remove(eth_interface_list, + GINT_TO_POINTER((int) index)); +} + +static void eth_enable_tethering(struct connman_technology *technology, + const char *bridge) +{ + GList *list; + + for (list = eth_interface_list; list; list = list->next) { + int index = GPOINTER_TO_INT(list->data); + struct connman_device *device = + connman_device_find_by_index(index); + + if (device != NULL) + connman_device_disconnect_service(device); + + connman_technology_tethering_notify(technology, TRUE); + + connman_inet_ifup(index); + + connman_inet_add_to_bridge(index, bridge); + + eth_tethering = TRUE; + } +} + +static void eth_disable_tethering(struct connman_technology *technology, + const char *bridge) +{ + GList *list; + + for (list = eth_interface_list; list; list = list->next) { + int index = GPOINTER_TO_INT(list->data); + struct connman_device *device = + connman_device_find_by_index(index); + + connman_inet_remove_from_bridge(index, bridge); + + connman_inet_ifdown(index); + + connman_technology_tethering_notify(technology, FALSE); + + if (device != NULL) + connman_device_reconnect_service(device); + + eth_tethering = FALSE; + } +} + +static int eth_set_tethering(struct connman_technology *technology, + const char *identifier, const char *passphrase, + const char *bridge, connman_bool_t enabled) +{ + if (connman_technology_is_tethering_allowed( + CONNMAN_SERVICE_TYPE_ETHERNET) == FALSE) + return 0; + + DBG("bridge %s enabled %d", bridge, enabled); + + if (enabled) + eth_enable_tethering(technology, bridge); + else + eth_disable_tethering(technology, bridge); + + return 0; +} + static struct connman_technology_driver eth_driver = { .name = "ethernet", .type = CONNMAN_SERVICE_TYPE_ETHERNET, .probe = eth_probe, .remove = eth_remove, + .add_interface = eth_add_interface, + .remove_interface = eth_remove_interface, + .set_tethering = eth_set_tethering, }; static int ethernet_init(void) diff --git a/src/technology.c b/src/technology.c index f15fbd9..6e21b4b 100644 --- a/src/technology.c +++ b/src/technology.c @@ -99,6 +99,30 @@ static void rfkill_check(gpointer key, gpointer value, gpointer user_data) rfkill->softblock, rfkill->hardblock); } +connman_bool_t +connman_technology_is_tethering_allowed(enum connman_service_type type) +{ + static char *allowed_default[] = { "wifi", "bluetooth", "gadget", + NULL }; + const char *type_str = __connman_service_type2string(type); + char **allowed; + int i; + + if (type_str == NULL) + return FALSE; + + allowed = connman_setting_get_string_list("AllowedTetheringTechnologies"); + if (allowed == NULL) + allowed = allowed_default; + + for (i = 0; allowed[i] != NULL; i++) { + if (g_strcmp0(allowed[i], type_str) == 0) + return TRUE; + } + + return FALSE; +} + /** * connman_technology_driver_register: * @driver: Technology driver definition @@ -787,6 +811,13 @@ static DBusMessage *set_property(DBusConnection *conn, if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); + if (connman_technology_is_tethering_allowed(technology->type) + == FALSE) { + DBG("%s tethering not allowed by config file", + __connman_service_type2string(technology->type)); + return __connman_error_not_supported(msg); + } + dbus_message_iter_get_basic(&value, &tethering); if (technology->tethering == tethering) { -- 2.7.4