From 1e09c28c8e398c349b7cdf2c802a1bae71bbb996 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 16 Sep 2010 00:21:23 +0200 Subject: [PATCH 3/5] Move current wifi plugin to legacy The current wifi plugin is replaced by the new API one and is renamed to wifi-legacy.c. --- Makefile.plugins | 16 ++- plugins/wifi-legacy.c | 237 ++++++++++++++++++++++++ plugins/wifi.c | 485 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 685 insertions(+), 53 deletions(-) create mode 100644 plugins/wifi-legacy.c diff --git a/Makefile.plugins b/Makefile.plugins index 5ce6c52..ce45014 100644 --- a/Makefile.plugins +++ b/Makefile.plugins @@ -34,14 +34,24 @@ endif if WIFI if WIFI_BUILTIN builtin_modules += wifi -builtin_sources += plugins/wifi.c plugins/supplicant.h plugins/supplicant.c +builtin_sources += plugins/wifi.c +builtin_modules += wifi_legacy +builtin_sources += plugins/wifi-legacy.c \ + plugins/supplicant.h plugins/supplicant.c else plugin_LTLIBRARIES += plugins/wifi.la plugin_objects += $(plugins_wifi_la_OBJECTS) -plugins_wifi_la_SOURCES = plugins/wifi.c \ - plugins/supplicant.h plugins/supplicant.c +plugins_wifi_la_SOURCES = plugins/wifi.c plugins_wifi_la_CFLAGS = $(plugin_cflags) plugins_wifi_la_LDFLAGS = $(plugin_ldflags) + +plugin_LTLIBRARIES += plugins/wifi_legacy.la +plugin_objects += $(plugins_wifi_legacy_la_OBJECTS) +plugins_wifi_legacy_la_SOURCES = plugins/wifi-legacy.c \ + plugins/supplicant.h plugins/supplicant.c +plugins_wifi_legacy_la_CFLAGS = $(plugin_cflags) +plugins_wifi_legacy_la_LDFLAGS = $(plugin_ldflags) + endif endif diff --git a/plugins/wifi-legacy.c b/plugins/wifi-legacy.c new file mode 100644 index 0000000..eb7dd83 --- /dev/null +++ b/plugins/wifi-legacy.c @@ -0,0 +1,237 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifndef IFF_LOWER_UP +#define IFF_LOWER_UP 0x10000 +#endif + +#include +#include + +#define CONNMAN_API_SUBJECT_TO_CHANGE +#include +#include +#include +#include + +#include "supplicant.h" + +#define CLEANUP_TIMEOUT 8 /* in seconds */ +#define INACTIVE_TIMEOUT 12 /* in seconds */ + +struct wifi_data { + char *identifier; + connman_bool_t connected; + int index; + unsigned flags; + unsigned int watch; +}; + +static int network_probe(struct connman_network *network) +{ + DBG("network %p", network); + + return 0; +} + +static void network_remove(struct connman_network *network) +{ + DBG("network %p", network); +} + +static int network_connect(struct connman_network *network) +{ + DBG("network %p", network); + + return supplicant_connect(network); +} + +static int network_disconnect(struct connman_network *network) +{ + DBG("network %p", network); + + return supplicant_disconnect(network); +} + +static struct connman_network_driver network_driver = { + .name = "wifi", + .type = CONNMAN_NETWORK_TYPE_WIFI, + .probe = network_probe, + .remove = network_remove, + .connect = network_connect, + .disconnect = network_disconnect, +}; + +static void wifi_newlink(unsigned flags, unsigned change, void *user_data) +{ + struct connman_device *device = user_data; + struct wifi_data *wifi = connman_device_get_data(device); + + DBG("index %d flags %d change %d", wifi->index, flags, change); + + if (!change) + return; + + if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) { + if (flags & IFF_UP) { + DBG("interface up"); + } else { + DBG("interface down"); + } + } + + if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) { + if (flags & IFF_LOWER_UP) { + DBG("carrier on"); + } else { + DBG("carrier off"); + } + } + + wifi->flags = flags; +} + +static int wifi_probe(struct connman_device *device) +{ + struct wifi_data *wifi; + + DBG("device %p", device); + + wifi = g_try_new0(struct wifi_data, 1); + if (wifi == NULL) + return -ENOMEM; + + wifi->connected = FALSE; + + connman_device_set_data(device, wifi); + + wifi->index = connman_device_get_index(device); + wifi->flags = 0; + + wifi->watch = connman_rtnl_add_newlink_watch(wifi->index, + wifi_newlink, device); + + return 0; +} + +static void wifi_remove(struct connman_device *device) +{ + struct wifi_data *wifi = connman_device_get_data(device); + + DBG("device %p", device); + + connman_device_set_data(device, NULL); + + connman_rtnl_remove_watch(wifi->watch); + + g_free(wifi->identifier); + g_free(wifi); +} + +static int wifi_enable(struct connman_device *device) +{ + DBG("device %p", device); + + return supplicant_start(device); +} + +static int wifi_disable(struct connman_device *device) +{ + struct wifi_data *wifi = connman_device_get_data(device); + + DBG("device %p", device); + + wifi->connected = FALSE; + + return supplicant_stop(device); +} + +static int wifi_scan(struct connman_device *device) +{ + DBG("device %p", device); + + return supplicant_scan(device); +} + +static struct connman_device_driver wifi_driver = { + .name = "wifi", + .type = CONNMAN_DEVICE_TYPE_WIFI, + .probe = wifi_probe, + .remove = wifi_remove, + .enable = wifi_enable, + .disable = wifi_disable, + .scan = wifi_scan, +}; + +static void wifi_register(void) +{ + DBG(""); + + if (connman_device_driver_register(&wifi_driver) < 0) + connman_error("Failed to register WiFi driver"); +} + +static void wifi_unregister(void) +{ + DBG(""); + + connman_device_driver_unregister(&wifi_driver); +} + +static struct supplicant_driver supplicant = { + .name = "wifi", + .probe = wifi_register, + .remove = wifi_unregister, +}; + +static int wifi_init(void) +{ + int err; + + err = connman_network_driver_register(&network_driver); + if (err < 0) + return err; + + err = supplicant_register(&supplicant); + if (err < 0) { + connman_network_driver_unregister(&network_driver); + return err; + } + + return 0; +} + +static void wifi_exit(void) +{ + supplicant_unregister(&supplicant); + + connman_network_driver_unregister(&network_driver); +} + +CONNMAN_PLUGIN_DEFINE(wifi_legacy, "WiFi interface plugin", VERSION, + CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit) diff --git a/plugins/wifi.c b/plugins/wifi.c index 34c1634..8986233 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -23,8 +23,14 @@ #include #endif +#include #include -#include +#include +#include +#include +#include +#include +#include #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 @@ -35,58 +41,66 @@ #define CONNMAN_API_SUBJECT_TO_CHANGE #include +#include #include #include #include -#include "supplicant.h" +#include #define CLEANUP_TIMEOUT 8 /* in seconds */ #define INACTIVE_TIMEOUT 12 /* in seconds */ struct wifi_data { char *identifier; + struct connman_device *device; + struct connman_network *network; + GSupplicantInterface *interface; connman_bool_t connected; int index; unsigned flags; unsigned int watch; }; -static int network_probe(struct connman_network *network) +static int get_bssid(struct connman_device *device, + unsigned char *bssid, unsigned int *bssid_len) { - DBG("network %p", network); + struct iwreq wrq; + char *ifname; + int ifindex; + int fd, err; + + ifindex = connman_device_get_index(device); + if (ifindex < 0) + return -EINVAL; + + ifname = connman_inet_ifname(ifindex); + if (ifname == NULL) + return -EINVAL; + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + g_free(ifname); + return -EINVAL; + } - return 0; -} + memset(&wrq, 0, sizeof(wrq)); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); -static void network_remove(struct connman_network *network) -{ - DBG("network %p", network); -} + err = ioctl(fd, SIOCGIWAP, &wrq); -static int network_connect(struct connman_network *network) -{ - DBG("network %p", network); + g_free(ifname); + close(fd); - return supplicant_connect(network); -} + if (err < 0) + return -EIO; -static int network_disconnect(struct connman_network *network) -{ - DBG("network %p", network); + memcpy(bssid, wrq.u.ap_addr.sa_data, ETH_ALEN); + *bssid_len = ETH_ALEN; - return supplicant_disconnect(network); + return 0; } -static struct connman_network_driver network_driver = { - .name = "wifi", - .type = CONNMAN_NETWORK_TYPE_WIFI, - .probe = network_probe, - .remove = network_remove, - .connect = network_connect, - .disconnect = network_disconnect, -}; - static void wifi_newlink(unsigned flags, unsigned change, void *user_data) { struct connman_device *device = user_data; @@ -98,19 +112,17 @@ static void wifi_newlink(unsigned flags, unsigned change, void *user_data) return; if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) { - if (flags & IFF_UP) { + if (flags & IFF_UP) DBG("interface up"); - } else { + else DBG("interface down"); - } } if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) { - if (flags & IFF_LOWER_UP) { + if (flags & IFF_LOWER_UP) DBG("carrier on"); - } else { + else DBG("carrier off"); - } } wifi->flags = flags; @@ -129,6 +141,7 @@ static int wifi_probe(struct connman_device *device) wifi->connected = FALSE; connman_device_set_data(device, wifi); + wifi->device = connman_device_ref(device); wifi->index = connman_device_get_index(device); wifi->flags = 0; @@ -146,18 +159,54 @@ static void wifi_remove(struct connman_device *device) DBG("device %p", device); connman_device_set_data(device, NULL); - + connman_device_unref(wifi->device); connman_rtnl_remove_watch(wifi->watch); g_free(wifi->identifier); g_free(wifi); } +static void interface_create_callback(int result, + GSupplicantInterface *interface, + void *user_data) +{ + struct wifi_data *wifi = user_data; + + DBG("result %d ifname %s", result, + g_supplicant_interface_get_ifname(interface)); + + if (result < 0) + return; + + wifi->interface = interface; + g_supplicant_interface_set_data(interface, wifi); +} + +static void interface_remove_callback(int result, + GSupplicantInterface *interface, + void *user_data) +{ + struct wifi_data *wifi = user_data; + + DBG("result %d", result); + + if (result < 0) + return; + + wifi->interface = NULL; +} + + static int wifi_enable(struct connman_device *device) { - DBG("device %p", device); + struct wifi_data *wifi = connman_device_get_data(device); + const char *interface = connman_device_get_string(device, "Interface"); + + DBG("device %p %p", device, wifi); - return supplicant_start(device); + return g_supplicant_interface_create(interface, "nl80211,wext", + interface_create_callback, + wifi); } static int wifi_disable(struct connman_device *device) @@ -168,17 +217,37 @@ static int wifi_disable(struct connman_device *device) wifi->connected = FALSE; - return supplicant_stop(device); + return g_supplicant_interface_remove(wifi->interface, + interface_remove_callback, + wifi); +} + +static void scan_callback(int result, GSupplicantInterface *interface, + void *user_data) +{ + struct connman_device *device = user_data; + + DBG("result %d", result); + + if (result < 0) { + connman_device_set_scanning(device, FALSE); + return; + } + + connman_device_set_scanning(device, TRUE); } static int wifi_scan(struct connman_device *device) { - DBG("device %p", device); + struct wifi_data *wifi = connman_device_get_data(device); - return supplicant_scan(device); + DBG("device %p %p", device, wifi->interface); + + return g_supplicant_interface_scan(wifi->interface, scan_callback, + device); } -static struct connman_device_driver wifi_driver = { +static struct connman_device_driver wifi_ng_driver = { .name = "wifi", .type = CONNMAN_DEVICE_TYPE_WIFI, .probe = wifi_probe, @@ -188,25 +257,339 @@ static struct connman_device_driver wifi_driver = { .scan = wifi_scan, }; -static void wifi_register(void) +static void system_ready(void) { DBG(""); - if (connman_device_driver_register(&wifi_driver) < 0) + if (connman_device_driver_register(&wifi_ng_driver) < 0) connman_error("Failed to register WiFi driver"); } -static void wifi_unregister(void) +static void system_killed(void) { DBG(""); - connman_device_driver_unregister(&wifi_driver); + connman_device_driver_unregister(&wifi_ng_driver); +} + +static void interface_added(GSupplicantInterface *interface) +{ + const char *ifname = g_supplicant_interface_get_ifname(interface); + const char *driver = g_supplicant_interface_get_driver(interface); + struct wifi_data *wifi; + + wifi = (struct wifi_data *)g_supplicant_interface_get_data(interface); + + DBG("ifname %s driver %s wifi %p", ifname, driver, wifi); + + if (wifi == NULL || wifi->device == NULL) { + connman_error("Wrong wifi pointer"); + return; + } + + connman_device_set_powered(wifi->device, TRUE); + wifi_scan(wifi->device); +} + +static void interface_state(GSupplicantInterface *interface) +{ + struct connman_network *network; + struct connman_device *device; + struct wifi_data *wifi; + GSupplicantState state = g_supplicant_interface_get_state(interface); + unsigned char bssid[ETH_ALEN]; + unsigned int bssid_len; + + wifi = (struct wifi_data *) g_supplicant_interface_get_data(interface); + + DBG("wifi %p interface state %d", wifi, state); + + if (wifi == NULL) + return; + + network = wifi->network; + device = wifi->device; + + if (device == NULL || network == NULL) + return; + + switch (state) { + case G_SUPPLICANT_STATE_SCANNING: + connman_device_set_scanning(device, TRUE); + break; + + case G_SUPPLICANT_STATE_AUTHENTICATING: + case G_SUPPLICANT_STATE_ASSOCIATING: + connman_network_set_associating(network, TRUE); + break; + + case G_SUPPLICANT_STATE_COMPLETED: + /* reset scan trigger and schedule background scan */ + connman_device_schedule_scan(device); + + if (get_bssid(device, bssid, &bssid_len) == 0) + connman_network_set_address(network, + bssid, bssid_len); + connman_network_set_connected(network, TRUE); + break; + + case G_SUPPLICANT_STATE_DISCONNECTED: + connman_network_set_connected(network, FALSE); + break; + + case G_SUPPLICANT_STATE_INACTIVE: + break; + + case G_SUPPLICANT_STATE_UNKNOWN: + case G_SUPPLICANT_STATE_ASSOCIATED: + case G_SUPPLICANT_STATE_4WAY_HANDSHAKE: + case G_SUPPLICANT_STATE_GROUP_HANDSHAKE: + break; + } + + DBG("DONE"); +} + +static void interface_removed(GSupplicantInterface *interface) +{ + const char *ifname = g_supplicant_interface_get_ifname(interface); + struct wifi_data *wifi; + + DBG("ifname %s", ifname); + + wifi = (struct wifi_data *)g_supplicant_interface_get_data(interface); + + if (wifi == NULL || wifi->device == NULL) { + connman_error("Wrong wifi pointer"); + return; + } + + connman_device_set_powered(wifi->device, FALSE); } -static struct supplicant_driver supplicant = { +static void scan_started(GSupplicantInterface *interface) +{ + struct wifi_data *wifi; + + DBG(""); + + wifi = (struct wifi_data *)g_supplicant_interface_get_data(interface); + + if (wifi == NULL) + return; + + if (wifi->device) + connman_device_set_scanning(wifi->device, TRUE); +} + +static void scan_finished(GSupplicantInterface *interface) +{ + struct wifi_data *wifi; + + DBG(""); + + wifi = (struct wifi_data *)g_supplicant_interface_get_data(interface); + + if (wifi == NULL) + return; +} + +static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network) +{ + unsigned char strength; + + strength = 120 + g_supplicant_network_get_signal(supplicant_network); + if (strength > 100) + strength = 100; + + return strength; +} + +static void network_added(GSupplicantNetwork *supplicant_network) +{ + struct connman_network *network; + GSupplicantInterface *interface; + struct wifi_data *wifi; + const char *name, *path, *identifier, *mode, *security, *group; + unsigned char *ssid; + unsigned int ssid_len; + + DBG(""); + + interface = g_supplicant_network_get_interface(supplicant_network); + wifi = (struct wifi_data *) g_supplicant_interface_get_data(interface); + name = g_supplicant_network_get_name(supplicant_network); + path = g_supplicant_network_get_path(supplicant_network); + identifier = g_supplicant_network_get_identifier(supplicant_network); + mode = g_supplicant_network_get_mode(supplicant_network); + security = g_supplicant_network_get_security(supplicant_network); + group = g_supplicant_network_get_identifier(supplicant_network); + + if (wifi == NULL) + return; + + ssid = (unsigned char *)g_supplicant_network_get_ssid(supplicant_network, &ssid_len); + + network = connman_device_get_network(wifi->device, path); + + if (network == NULL) { + network = connman_network_create(identifier, + CONNMAN_NETWORK_TYPE_WIFI); + if (network == NULL) + return; + + connman_network_set_index(network, wifi->index); + + connman_network_set_protocol(network, + CONNMAN_NETWORK_PROTOCOL_IP); + + if (connman_device_add_network(wifi->device, network) < 0) { + connman_network_unref(network); + return; + } + } + + if (name != NULL && name[0] != '\0') + connman_network_set_name(network, name); + + connman_network_set_blob(network, "WiFi.SSID", + ssid, ssid_len); + connman_network_set_string(network, "WiFi.Mode", mode); + connman_network_set_string(network, "WiFi.Security", security); + connman_network_set_strength(network, + calculate_strength(supplicant_network)); + + connman_network_set_available(network, TRUE); + + if (ssid != NULL) + connman_network_set_group(network, group); +} + +static void network_removed(GSupplicantNetwork *network) +{ + const char *name = g_supplicant_network_get_name(network); + + DBG("* name %s", name); +} + +static const GSupplicantCallbacks callbacks = { + .system_ready = system_ready, + .system_killed = system_killed, + .interface_added = interface_added, + .interface_state = interface_state, + .interface_removed = interface_removed, + .scan_started = scan_started, + .scan_finished = scan_finished, + .network_added = network_added, + .network_removed = network_removed, +}; + + +static int network_probe(struct connman_network *network) +{ + DBG("network %p", network); + + return 0; +} + +static void network_remove(struct connman_network *network) +{ + DBG("network %p", network); +} + +static void connect_callback(int result, GSupplicantInterface *interface, + void *user_data) +{ + connman_error("%s", __func__); +} + +static void disconnect_callback(int result, GSupplicantInterface *interface, + void *user_data) +{ + struct wifi_data *wifi = user_data; + + if (result < 0) { + connman_error("%s", __func__); + return; + } + + connman_network_unref(wifi->network); + + wifi->network = NULL; +} + + +static GSupplicantSecurity network_security(const char *security) +{ + if (g_str_equal(security, "none") == TRUE) + return G_SUPPLICANT_SECURITY_NONE; + else if (g_str_equal(security, "wep") == TRUE) + return G_SUPPLICANT_SECURITY_WEP; + else if (g_str_equal(security, "psk") == TRUE) + return G_SUPPLICANT_SECURITY_PSK; + else if (g_str_equal(security, "wpa") == TRUE) + return G_SUPPLICANT_SECURITY_PSK; + else if (g_str_equal(security, "rsn") == TRUE) + return G_SUPPLICANT_SECURITY_PSK; + else if (g_str_equal(security, "ieee8021x") == TRUE) + return G_SUPPLICANT_SECURITY_IEEE8021X; + + return G_SUPPLICANT_SECURITY_UNKNOWN; +} + +static int network_connect(struct connman_network *network) +{ + struct connman_device *device = connman_network_get_device(network); + struct wifi_data *wifi; + GSupplicantInterface *interface; + GSupplicantSSID ssid; + const char *security; + + DBG("network %p", network); + + if (device == NULL) + return -ENODEV; + + wifi = connman_device_get_data(device); + if (wifi == NULL) + return -ENODEV; + + interface = wifi->interface; + + memset(&ssid, 0, sizeof(ssid)); + ssid.ssid = connman_network_get_blob(network, "WiFi.SSID", + &ssid.ssid_len); + security = connman_network_get_string(network, "WiFi.Security"); + ssid.security = network_security(security); + + wifi->network = connman_network_ref(network); + + return g_supplicant_interface_connect(interface, &ssid, + connect_callback, NULL); +} + +static int network_disconnect(struct connman_network *network) +{ + struct connman_device *device = connman_network_get_device(network); + struct wifi_data *wifi; + + DBG("network %p", network); + + wifi = connman_device_get_data(device); + if (wifi == NULL || wifi->interface == NULL) + return -ENODEV; + + return g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, wifi); +} + +static struct connman_network_driver network_driver = { .name = "wifi", - .probe = wifi_register, - .remove = wifi_unregister, + .type = CONNMAN_NETWORK_TYPE_WIFI, + .probe = network_probe, + .remove = network_remove, + .connect = network_connect, + .disconnect = network_disconnect, }; static int wifi_init(void) @@ -217,7 +600,7 @@ static int wifi_init(void) if (err < 0) return err; - err = supplicant_register(&supplicant); + err = g_supplicant_register(&callbacks); if (err < 0) { connman_network_driver_unregister(&network_driver); return err; @@ -228,7 +611,9 @@ static int wifi_init(void) static void wifi_exit(void) { - supplicant_unregister(&supplicant); + DBG(); + + g_supplicant_unregister(&callbacks); connman_network_driver_unregister(&network_driver); } -- 1.7.1