summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2013-04-25 14:47:51 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2013-04-26 12:33:58 +0300
commitaa939f614bab24c96bf1df784efcee5bcd80cbf9 (patch)
tree7cd23c12d3062f0cd09a72dd348309083056a01b
parentd1ae988ca517c82a7345b8147b651866ca6df527 (diff)
downloadconnman-aa939f614bab24c96bf1df784efcee5bcd80cbf9.tar.gz
connman-aa939f614bab24c96bf1df784efcee5bcd80cbf9.tar.bz2
connman-aa939f614bab24c96bf1df784efcee5bcd80cbf9.zip
ethernet: Add tethering support
-rw-r--r--include/technology.h1
-rw-r--r--plugins/ethernet.c102
-rw-r--r--src/technology.c31
3 files changed, 133 insertions, 1 deletions
diff --git a/include/technology.h b/include/technology.h
index 71314f27..9fe994cd 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 6a20eb29..bafc75dd 100644
--- a/plugins/ethernet.c
+++ b/plugins/ethernet.c
@@ -39,6 +39,9 @@
#include <connman/inet.h>
#include <connman/rtnl.h>
#include <connman/log.h>
+#include <connman/setting.h>
+
+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 f15fbd93..6e21b4b5 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) {