mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 09:39:25 +01:00
hwsim: Watch RTNL NewLink events
Handle NewLink events to detect interface mac address changes. In my current testing I don't see nl80211 events on address change so it's best to react to both types of events.
This commit is contained in:
parent
52ee3b0843
commit
1338c446b0
@ -28,6 +28,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include <ell/ell.h>
|
||||
|
||||
@ -105,6 +107,7 @@ struct hwsim_rule {
|
||||
static struct l_genl *genl;
|
||||
static struct l_genl_family *hwsim;
|
||||
static struct l_genl_family *nl80211;
|
||||
static struct l_netlink *rtnl;
|
||||
|
||||
static const char *options;
|
||||
static int exit_status;
|
||||
@ -931,6 +934,74 @@ static void nl80211_config_notify(struct l_genl_msg *msg, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static void rtnl_newlink_notify(const struct ifinfomsg *ifi, int bytes)
|
||||
{
|
||||
struct rtattr *attr;
|
||||
struct interface_info_rec *rec;
|
||||
bool addr_change = false, name_change = false;
|
||||
const char *path;
|
||||
|
||||
rec = l_queue_find(interface_info, interface_info_match_id,
|
||||
L_UINT_TO_PTR(ifi->ifi_index));
|
||||
if (!rec)
|
||||
return;
|
||||
|
||||
for (attr = IFLA_RTA(ifi); RTA_OK(attr, bytes);
|
||||
attr = RTA_NEXT(attr, bytes)) {
|
||||
switch (attr->rta_type) {
|
||||
case IFLA_IFNAME:
|
||||
if (!strcmp(rec->name, RTA_DATA(attr)))
|
||||
continue;
|
||||
|
||||
name_change = true;
|
||||
l_free(rec->name);
|
||||
rec->name = l_strdup(RTA_DATA(attr));
|
||||
break;
|
||||
case IFLA_ADDRESS:
|
||||
if (RTA_PAYLOAD(attr) < ETH_ALEN)
|
||||
break;
|
||||
|
||||
if (!memcmp(rec->addr, RTA_DATA(attr), ETH_ALEN))
|
||||
continue;
|
||||
|
||||
addr_change = true;
|
||||
memcpy(rec->addr, RTA_DATA(attr), ETH_ALEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr_change && !name_change)
|
||||
return;
|
||||
|
||||
path = interface_get_path(rec);
|
||||
|
||||
if (addr_change)
|
||||
l_dbus_property_changed(dbus, path, HWSIM_INTERFACE_INTERFACE,
|
||||
"Address");
|
||||
|
||||
if (name_change)
|
||||
l_dbus_property_changed(dbus, path, HWSIM_INTERFACE_INTERFACE,
|
||||
"Name");
|
||||
}
|
||||
|
||||
static void rtnl_link_notify(uint16_t type, const void *data, uint32_t len,
|
||||
void *user_data)
|
||||
{
|
||||
const struct ifinfomsg *ifi = data;
|
||||
unsigned int bytes;
|
||||
|
||||
if (ifi->ifi_type != ARPHRD_ETHER)
|
||||
return;
|
||||
|
||||
bytes = len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWLINK:
|
||||
rtnl_newlink_notify(ifi, bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_multicast_addr(const uint8_t *addr)
|
||||
{
|
||||
return util_is_bit_set(addr[0], 7);
|
||||
@ -2022,6 +2093,18 @@ static void get_radio_done_initial(void *user_data)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rtnl = l_netlink_new(NETLINK_ROUTE);
|
||||
if (!rtnl) {
|
||||
l_error("Failed to open route netlink socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!l_netlink_register(rtnl, RTNLGRP_LINK,
|
||||
rtnl_link_notify, NULL, NULL)) {
|
||||
l_error("Failed to register for RTNL link notifications");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
@ -2313,6 +2396,8 @@ int main(int argc, char *argv[])
|
||||
hwsim_radio_cache_cleanup();
|
||||
l_queue_destroy(rules, l_free);
|
||||
|
||||
l_netlink_destroy(rtnl);
|
||||
|
||||
done:
|
||||
l_signal_remove(signal);
|
||||
l_main_exit();
|
||||
|
Loading…
Reference in New Issue
Block a user