3
0
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:
Andrew Zaborowski 2017-03-26 03:16:50 +02:00 committed by Denis Kenzior
parent 52ee3b0843
commit 1338c446b0

View File

@ -28,6 +28,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <getopt.h> #include <getopt.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/rtnetlink.h>
#include <net/if_arp.h>
#include <ell/ell.h> #include <ell/ell.h>
@ -105,6 +107,7 @@ struct hwsim_rule {
static struct l_genl *genl; static struct l_genl *genl;
static struct l_genl_family *hwsim; static struct l_genl_family *hwsim;
static struct l_genl_family *nl80211; static struct l_genl_family *nl80211;
static struct l_netlink *rtnl;
static const char *options; static const char *options;
static int exit_status; 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) static bool is_multicast_addr(const uint8_t *addr)
{ {
return util_is_bit_set(addr[0], 7); return util_is_bit_set(addr[0], 7);
@ -2022,6 +2093,18 @@ static void get_radio_done_initial(void *user_data)
goto error; 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; return;
error: error:
@ -2313,6 +2396,8 @@ int main(int argc, char *argv[])
hwsim_radio_cache_cleanup(); hwsim_radio_cache_cleanup();
l_queue_destroy(rules, l_free); l_queue_destroy(rules, l_free);
l_netlink_destroy(rtnl);
done: done:
l_signal_remove(signal); l_signal_remove(signal);
l_main_exit(); l_main_exit();