From 1338c446b03fa6a412e789b7846a980631b34d30 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Sun, 26 Mar 2017 03:16:50 +0200 Subject: [PATCH] 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. --- tools/hwsim.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/tools/hwsim.c b/tools/hwsim.c index 7ca46f25..1e143fcc 100644 --- a/tools/hwsim.c +++ b/tools/hwsim.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include @@ -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();