| 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 |
| |