hwsim: Keep track of interface types

This commit is contained in:
Denis Kenzior 2021-12-27 10:14:17 -06:00
parent d676f159d3
commit 1dcab170b6
2 changed files with 49 additions and 48 deletions

View File

@ -377,6 +377,8 @@ bin_PROGRAMS += tools/hwsim
tools_hwsim_SOURCES = tools/hwsim.c src/mpdu.h \ tools_hwsim_SOURCES = tools/hwsim.c src/mpdu.h \
src/util.h src/util.c \ src/util.h src/util.c \
src/nl80211cmd.h src/nl80211cmd.c \
src/nl80211util.h src/nl80211util.c \
src/storage.h src/storage.c \ src/storage.h src/storage.c \
src/common.h src/common.c \ src/common.h src/common.c \
src/band.h src/band.c src/band.h src/band.c

View File

@ -42,6 +42,8 @@
#include "src/storage.h" #include "src/storage.h"
#include "src/mpdu.h" #include "src/mpdu.h"
#include "src/crypto.h" #include "src/crypto.h"
#include "src/nl80211util.h"
#include "src/nl80211cmd.h"
#define HWSIM_SERVICE "net.connman.hwsim" #define HWSIM_SERVICE "net.connman.hwsim"
@ -419,6 +421,7 @@ struct interface_info_rec {
struct radio_info_rec *radio_rec; struct radio_info_rec *radio_rec;
uint8_t addr[ETH_ALEN]; uint8_t addr[ETH_ALEN];
char *name; char *name;
uint32_t iftype;
}; };
static struct l_queue *radio_info; static struct l_queue *radio_info;
@ -818,14 +821,11 @@ static void get_wiphy_callback(struct l_genl_msg *msg, void *user_data)
static void get_interface_callback(struct l_genl_msg *msg, void *user_data) static void get_interface_callback(struct l_genl_msg *msg, void *user_data)
{ {
struct l_genl_attr attr; uint32_t ifindex;
uint16_t type, len; uint32_t wiphy_id;
const void *data; uint32_t iftype;
const uint8_t *addr = NULL; const uint8_t *addr;
const uint32_t *wiphy_id = NULL; const char *ifname;
const uint32_t *ifindex = NULL;
const char *ifname = NULL;
size_t ifname_len = 0;
struct interface_info_rec *rec; struct interface_info_rec *rec;
struct radio_info_rec *radio_rec; struct radio_info_rec *radio_rec;
bool old; bool old;
@ -833,57 +833,28 @@ static void get_interface_callback(struct l_genl_msg *msg, void *user_data)
struct interface_info_rec prev_rec; struct interface_info_rec prev_rec;
bool name_change = false; bool name_change = false;
if (!l_genl_attr_init(&attr, msg)) if (nl80211_parse_attrs(msg, NL80211_ATTR_IFINDEX, &ifindex,
return; NL80211_ATTR_IFNAME, &ifname,
NL80211_ATTR_WIPHY, &wiphy_id,
while (l_genl_attr_next(&attr, &type, &len, &data)) { NL80211_ATTR_IFTYPE, &iftype,
switch (type) { NL80211_ATTR_MAC, &addr,
case NL80211_ATTR_MAC: NL80211_ATTR_UNSPEC) < 0)
if (len != ETH_ALEN)
break;
addr = data;
break;
case NL80211_ATTR_WIPHY:
if (len != 4)
break;
wiphy_id = data;
break;
case NL80211_ATTR_IFINDEX:
if (len != 4)
break;
ifindex = data;
break;
case NL80211_ATTR_IFNAME:
ifname = data;
ifname_len = len;
break;
}
}
if (!addr || !wiphy_id || !ifindex || !ifname)
return; return;
radio_rec = l_queue_find(radio_info, radio_info_match_wiphy_id, radio_rec = l_queue_find(radio_info, radio_info_match_wiphy_id,
L_UINT_TO_PTR(*wiphy_id)); L_UINT_TO_PTR(wiphy_id));
if (!radio_rec) if (!radio_rec)
/* This is not a hwsim interface, don't track it */ /* This is not a hwsim interface, don't track it */
return; return;
rec = l_queue_find(interface_info, interface_info_match_id, rec = l_queue_find(interface_info, interface_info_match_id,
L_UINT_TO_PTR(*ifindex)); L_UINT_TO_PTR(ifindex));
if (rec) { if (rec) {
old = true; old = true;
memcpy(&prev_rec, rec, sizeof(prev_rec)); memcpy(&prev_rec, rec, sizeof(prev_rec));
if (strlen(rec->name) != ifname_len || if (strcmp(rec->name, ifname))
memcmp(rec->name, ifname, ifname_len))
name_change = true; name_change = true;
l_free(rec->name); l_free(rec->name);
@ -892,12 +863,13 @@ static void get_interface_callback(struct l_genl_msg *msg, void *user_data)
rec = l_new(struct interface_info_rec, 1); rec = l_new(struct interface_info_rec, 1);
rec->id = *ifindex; rec->id = ifindex;
rec->radio_rec = radio_rec; rec->radio_rec = radio_rec;
} }
memcpy(rec->addr, addr, ETH_ALEN); memcpy(rec->addr, addr, ETH_ALEN);
rec->name = l_strndup(ifname, ifname_len); rec->name = l_strdup(ifname);
rec->iftype = iftype;
if (!interface_info) if (!interface_info)
interface_info = l_queue_new(); interface_info = l_queue_new();
@ -987,6 +959,30 @@ static void del_radio_event(struct l_genl_msg *msg)
radio_free(radio); radio_free(radio);
} }
static void set_interface_event(struct l_genl_msg *msg)
{
struct interface_info_rec *interface;
uint32_t ifindex;
uint32_t iftype;
if (nl80211_parse_attrs(msg, NL80211_ATTR_IFINDEX, &ifindex,
NL80211_ATTR_IFTYPE, &iftype,
NL80211_ATTR_UNSPEC) < 0)
return;
interface = l_queue_find(interface_info, interface_info_match_id,
L_UINT_TO_PTR(ifindex));
if (!interface)
return;
if (interface->iftype == iftype)
return;
l_debug("Interface iftype changed for ifindex: %u, iftype: %u",
ifindex, iftype);
interface->iftype = iftype;
}
static void del_interface_event(struct l_genl_msg *msg) static void del_interface_event(struct l_genl_msg *msg)
{ {
struct interface_info_rec *interface; struct interface_info_rec *interface;
@ -1064,6 +1060,9 @@ static void nl80211_config_notify(struct l_genl_msg *msg, void *user_data)
case NL80211_CMD_NEW_INTERFACE: case NL80211_CMD_NEW_INTERFACE:
get_interface_callback(msg, NULL); get_interface_callback(msg, NULL);
break; break;
case NL80211_CMD_SET_INTERFACE:
set_interface_event(msg);
break;
case NL80211_CMD_DEL_INTERFACE: case NL80211_CMD_DEL_INTERFACE:
del_interface_event(msg); del_interface_event(msg);
break; break;