From d67425c9362a7a9f059ec0d59c35e39db2d743a5 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Wed, 8 Mar 2017 15:07:14 +0100 Subject: [PATCH] netdev: React to interface address change Handle the changes of interface address in RTNL New Link messages similarly to the name changes, emit a NETDEV_WATCH_EVENT_ADDRESS_CHANGE event and a propety change on dbus. Note this can only happen when the interface is down so it doesn't break anything but we need to handle it anyway. --- src/device.c | 4 ++++ src/netdev.c | 24 +++++++++++++++++++----- src/netdev.h | 1 + 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/device.c b/src/device.c index d2e57040..4aafaef6 100644 --- a/src/device.c +++ b/src/device.c @@ -1699,6 +1699,10 @@ static void device_netdev_notify(struct netdev *netdev, l_dbus_property_changed(dbus, device_get_path(device), IWD_DEVICE_INTERFACE, "Name"); break; + case NETDEV_WATCH_EVENT_ADDRESS_CHANGE: + l_dbus_property_changed(dbus, device_get_path(device), + IWD_DEVICE_INTERFACE, "Address"); + break; } } diff --git a/src/netdev.c b/src/netdev.c index f16173d1..4e31b843 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -2585,6 +2585,7 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes) struct netdev *netdev; bool old_up, new_up; char old_name[IFNAMSIZ]; + uint8_t old_addr[ETH_ALEN]; struct rtattr *attr; struct netdev_watch_event_data event; @@ -2594,17 +2595,23 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes) old_up = netdev_get_is_up(netdev); strcpy(old_name, netdev->name); + memcpy(old_addr, netdev->addr, ETH_ALEN); netdev->ifi_flags = ifi->ifi_flags; for (attr = IFLA_RTA(ifi); RTA_OK(attr, bytes); attr = RTA_NEXT(attr, bytes)) { - if (attr->rta_type != IFLA_IFNAME) - continue; + switch (attr->rta_type) { + case IFLA_IFNAME: + strcpy(netdev->name, RTA_DATA(attr)); + break; + case IFLA_ADDRESS: + if (RTA_PAYLOAD(attr) < ETH_ALEN) + break; - strcpy(netdev->name, RTA_DATA(attr)); - - break; + memcpy(netdev->addr, RTA_DATA(attr), ETH_ALEN); + break; + } } new_up = netdev_get_is_up(netdev); @@ -2623,6 +2630,13 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes) l_queue_foreach(netdev->watches, netdev_watch_notify, &event); } + + if (memcmp(old_addr, netdev->addr, ETH_ALEN)) { + event.netdev = netdev; + event.type = NETDEV_WATCH_EVENT_ADDRESS_CHANGE; + + l_queue_foreach(netdev->watches, netdev_watch_notify, &event); + } } static void netdev_dellink_notify(const struct ifinfomsg *ifi, int bytes) diff --git a/src/netdev.h b/src/netdev.h index 20786988..77db458d 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -52,6 +52,7 @@ enum netdev_watch_event { NETDEV_WATCH_EVENT_UP, NETDEV_WATCH_EVENT_DOWN, NETDEV_WATCH_EVENT_NAME_CHANGE, + NETDEV_WATCH_EVENT_ADDRESS_CHANGE, }; typedef void (*netdev_command_func_t) (bool result, void *user_data);