Fix handling of strict-aliasing rules
[framework/connectivity/connman.git] / plugins / supplicant.c
index 6439667..958200e 100644 (file)
@@ -185,6 +185,7 @@ struct supplicant_task {
        gboolean noscan;
        GSList *scan_results;
        struct iw_range *range;
+       gboolean connecting;
        gboolean disconnecting;
 };
 
@@ -229,6 +230,75 @@ static struct supplicant_task *find_task_by_path(const char *path)
        return NULL;
 }
 
+static int get_range(struct supplicant_task *task)
+{
+       struct iwreq wrq;
+       int fd, err;
+
+       fd = socket(PF_INET, SOCK_DGRAM, 0);
+       if (fd < 0)
+               return -1;
+
+       memset(&wrq, 0, sizeof(struct iwreq));
+       strncpy(wrq.ifr_name, task->ifname, IFNAMSIZ);
+       wrq.u.data.pointer = task->range;
+       wrq.u.data.length = sizeof(struct iw_range);
+
+       err = ioctl(fd, SIOCGIWRANGE, &wrq);
+
+       close(fd);
+
+       return err;
+}
+
+static char *get_bssid(struct connman_device *device)
+{
+       char *bssid;
+       unsigned char ioctl_bssid[ETH_ALEN];
+       int ifindex;
+       char *ifname;
+       struct iwreq wrq;
+       int fd, err;
+
+       ifindex = connman_device_get_index(device);
+       if (ifindex < 0)
+               return NULL;
+
+       ifname = connman_inet_ifname(ifindex);
+       if (ifname == NULL)
+               return NULL;
+
+       fd = socket(PF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               g_free(ifname);
+               return NULL;
+       }
+
+       memset(&wrq, 0, sizeof(wrq));
+       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+
+       err = ioctl(fd, SIOCGIWAP, &wrq);
+
+       g_free(ifname);
+       close(fd);
+
+       if (err < 0)
+               return NULL;
+
+       memcpy(ioctl_bssid, wrq.u.ap_addr.sa_data, ETH_ALEN);
+
+       bssid = g_try_malloc0(13);
+       if (bssid == NULL)
+               return NULL;
+
+       snprintf(bssid, 13, "%02x%02x%02x%02x%02x%02x",
+                                       ioctl_bssid[0], ioctl_bssid[1],
+                                       ioctl_bssid[2], ioctl_bssid[3],
+                                       ioctl_bssid[4], ioctl_bssid[5]);
+
+       return bssid;
+}
+
 static void add_interface_reply(DBusPendingCall *call, void *user_data)
 {
        struct supplicant_task *task = user_data;
@@ -754,14 +824,16 @@ static int set_network(struct supplicant_task *task,
                        connman_dbus_dict_append_variant(&dict, "psk",
                                                DBUS_TYPE_STRING, &passphrase);
        } else if (g_ascii_strcasecmp(security, "wep") == 0) {
-               const char *key_mgmt = "NONE", *index = "0";
+               const char *key_mgmt = "NONE";
                const char *auth_alg = "OPEN SHARED";
-               connman_dbus_dict_append_variant(&dict, "key_mgmt",
-                                               DBUS_TYPE_STRING, &key_mgmt);
+               const char *key_index = "0";
 
                connman_dbus_dict_append_variant(&dict, "auth_alg",
                                                DBUS_TYPE_STRING, &auth_alg);
 
+               connman_dbus_dict_append_variant(&dict, "key_mgmt",
+                                               DBUS_TYPE_STRING, &key_mgmt);
+
                if (passphrase) {
                        int size = strlen(passphrase);
                        if (size == 10 || size == 26) {
@@ -784,8 +856,9 @@ static int set_network(struct supplicant_task *task,
                                connman_dbus_dict_append_variant(&dict,
                                                "wep_key0", DBUS_TYPE_STRING,
                                                                &passphrase);
+
                        connman_dbus_dict_append_variant(&dict, "wep_tx_keyidx",
-                                               DBUS_TYPE_STRING, &index);
+                                               DBUS_TYPE_STRING, &key_index);
                }
        } else {
                const char *key_mgmt = "NONE";
@@ -876,6 +949,11 @@ static char *build_group(const char *addr, const char *name,
        if (str == NULL)
                return NULL;
 
+       if (ssid == NULL) {
+               g_string_append_printf(str, "hidden_%s", addr);
+               goto done;
+       }
+
        for (i = 0; special_ssid[i].name; i++) {
                if (g_strcmp0(special_ssid[i].name, name) == 0) {
                        if (special_ssid[i].value == NULL)
@@ -904,7 +982,7 @@ static void extract_addr(DBusMessageIter *value,
                                        struct supplicant_result *result)
 {
        DBusMessageIter array;
-       struct ether_addr *eth;
+       struct ether_addr eth;
        unsigned char *addr;
        int addr_len;
 
@@ -925,15 +1003,14 @@ static void extract_addr(DBusMessageIter *value,
        if (result->path == NULL)
                return;
 
-       eth = (void *) addr;
-
+       memcpy(&eth, addr, sizeof(eth));
        snprintf(result->path, 13, "%02x%02x%02x%02x%02x%02x",
-                                               eth->ether_addr_octet[0],
-                                               eth->ether_addr_octet[1],
-                                               eth->ether_addr_octet[2],
-                                               eth->ether_addr_octet[3],
-                                               eth->ether_addr_octet[4],
-                                               eth->ether_addr_octet[5]);
+                                               eth.ether_addr_octet[0],
+                                               eth.ether_addr_octet[1],
+                                               eth.ether_addr_octet[2],
+                                               eth.ether_addr_octet[3],
+                                               eth.ether_addr_octet[4],
+                                               eth.ether_addr_octet[5]);
 }
 
 static void extract_ssid(DBusMessageIter *value,
@@ -949,6 +1026,9 @@ static void extract_ssid(DBusMessageIter *value,
        if (ssid_len < 1)
                return;
 
+       if (ssid[0] == '\0')
+               return;
+
        result->ssid = g_try_malloc(ssid_len);
        if (result->ssid == NULL)
                return;
@@ -1064,7 +1144,8 @@ static void properties_reply(DBusPendingCall *call, void *user_data)
        unsigned char strength;
        unsigned short channel, frequency;
        const char *mode, *security;
-       char *group;
+       char *group = NULL;
+       unsigned int ssid_len;
 
        DBG("task %p", task);
 
@@ -1202,8 +1283,10 @@ static void properties_reply(DBusPendingCall *call, void *user_data)
        if (result.name != NULL && result.name[0] != '\0')
                connman_network_set_name(network, result.name);
 
-       connman_network_set_blob(network, "WiFi.SSID",
-                                               result.ssid, result.ssid_len);
+       if (connman_network_get_blob(network, "WiFi.SSID", &ssid_len) == NULL) {
+               connman_network_set_blob(network, "WiFi.SSID",
+                                        result.ssid, result.ssid_len);
+       }
 
        connman_network_set_string(network, "WiFi.Mode", mode);
 
@@ -1218,11 +1301,12 @@ static void properties_reply(DBusPendingCall *call, void *user_data)
        connman_network_set_uint16(network, "WiFi.Channel", channel);
        connman_network_set_string(network, "WiFi.Security", security);
 
-       connman_network_set_group(network, group);
+       if (result.ssid != NULL)
+               connman_network_set_group(network, group);
 
+done:
        g_free(group);
 
-done:
        g_free(result.path);
        g_free(result.addr);
        g_free(result.name);
@@ -1411,6 +1495,8 @@ static int task_connect(struct supplicant_task *task)
        if (g_str_equal(security, "none") == FALSE && passphrase == NULL)
                return -EINVAL;
 
+       task->connecting = TRUE;
+
        add_network(task);
 
        select_network(task);
@@ -1423,43 +1509,6 @@ static int task_connect(struct supplicant_task *task)
        return 0;
 }
 
-static char *get_bssid(struct connman_device *device)
-{
-       char *bssid;
-       unsigned char ioctl_bssid[ETH_ALEN];
-       int fd, ret;
-       struct iwreq wrq;
-
-       if (connman_device_get_type(device) != CONNMAN_DEVICE_TYPE_WIFI)
-               return NULL;
-
-       fd = socket(PF_INET, SOCK_DGRAM, 0);
-       if (fd < 0)
-               return NULL;
-
-       memset(&wrq, 0, sizeof(wrq));
-       strncpy(wrq.ifr_name, connman_device_get_interface(device), IFNAMSIZ);
-
-       ret = ioctl(fd, SIOCGIWAP, &wrq);
-       close(fd);
-       if (ret != 0)
-               return NULL;
-
-       memcpy(ioctl_bssid, wrq.u.ap_addr.sa_data, ETH_ALEN);
-
-       bssid = g_try_malloc0(13);
-       if (bssid == NULL)
-               return NULL;
-
-       snprintf(bssid, 13, "%02x%02x%02x%02x%02x%02x",
-                ioctl_bssid[0], ioctl_bssid[1],
-                ioctl_bssid[2], ioctl_bssid[3],
-                ioctl_bssid[4], ioctl_bssid[5]);
-
-       return bssid;
-}
-
-
 static void state_change(struct supplicant_task *task, DBusMessage *msg)
 {
        DBusError error;
@@ -1515,10 +1564,9 @@ static void state_change(struct supplicant_task *task, DBusMessage *msg)
 
        switch (task->state) {
        case WPA_COMPLETED:
-               /* carrier on */
                if (connman_network_get_group(task->network) == NULL) {
                        const char *name, *mode, *security;
-                       char *group, *bssid;
+                       char *bssid;
 
                        /*
                         * This is a hidden network, we need to set its
@@ -1527,24 +1575,30 @@ static void state_change(struct supplicant_task *task, DBusMessage *msg)
                        bssid = get_bssid(task->device);
 
                        name = connman_network_get_string(task->network,
-                                                         "Name");
+                                                               "Name");
                        mode = connman_network_get_string(task->network,
-                                                         "WiFi.Mode");
+                                                               "WiFi.Mode");
                        security = connman_network_get_string(task->network,
-                                                             "WiFi.Security");
+                                                       "WiFi.Security");
 
                        if (bssid && name && mode && security) {
+                               char *group;
+
                                group = build_group(bssid, name, NULL, 0,
-                                                   mode, security);
+                                                               mode, security);
                                connman_network_set_group(task->network, group);
+                               g_free(group);
                        }
 
                        g_free(bssid);
-                       g_free(group);
                }
+
+               /* carrier on */
                connman_network_set_connected(task->network, TRUE);
                connman_device_set_scanning(task->device, FALSE);
+               task->connecting = FALSE;
                break;
+
        case WPA_DISCONNECTED:
                if (task->disconnecting == TRUE) {
                        connman_network_set_connected(task->network, FALSE);
@@ -1560,11 +1614,14 @@ static void state_change(struct supplicant_task *task, DBusMessage *msg)
                        /* carrier off */
                        connman_network_set_connected(task->network, FALSE);
                        connman_device_set_scanning(task->device, FALSE);
+                       task->connecting = FALSE;
                }
                break;
+
        case WPA_ASSOCIATING:
                connman_network_set_associating(task->network, TRUE);
                break;
+
        default:
                connman_network_set_associating(task->network, FALSE);
                break;
@@ -1603,27 +1660,6 @@ static DBusHandlerResult supplicant_filter(DBusConnection *conn,
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
-static int supplicant_get_range(struct supplicant_task *task)
-{
-       struct iwreq wrq;
-       int fd, err;
-
-       fd = socket(PF_INET, SOCK_DGRAM, 0);
-       if (fd < 0)
-               return -1;
-
-       memset(&wrq, 0, sizeof(struct iwreq));
-       strncpy(wrq.ifr_name, task->ifname, IFNAMSIZ);
-       wrq.u.data.pointer = task->range;
-       wrq.u.data.length = sizeof(struct iw_range);
-
-       err = ioctl(fd, SIOCGIWRANGE, &wrq);
-
-       close(fd);
-
-       return err;
-}
-
 int supplicant_start(struct connman_device *device)
 {
        struct supplicant_task *task;
@@ -1649,7 +1685,7 @@ int supplicant_start(struct connman_device *device)
                goto failed;
        }
 
-       err = supplicant_get_range(task);
+       err = get_range(task);
        if (err < 0)
                goto failed;
 
@@ -1658,6 +1694,7 @@ int supplicant_start(struct connman_device *device)
        task->created = FALSE;
        task->noscan = FALSE;
        task->state = WPA_INVALID;
+       task->connecting = FALSE;
        task->disconnecting = FALSE;
        task->pending_network = NULL;