X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Fethernet.c;h=2a91e2f32f6a7a884b187861e9da3a0f6b027f03;hb=23af53cf192b6f0b4faccac2883dbf1826585c01;hp=d176508d80849dc38543315c18f52955b89b5894;hpb=22633ced6225d294ce8483efbf2b39ea0c0c1b65;p=platform%2Fupstream%2Fconnman.git diff --git a/plugins/ethernet.c b/plugins/ethernet.c index d176508..2a91e2f 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -27,11 +27,13 @@ #include #include #include +#include #include #include #include #include +#include #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 @@ -47,6 +49,14 @@ #include #include #include +#if defined TIZEN_EXT_WIFI_MESH +#include +#endif + +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +#include +#include +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ static bool eth_tethering = false; @@ -55,6 +65,9 @@ struct ethernet_data { unsigned flags; unsigned int watch; struct connman_network *network; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + GSupplicantInterface *interface; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ }; @@ -83,6 +96,48 @@ static int get_vlan_vid(const char *ifname) return vid; } +static int get_dsa_port(const char *ifname) +{ + int sk; + int dsaport = -1; + struct ifreq ifr; + struct ethtool_cmd cmd; + struct ethtool_drvinfo drvinfocmd; + struct vlan_ioctl_args vifr; + + sk = socket(AF_INET, SOCK_STREAM, 0); + if (sk < 0) + return -errno; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + + /* check if it is a vlan and get physical interface name*/ + vifr.cmd = GET_VLAN_REALDEV_NAME_CMD; + strncpy(vifr.device1, ifname, sizeof(vifr.device1)); + + if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0) + strncpy(ifr.ifr_name, vifr.u.device2, sizeof(ifr.ifr_name)); + + /* get driver info */ + drvinfocmd.cmd = ETHTOOL_GDRVINFO; + ifr.ifr_data = (caddr_t)&drvinfocmd; + + if (!ioctl(sk, SIOCETHTOOL, &ifr)) { + if(!strcmp(drvinfocmd.driver, "dsa")) { + /* get dsa port*/ + cmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = (caddr_t)&cmd; + + if (!ioctl(sk, SIOCETHTOOL, &ifr)) + dsaport = cmd.phy_address; + } + } + close(sk); + + return dsaport; +} + static int eth_network_probe(struct connman_network *network) { DBG("network %p", network); @@ -95,6 +150,133 @@ static void eth_network_remove(struct connman_network *network) DBG("network %p", network); } +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +static struct connman_network *g_network = NULL; + +void handle_eap_signal(GSupplicantInterface *interface, bool status) +{ + DBG("captured EAP signal"); + + if (!g_network) + return; + + if (g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; + + if (!connman_network_check_validity(g_network)) + return; + + DBG("network is valid"); + + g_supplicant_unregister_eap_callback(); + + if (!status) { + // Should we mark service as non favorite or make autoconnect as false? + + struct ethernet_data *ethernet = g_supplicant_interface_get_data(interface); + if (ethernet && ethernet->interface) { + g_supplicant_interface_remove(ethernet->interface, NULL, NULL); + ethernet->interface = NULL; + } + + connman_network_set_error(g_network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + g_network = NULL; + return; + } + + connman_network_set_connected(g_network, status); + g_network = NULL; +} + +static void interface_create_callback(int result, + GSupplicantInterface *interface, void *user_data) +{ + struct ethernet_data *ethernet = user_data; + + if (result < 0 || !interface || !ethernet) + return; + + DBG("result %d ifname %s, ethernet %p", result, + g_supplicant_interface_get_ifname(interface), + ethernet); + + ethernet->interface = interface; + g_supplicant_interface_set_data(interface, ethernet); +} + +static int eth_network_connect(struct connman_network *network) +{ + DBG("network %p", network); + + struct connman_service *service = connman_service_lookup_from_network(network); + + if (service && __connman_service_get_use_eapol(service)) { + struct connman_device *device = connman_network_get_device(network); + struct ethernet_data *ethernet = connman_device_get_data(device); + const char *driver = "wired"; + int index = connman_network_get_index(network); + char *ifname = connman_inet_ifname(index);; + char *config_file = NULL; + + g_supplicant_register_eap_callback(handle_eap_signal); + g_network = network; + + if (asprintf(&config_file, "/opt/usr/data/network/%s-eapol.conf", ifname) < 0) { + g_free(ifname); + return -ENOMEM; + } + + DBG("config_file %s", config_file); + + g_supplicant_replace_config_file(ifname, config_file); + free(config_file); + + /* + * TODO: RemoveInterface if already present because + * already created interface will not start EAP handshake. + */ + g_supplicant_interface_create(ifname, driver, NULL, + interface_create_callback, ethernet); + + g_free(ifname); + + return 0; + } + + connman_network_set_connected(network, true); + + return 0; +} + +static int eth_network_disconnect(struct connman_network *network) +{ + DBG("network %p", network); + + struct connman_service *service = connman_service_lookup_from_network(network); + + if (service && __connman_service_get_use_eapol(service)) { + struct connman_device *device = connman_network_get_device(network); + struct ethernet_data *ethernet = connman_device_get_data(device); + + g_network = NULL; + g_supplicant_unregister_eap_callback(); + if (ethernet && ethernet->interface) { + g_supplicant_interface_remove(ethernet->interface, NULL, NULL); + ethernet->interface = NULL; + } + connman_network_set_associating(network, false); + connman_network_set_connected(network, false); + + return 0; + } + + connman_network_set_connected(network, false); + + return 0; +} + +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + static int eth_network_connect(struct connman_network *network) { DBG("network %p", network); @@ -113,6 +295,8 @@ static int eth_network_disconnect(struct connman_network *network) return 0; } +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + static struct connman_network_driver eth_network_driver = { .name = "cable", .type = CONNMAN_NETWORK_TYPE_ETHERNET, @@ -126,7 +310,7 @@ static void add_network(struct connman_device *device, struct ethernet_data *ethernet) { struct connman_network *network; - int index, vid; + int index; char *ifname; network = connman_network_create("carrier", @@ -139,24 +323,33 @@ static void add_network(struct connman_device *device, ifname = connman_inet_ifname(index); if (!ifname) return; - vid = get_vlan_vid(ifname); connman_network_set_name(network, "Wired"); if (connman_device_add_network(device, network) < 0) { connman_network_unref(network); + g_free(ifname); return; } if (!eth_tethering) { - char group[10] = "cable"; + char group[25] = "cable"; + int vid, dsaport; + + vid = get_vlan_vid(ifname); + dsaport = get_dsa_port(ifname); + /* * Prevent service from starting the reconnect * procedure as we do not want the DHCP client * to run when tethering. */ - if (vid >= 0) + if((vid >= 0) && (dsaport >= 0)) + snprintf(group, sizeof(group), "p%02x_%03x_cable", dsaport, vid); + else if (vid >= 0) snprintf(group, sizeof(group), "%03x_cable", vid); + else if (dsaport >= 0) + snprintf(group, sizeof(group), "p%02x_cable", dsaport); connman_network_set_group(network, group); } @@ -201,6 +394,10 @@ static void ethernet_newlink(unsigned flags, unsigned change, void *user_data) } else { DBG("carrier off"); remove_network(device, ethernet); +#if defined TIZEN_EXT_WIFI_MESH + /* Remove ethernet from mesh bridge */ + __connman_mesh_remove_ethernet_from_bridge(); +#endif } } @@ -221,6 +418,9 @@ static int eth_dev_probe(struct connman_device *device) ethernet->index = connman_device_get_index(device); ethernet->flags = 0; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + ethernet->interface = NULL; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ ethernet->watch = connman_rtnl_add_newlink_watch(ethernet->index, ethernet_newlink, device); @@ -236,6 +436,16 @@ static void eth_dev_remove(struct connman_device *device) connman_device_set_data(device, NULL); +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + if (!ethernet) + return; + + if (ethernet->interface) { + g_supplicant_interface_remove(ethernet->interface, NULL, NULL); + ethernet->interface = NULL; + } +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + connman_rtnl_remove_watch(ethernet->watch); remove_network(device, ethernet); @@ -379,6 +589,54 @@ static struct connman_technology_driver eth_tech_driver = { .set_tethering = eth_tech_set_tethering, }; +#if defined TIZEN_EXT_WIFI_MESH +static int eth_mesh_add_to_bridge(const char *bridge) +{ + GList *list; + struct ethernet_data *ethernet; + + DBG("Add ethernet to bridge %s", bridge); + + 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) { + ethernet = connman_device_get_data(device); + if (ethernet) + remove_network(device, ethernet); + } + + connman_inet_ifup(index); + + connman_inet_add_to_bridge(index, bridge); + } + + return 0; +} + +static int eth_mesh_remove_from_bridge(const char *bridge) +{ + GList *list; + + DBG("Remove ethernet from bridge %s", bridge); + + for (list = eth_interface_list; list; list = list->next) { + int index = GPOINTER_TO_INT(list->data); + + connman_inet_remove_from_bridge(index, bridge); + } + + return 0; +} + +static struct connman_mesh_eth_driver eth_mesh_driver = { + .add_to_bridge = eth_mesh_add_to_bridge, + .remove_from_bridge = eth_mesh_remove_from_bridge, +}; +#endif + static int ethernet_init(void) { int err; @@ -387,6 +645,12 @@ static int ethernet_init(void) if (err < 0) return err; +#if defined TIZEN_EXT_WIFI_MESH + err = connman_mesh_eth_driver_register(ð_mesh_driver); + if (err < 0) + return err; +#endif + err = connman_network_driver_register(ð_network_driver); if (err < 0) return err; @@ -404,6 +668,10 @@ static void ethernet_exit(void) { connman_technology_driver_unregister(ð_tech_driver); +#if defined TIZEN_EXT_WIFI_MESH + connman_mesh_eth_driver_unregister(ð_mesh_driver); +#endif + connman_network_driver_unregister(ð_network_driver); connman_device_driver_unregister(ð_dev_driver);