netdev: Move netdev enumeration to netdev.c

This commit is contained in:
Denis Kenzior 2016-06-01 17:23:33 -05:00
parent 833ed20b9a
commit d6c6e4acda
4 changed files with 178 additions and 174 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -25,6 +25,7 @@
struct wiphy;
struct device;
struct netdev;
typedef void (*iwd_device_foreach_func)(struct device *, void *data);