From 896aa41082de748fb7fe5e2b950a07c1137a169b Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 12 Jun 2018 12:20:18 +0800 Subject: [PATCH] netdev: handle netlink events on bridge ports When a wifi interface is added/removed to/from a bridge, a RTM_NEW/DELLINK event is issued. This is the same event used to signal when an interface is created/deleted. For this reason the event generated by the bridge code has to be properly distinguished and handled accordingly. Failing to do so will result in inconsistencies in iwd which will think an interface has been deleted when it was actually not. Detect incoming NEW/DELLINK bridge events and reacts accordingly. For now, this simply means printing a simple message, as there is no special logic in iwd for this yet. --- src/netdev.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/netdev.c b/src/netdev.c index 21990d38..f9fab848 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -3472,6 +3472,30 @@ int netdev_set_iftype(struct netdev *netdev, enum netdev_iftype type) return 0; } +static void netdev_bridge_port_event(const struct ifinfomsg *ifi, int bytes, + bool added) +{ + struct netdev *netdev; + struct rtattr *attr; + uint32_t master = 0; + + netdev = netdev_find(ifi->ifi_index); + if (!netdev) + return; + + for (attr = IFLA_RTA(ifi); RTA_OK(attr, bytes); + attr = RTA_NEXT(attr, bytes)) { + switch (attr->rta_type) { + case IFLA_MASTER: + memcpy(&master, RTA_DATA(attr), sizeof(master)); + break; + } + } + + l_debug("netdev: %d %s bridge: %d", ifi->ifi_index, + (added ? "added to" : "removed from"), master); +} + static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes) { struct netdev *netdev; @@ -3480,6 +3504,11 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes) uint8_t old_addr[ETH_ALEN]; struct rtattr *attr; + if (ifi->ifi_family == AF_BRIDGE) { + netdev_bridge_port_event(ifi, bytes, true); + return; + } + netdev = netdev_find(ifi->ifi_index); if (!netdev) return; @@ -3525,6 +3554,11 @@ static void netdev_dellink_notify(const struct ifinfomsg *ifi, int bytes) { struct netdev *netdev; + if (ifi->ifi_family == AF_BRIDGE) { + netdev_bridge_port_event(ifi, bytes, false); + return; + } + netdev = l_queue_remove_if(netdev_list, netdev_match, L_UINT_TO_PTR(ifi->ifi_index)); if (!netdev)