diff options
-rw-r--r-- | plugins/ethernet.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/plugins/ethernet.c b/plugins/ethernet.c index aa4edfae..01980152 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -25,6 +25,8 @@ #include <errno.h> #include <net/if.h> +#include <stdio.h> +#include <string.h> #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 @@ -299,6 +301,71 @@ static struct connman_device_driver gadget_driver = { }; static GList *cdc_interface_list = NULL; +static GHashTable *cdc_mac_hash = NULL; + +static void add_station(int index) +{ + char *path, line[128] = {'\0'}; + char *ifname = connman_inet_ifname(index); + char *mac; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf("/sys/class/usb_mode/%s/f_rndis/ethaddr", + ifname); + + f = fopen(path, "re"); + + g_free(ifname); + g_free(path); + + if (f == NULL) + return; + + if (fgets(line, sizeof(line), f) == NULL) { + fclose(f); + return; + } + + fclose(f); + + mac = g_ascii_strdown(line, strlen(line) - 1); + DBG("Add station %s in Technology %d", mac, + CONNMAN_SERVICE_TYPE_GADGET); + + g_hash_table_insert(cdc_mac_hash, GINT_TO_POINTER(index), + mac); + + connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_GADGET, + mac); +} + +static void remove_station(int index) +{ + char *mac; + mac = g_hash_table_lookup(cdc_mac_hash, GINT_TO_POINTER(index)); + if (mac == NULL) + return; + + connman_technology_tethering_remove_station(mac); + + g_hash_table_remove(cdc_mac_hash, GINT_TO_POINTER(index)); +} + +static gboolean remove_all_station(gpointer key, gpointer value, gpointer user_data) +{ + char *mac; + mac = value; + if (mac == NULL) + return TRUE; + + connman_technology_tethering_remove_station(mac); + + return TRUE; +} + static void tech_add_interface(struct connman_technology *technology, int index, const char *name, const char *ident) @@ -320,6 +387,7 @@ static void tech_remove_interface(struct connman_technology *technology, cdc_interface_list = g_list_remove(cdc_interface_list, GINT_TO_POINTER((int) index)); + remove_station(index); } static void enable_tethering(struct connman_technology *technology, @@ -335,6 +403,8 @@ static void enable_tethering(struct connman_technology *technology, connman_inet_ifup(index); connman_inet_add_to_bridge(index, bridge); + + add_station(index); } } @@ -351,6 +421,8 @@ static void disable_tethering(struct connman_technology *technology, connman_inet_ifdown(index); connman_technology_tethering_notify(technology, FALSE); + + remove_station(index); } } @@ -371,14 +443,25 @@ static int tech_set_tethering(struct connman_technology *technology, static int tech_probe(struct connman_technology *technology) { + DBG("tech probe %p", technology); + cdc_mac_hash = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, g_free); return 0; } static void tech_remove(struct connman_technology *technology) { + DBG("tech remove %p", technology); g_list_free(cdc_interface_list); cdc_interface_list = NULL; + + if (cdc_mac_hash) { + g_hash_table_foreach_remove(cdc_mac_hash, remove_all_station, + NULL); + g_hash_table_destroy(cdc_mac_hash); + cdc_mac_hash = NULL; + } } static struct connman_technology_driver tech_driver = { |