From d6c6e4acda9c49286ad68ac43dbc78603496a566 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 1 Jun 2016 17:23:33 -0500 Subject: [PATCH] netdev: Move netdev enumeration to netdev.c --- src/device.h | 4 + src/netdev.c | 101 +++++++++++++++++++++ src/wiphy.c | 246 +++++++++++++++------------------------------------ src/wiphy.h | 1 + 4 files changed, 178 insertions(+), 174 deletions(-) diff --git a/src/device.h b/src/device.h index cae3a32a..47038581 100644 --- a/src/device.h +++ b/src/device.h @@ -24,6 +24,7 @@ struct scan_bss; struct wiphy; +struct netdev; struct device; typedef void (*device_watch_func_t)(struct device *device, void *userdata); @@ -49,5 +50,8 @@ void device_connect_network(struct device *device, struct network *network, uint32_t device_get_ifindex(struct device *device); const uint8_t *device_get_address(struct device *device); +struct device *device_create(struct wiphy *wiphy, struct netdev *netdev); +void device_remove(struct device *device); + bool device_init(void); bool device_exit(void); diff --git a/src/netdev.c b/src/netdev.c index b88a9e76..990e9639 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -33,6 +33,7 @@ #include "linux/nl80211.h" #include "src/wiphy.h" +#include "src/device.h" #include "src/netdev.h" struct netdev { @@ -159,6 +160,99 @@ struct netdev *netdev_find(int ifindex) return l_queue_find(netdev_list, netdev_match, L_UINT_TO_PTR(ifindex)); } +static void netdev_get_interface_callback(struct l_genl_msg *msg, + void *user_data) +{ + struct l_genl_attr attr; + uint16_t type, len; + const void *data; + const char *ifname; + uint16_t ifname_len; + const uint8_t *ifaddr; + const uint32_t *ifindex, *iftype; + struct netdev *netdev; + struct wiphy *wiphy = NULL; + + if (!l_genl_attr_init(&attr, msg)) + return; + + while (l_genl_attr_next(&attr, &type, &len, &data)) { + switch (type) { + case NL80211_ATTR_IFINDEX: + if (len != sizeof(uint32_t)) { + l_warn("Invalid interface index attribute"); + return; + } + + ifindex = data; + break; + + case NL80211_ATTR_IFNAME: + if (len > IFNAMSIZ) { + l_warn("Invalid interface name attribute"); + return; + } + + ifname = data; + ifname_len = len; + break; + + case NL80211_ATTR_WIPHY: + if (len != sizeof(uint32_t)) { + l_warn("Invalid wiphy attribute"); + return; + } + + wiphy = wiphy_find(*((uint32_t *) data)); + break; + + case NL80211_ATTR_IFTYPE: + if (len != sizeof(uint32_t)) { + l_warn("Invalid interface type attribute"); + return; + } + + iftype = data; + break; + + case NL80211_ATTR_MAC: + if (len != ETH_ALEN) { + l_warn("Invalid interface address attribute"); + return; + } + + ifaddr = data; + break; + } + } + + if (!wiphy) { + l_warn("Missing wiphy attribute or wiphy not found"); + return; + } + + if (!ifindex || !ifaddr | !ifname) { + l_warn("Unable to parse interface information"); + return; + } + + if (netdev_find(*ifindex)) { + l_debug("Skipping duplicate netdev %s[%d]", ifname, *ifindex); + return; + } + + netdev = l_new(struct netdev, 1); + netdev->index = *ifindex; + netdev->type = *iftype; + memcpy(netdev->addr, ifaddr, sizeof(netdev->addr)); + memcpy(netdev->name, ifname, ifname_len); + + l_queue_push_tail(netdev_list, netdev); + + l_debug("Found interface %s[%d]", netdev->name, netdev->index); + device_create(wiphy, netdev); +} + static void netdev_config_notify(struct l_genl_msg *msg, void *user_data) { struct l_genl_attr attr; @@ -217,6 +311,8 @@ static void netdev_config_notify(struct l_genl_msg *msg, void *user_data) bool netdev_init(struct l_genl_family *in) { + struct l_genl_msg *msg; + if (rtnl) return false; @@ -239,6 +335,11 @@ bool netdev_init(struct l_genl_family *in) NULL, NULL)) l_error("Registering for config notification failed"); + msg = l_genl_msg_new(NL80211_CMD_GET_INTERFACE); + if (!l_genl_family_dump(nl80211, msg, netdev_get_interface_callback, + NULL, NULL)) + l_error("Getting all interface information failed"); + return true; } diff --git a/src/wiphy.c b/src/wiphy.c index 5d52c14b..eeccba52 100644 --- a/src/wiphy.c +++ b/src/wiphy.c @@ -64,7 +64,6 @@ enum device_state { struct device { uint32_t index; char name[IFNAMSIZ]; - uint32_t type; uint8_t addr[ETH_ALEN]; enum device_state state; struct l_queue *bss_list; @@ -89,7 +88,6 @@ struct wiphy { uint32_t id; char name[20]; uint32_t feature_flags; - struct l_queue *netdev_list; bool support_scheduled_scan:1; bool support_rekey_offload:1; uint16_t pairwise_ciphers; @@ -103,6 +101,7 @@ struct autoconnect_entry { }; static struct l_queue *wiphy_list = NULL; +static struct l_queue *device_list; static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, struct l_queue *bss_list, void *userdata); @@ -345,21 +344,13 @@ uint32_t device_get_ifindex(struct device *device) void __iwd_device_foreach(iwd_device_foreach_func func, void *user_data) { - const struct l_queue_entry *wiphy_entry; + const struct l_queue_entry *device_entry; - for (wiphy_entry = l_queue_get_entries(wiphy_list); wiphy_entry; - wiphy_entry = wiphy_entry->next) { - struct wiphy *wiphy = wiphy_entry->data; - const struct l_queue_entry *netdev_entry; + for (device_entry = l_queue_get_entries(device_list); device_entry; + device_entry = device_entry->next) { + struct device *device = device_entry->data; - netdev_entry = l_queue_get_entries(wiphy->netdev_list); - - while (netdev_entry) { - struct device *device = netdev_entry->data; - - func(device, user_data); - netdev_entry = netdev_entry->next; - } + func(device, user_data); } } @@ -518,40 +509,6 @@ static bool bss_match(const void *a, const void *b) return !memcmp(bss_a->addr, bss_b->addr, sizeof(bss_a->addr)); } -static void device_free(void *data) -{ - struct device *device = data; - struct l_dbus *dbus; - - if (device->scan_pending) - dbus_pending_reply(&device->scan_pending, - dbus_error_aborted(device->scan_pending)); - - if (device->connect_pending) - dbus_pending_reply(&device->connect_pending, - dbus_error_aborted(device->connect_pending)); - - __device_watch_call_removed(device); - - dbus = dbus_get_bus(); - l_dbus_unregister_object(dbus, device_get_path(device)); - - l_debug("Freeing interface %s", device->name); - - l_hashmap_destroy(device->networks, network_free); - - l_queue_destroy(device->bss_list, bss_free); - l_queue_destroy(device->old_bss_list, bss_free); - l_queue_destroy(device->autoconnect_list, l_free); - l_io_destroy(device->eapol_io); - - scan_ifindex_remove(device->index); - netdev_set_linkmode_and_operstate(device->index, 0, IF_OPER_DOWN, - NULL, NULL); - - l_free(device); -} - static bool device_match(const void *a, const void *b) { const struct device *device = a; @@ -589,7 +546,6 @@ static void wiphy_free(void *data) l_debug("Freeing wiphy %s", wiphy->name); scan_freq_set_free(wiphy->supported_freqs); - l_queue_destroy(wiphy->netdev_list, device_free); l_free(wiphy); } @@ -1364,136 +1320,80 @@ static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, return true; } -static void interface_dump_callback(struct l_genl_msg *msg, void *user_data) +struct device *device_create(struct wiphy *wiphy, struct netdev *netdev) { - struct wiphy *wiphy = NULL; struct device *device; - struct l_genl_attr attr; - uint16_t type, len; - const void *data; - char ifname[IFNAMSIZ]; - uint8_t ifaddr[ETH_ALEN]; - uint32_t ifindex, iftype; + struct l_dbus *dbus = dbus_get_bus(); + uint32_t ifindex = netdev_get_ifindex(netdev); - if (!l_genl_attr_init(&attr, msg)) - return; + device = l_new(struct device, 1); + device->bss_list = l_queue_new(); + device->networks = l_hashmap_new(); + l_hashmap_set_hash_function(device->networks, l_str_hash); + l_hashmap_set_compare_function(device->networks, + (l_hashmap_compare_func_t) strcmp); + strcpy(device->name, netdev_get_name(netdev)); + memcpy(device->addr, netdev_get_address(netdev), sizeof(device->addr)); + device->index = ifindex; + device->wiphy = wiphy; - memset(ifname, 0, sizeof(ifname)); - memset(ifaddr, 0, sizeof(ifaddr)); - iftype = NL80211_IFTYPE_UNSPECIFIED; - ifindex = 0; + l_queue_push_head(device_list, device); - /* - * The interface index and interface name attributes are normally - * listed before the wiphy attribute. This handling assumes that - * all attributes are included in the same message. - * - * If any required attribute is missing, the whole message will - * be ignored. - */ - while (l_genl_attr_next(&attr, &type, &len, &data)) { - switch (type) { - case NL80211_ATTR_IFINDEX: - if (len != sizeof(uint32_t)) { - l_warn("Invalid interface index attribute"); - return; - } + if (!l_dbus_object_add_interface(dbus, device_get_path(device), + IWD_DEVICE_INTERFACE, device)) + l_info("Unable to register %s interface", IWD_DEVICE_INTERFACE); - ifindex = *((uint32_t *) data); - break; + __device_watch_call_added(device); - case NL80211_ATTR_IFNAME: - if (len > sizeof(ifname)) { - l_warn("Invalid interface name attribute"); - return; - } - - memcpy(ifname, data, len); - break; - - case NL80211_ATTR_WIPHY: - if (len != sizeof(uint32_t)) { - l_warn("Invalid wiphy attribute"); - return; - } - - wiphy = l_queue_find(wiphy_list, wiphy_match, - L_UINT_TO_PTR(*((uint32_t *) data))); - break; - - case NL80211_ATTR_IFTYPE: - if (len != sizeof(uint32_t)) { - l_warn("Invalid interface type attribute"); - return; - } - - iftype = *((uint32_t *) data); - break; - - case NL80211_ATTR_MAC: - if (len != sizeof(ifaddr)) { - l_warn("Invalid interface address attribute"); - return; - } - - memcpy(ifaddr, data, len); - break; - } - } - - if (!wiphy) { - l_warn("Missing wiphy attribute or wiphy not found"); - return; - } - - if (!ifindex) { - l_warn("Missing interface index attribute"); - return; - } - - device = l_queue_find(wiphy->netdev_list, device_match, - L_UINT_TO_PTR(ifindex)); - if (!device) { - struct l_dbus *dbus = dbus_get_bus(); - - device = l_new(struct device, 1); - device->bss_list = l_queue_new(); - device->networks = l_hashmap_new(); - l_hashmap_set_hash_function(device->networks, l_str_hash); - l_hashmap_set_compare_function(device->networks, - (l_hashmap_compare_func_t) strcmp); - memcpy(device->name, ifname, sizeof(device->name)); - memcpy(device->addr, ifaddr, sizeof(device->addr)); - device->index = ifindex; - device->type = iftype; - device->wiphy = wiphy; - - l_queue_push_head(wiphy->netdev_list, device); - - if (!l_dbus_object_add_interface(dbus, - device_get_path(device), - IWD_DEVICE_INTERFACE, device)) - l_info("Unable to register %s interface", - IWD_DEVICE_INTERFACE); - - __device_watch_call_added(device); - - netdev_set_linkmode_and_operstate(device->index, 1, + netdev_set_linkmode_and_operstate(device->index, 1, IF_OPER_DORMANT, NULL, NULL); - scan_ifindex_add(device->index); - device_enter_state(device, DEVICE_STATE_AUTOCONNECT); - } - - l_debug("Found interface %s", device->name); + scan_ifindex_add(device->index); + device_enter_state(device, DEVICE_STATE_AUTOCONNECT); device->eapol_io = eapol_open_pae(device->index); - if (!device->eapol_io) { + if (device->eapol_io) + l_io_set_read_handler(device->eapol_io, eapol_read, + device, NULL); + else l_error("Failed to open PAE socket"); - return; - } - l_io_set_read_handler(device->eapol_io, eapol_read, device, NULL); + return device; +} + +void device_remove(struct device *device) +{ + struct l_dbus *dbus; + + l_debug(""); + + l_queue_remove(device_list, device); + + if (device->scan_pending) + dbus_pending_reply(&device->scan_pending, + dbus_error_aborted(device->scan_pending)); + + if (device->connect_pending) + dbus_pending_reply(&device->connect_pending, + dbus_error_aborted(device->connect_pending)); + + __device_watch_call_removed(device); + + dbus = dbus_get_bus(); + l_dbus_unregister_object(dbus, device_get_path(device)); + + l_hashmap_destroy(device->networks, network_free); + + l_queue_destroy(device->bss_list, bss_free); + l_queue_destroy(device->old_bss_list, bss_free); + l_queue_destroy(device->autoconnect_list, l_free); + l_io_destroy(device->eapol_io); + + scan_ifindex_remove(device->index); + netdev_set_linkmode_and_operstate(device->index, 0, IF_OPER_DOWN, + NULL, NULL); + + l_free(device); } struct wiphy *wiphy_find(int wiphy_id) @@ -1659,7 +1559,6 @@ static void wiphy_dump_callback(struct l_genl_msg *msg, void *user_data) if (!wiphy) { wiphy = l_new(struct wiphy, 1); wiphy->id = id; - wiphy->netdev_list = l_queue_new(); wiphy->supported_freqs = scan_freq_set_new(); l_queue_push_head(wiphy_list, wiphy); } @@ -1827,7 +1726,7 @@ static void wiphy_mlme_notify(struct l_genl_msg *msg, void *user_data) return; } - device = l_queue_find(wiphy->netdev_list, device_match, + device = l_queue_find(device_list, device_match, L_UINT_TO_PTR(*((uint32_t *) data))); if (!device) { l_warn("No interface structure found"); @@ -1973,6 +1872,7 @@ bool wiphy_init(struct l_genl_family *in) __eapol_set_deauthenticate_func(handshake_failed); wiphy_list = l_queue_new(); + device_list = l_queue_new(); msg = l_genl_msg_new(NL80211_CMD_GET_PROTOCOL_FEATURES); if (!l_genl_family_send(nl80211, msg, protocol_features_callback, @@ -1989,11 +1889,6 @@ bool wiphy_init(struct l_genl_family *in) NULL, wiphy_dump_done)) l_error("Getting all wiphy devices failed"); - msg = l_genl_msg_new(NL80211_CMD_GET_INTERFACE); - if (!l_genl_family_dump(nl80211, msg, interface_dump_callback, - NULL, NULL)) - l_error("Getting all interface information failed"); - return true; } @@ -2002,6 +1897,9 @@ bool wiphy_exit(void) l_queue_destroy(wiphy_list, wiphy_free); wiphy_list = NULL; + l_queue_destroy(device_list, (l_queue_destroy_func_t) device_remove); + device_list = NULL; + nl80211 = NULL; l_dbus_unregister_interface(dbus_get_bus(), IWD_DEVICE_INTERFACE); diff --git a/src/wiphy.h b/src/wiphy.h index 58756b86..78763294 100644 --- a/src/wiphy.h +++ b/src/wiphy.h @@ -25,6 +25,7 @@ struct wiphy; struct device; +struct netdev; typedef void (*iwd_device_foreach_func)(struct device *, void *data);