mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-21 11:52:34 +01:00
netdev: Move netdev enumeration to netdev.c
This commit is contained in:
parent
833ed20b9a
commit
d6c6e4acda
@ -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);
|
||||
|
101
src/netdev.c
101
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;
|
||||
}
|
||||
|
||||
|
246
src/wiphy.c
246
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);
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
struct wiphy;
|
||||
struct device;
|
||||
struct netdev;
|
||||
|
||||
typedef void (*iwd_device_foreach_func)(struct device *, void *data);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user