blob: db3a63ea483fc8ced24b35f242d8777128b6ff19 [file] [log] [blame]
From 798bfb5e984845a27874d1a244686db6e384d7b8 Mon Sep 17 00:00:00 2001
From: Nate Karstens <nate.karstens@garmin.com>
Date: Thu, 13 Jul 2017 09:00:00 -0500
Subject: [PATCH 04/11] Use list for changed interfaces
Uses a linked list to store the index of changed network interfaces
instead of a bitfield. This allows for network interfaces with an
index greater than 31 (an index of 36 was seen on Android).
Upstream-Status: Submitted [dts@apple.com]
Signed-off-by: Nate Karstens <nate.karstens@garmin.com>
---
mDNSPosix/mDNSPosix.c | 67 +++++++++++++++++++++++++++++++++----------
1 file changed, 52 insertions(+), 15 deletions(-)
diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
index 195d04b..bb883c1 100755
--- a/mDNSPosix/mDNSPosix.c
+++ b/mDNSPosix/mDNSPosix.c
@@ -67,6 +67,14 @@ struct IfChangeRec
};
typedef struct IfChangeRec IfChangeRec;
+// Used to build a list of network interface indices
+struct NetworkInterfaceIndex
+{
+ int if_index;
+ struct NetworkInterfaceIndex *Next;
+};
+typedef struct NetworkInterfaceIndex NetworkInterfaceIndex;
+
// Note that static data is initialized to zero in (modern) C.
static PosixEventSource *gEventSources; // linked list of PosixEventSource's
static sigset_t gEventSignalSet; // Signals which event loop listens for
@@ -1458,6 +1466,32 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
return err;
}
+mDNSlocal mDNSBool ListContainsInterfaceIndex(GenLinkedList *list, int if_index)
+{
+ NetworkInterfaceIndex *item;
+
+ for (item = (NetworkInterfaceIndex*)list->Head; item != NULL; item = item->Next)
+ {
+ if (if_index == item->if_index) return mDNStrue;
+ }
+
+ return mDNSfalse;
+}
+
+mDNSlocal void AddInterfaceIndexToList(GenLinkedList *list, int if_index)
+{
+ NetworkInterfaceIndex *item;
+
+ if (ListContainsInterfaceIndex(list, if_index)) return;
+
+ item = malloc(sizeof *item);
+ if (item == NULL) return;
+
+ item->if_index = if_index;
+ item->Next = NULL;
+ AddToTail(list, item);
+}
+
#if MDNS_DEBUGMSGS
mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
{
@@ -1485,14 +1519,13 @@ mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
}
#endif
-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
+mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces)
// Read through the messages on sd and if any indicate that any interface records should
// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
{
ssize_t readCount;
char buff[4096];
struct nlmsghdr *pNLMsg = (struct nlmsghdr*) buff;
- mDNSu32 result = 0;
// The structure here is more complex than it really ought to be because,
// unfortunately, there's no good way to size a buffer in advance large
@@ -1528,9 +1561,9 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
// Process the NetLink message
if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
- result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
+ AddInterfaceIndexToList(changedInterfaces, ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index);
else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
- result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
+ AddInterfaceIndexToList(changedInterfaces, ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index);
// Advance pNLMsg to the next message in the buffer
if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
@@ -1541,8 +1574,6 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
else
break; // all done!
}
-
- return result;
}
#else // USES_NETLINK
@@ -1574,14 +1605,13 @@ mDNSlocal void PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
}
#endif
-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
+mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces)
// Read through the messages on sd and if any indicate that any interface records should
// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
{
ssize_t readCount;
char buff[4096];
struct ifa_msghdr *pRSMsg = (struct ifa_msghdr*) buff;
- mDNSu32 result = 0;
readCount = read(sd, buff, sizeof buff);
if (readCount < (ssize_t) sizeof(struct ifa_msghdr))
@@ -1596,12 +1626,10 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
pRSMsg->ifam_type == RTM_IFINFO)
{
if (pRSMsg->ifam_type == RTM_IFINFO)
- result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index;
+ AddInterfaceIndexToList(changedInterfaces, ((struct if_msghdr*) pRSMsg)->ifm_index);
else
- result |= 1 << pRSMsg->ifam_index;
+ AddInterfaceIndexToList(changedInterfaces, pRSMsg->ifam_index);
}
-
- return result;
}
#endif // USES_NETLINK
@@ -1611,7 +1639,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context)
{
IfChangeRec *pChgRec = (IfChangeRec*) context;
fd_set readFDs;
- mDNSu32 changedInterfaces = 0;
+ GenLinkedList changedInterfaces;
+ NetworkInterfaceIndex *changedInterface;
struct timeval zeroTimeout = { 0, 0 };
(void)fd; // Unused
@@ -1619,17 +1648,25 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context)
FD_ZERO(&readFDs);
FD_SET(pChgRec->NotifySD, &readFDs);
+ InitLinkedList(&changedInterfaces, offsetof(NetworkInterfaceIndex, Next));
+
do
{
- changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD);
+ ProcessRoutingNotification(pChgRec->NotifySD, &changedInterfaces);
}
while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout));
// Currently we rebuild the entire interface list whenever any interface change is
// detected. If this ever proves to be a performance issue in a multi-homed
// configuration, more care should be paid to changedInterfaces.
- if (changedInterfaces)
+ if (changedInterfaces.Head != NULL)
mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS);
+
+ while ((changedInterface = (NetworkInterfaceIndex*)changedInterfaces.Head) != NULL)
+ {
+ RemoveFromList(&changedInterfaces, changedInterface);
+ free(changedInterface);
+ }
}
// Register with either a Routing Socket or RtNetLink to listen for interface changes.
--
2.20.1