1From e79f81f5cd626ad77ec64de4325f6645cf253c5e Mon Sep 17 00:00:00 2001 2From: Nate Karstens <nate.karstens@garmin.com> 3Date: Thu, 13 Jul 2017 09:00:00 -0500 4Subject: [PATCH 5/8] Use list for changed interfaces 5 6Uses a linked list to store the index of changed network interfaces 7instead of a bitfield. This allows for network interfaces with an 8index greater than 31 (an index of 36 was seen on Android). 9 10Upstream-Status: Submitted [dts@apple.com] 11 12Signed-off-by: Nate Karstens <nate.karstens@garmin.com> 13Signed-off-by: Alex Kiernan <alex.kiernan@gmail.com> 14--- 15 mDNSPosix/mDNSPosix.c | 58 ++++++++++++++++++++++++++++++++----------- 16 1 file changed, 43 insertions(+), 15 deletions(-) 17 18Index: mDNSResponder/mDNSPosix/mDNSPosix.c 19=================================================================== 20--- mDNSResponder.orig/mDNSPosix/mDNSPosix.c 21+++ mDNSResponder/mDNSPosix/mDNSPosix.c 22@@ -74,6 +74,14 @@ struct IfChangeRec 23 }; 24 typedef struct IfChangeRec IfChangeRec; 25 26+// Used to build a list of network interface indices 27+struct NetworkInterfaceIndex 28+{ 29+ int if_index; 30+ struct NetworkInterfaceIndex *Next; 31+}; 32+typedef struct NetworkInterfaceIndex NetworkInterfaceIndex; 33+ 34 // Note that static data is initialized to zero in (modern) C. 35 static PosixEventSource *gEventSources; // linked list of PosixEventSource's 36 static sigset_t gEventSignalSet; // Signals which event loop listens for 37@@ -1621,6 +1629,23 @@ mDNSlocal mStatus OpenIfNotifySocket(int 38 return err; 39 } 40 41+mDNSlocal void AddInterfaceIndexToList(GenLinkedList *list, int if_index) 42+{ 43+ NetworkInterfaceIndex *item; 44+ 45+ for (item = (NetworkInterfaceIndex*)list->Head; item != NULL; item = item->Next) 46+ { 47+ if (if_index == item->if_index) return; 48+ } 49+ 50+ item = mdns_malloc(sizeof *item); 51+ if (item == NULL) return; 52+ 53+ item->if_index = if_index; 54+ item->Next = NULL; 55+ AddToTail(list, item); 56+} 57+ 58 #if MDNS_DEBUGMSGS 59 mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg) 60 { 61@@ -1648,14 +1673,13 @@ mDNSlocal void PrintNetLinkMsg(cons 62 } 63 #endif 64 65-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 66+mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces) 67 // Read through the messages on sd and if any indicate that any interface records should 68 // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. 69 { 70 ssize_t readCount; 71 char buff[4096]; 72 struct nlmsghdr *pNLMsg = (struct nlmsghdr*) buff; 73- mDNSu32 result = 0; 74 75 // The structure here is more complex than it really ought to be because, 76 // unfortunately, there's no good way to size a buffer in advance large 77@@ -1691,9 +1715,9 @@ mDNSlocal mDNSu32 ProcessRoutingNo 78 79 // Process the NetLink message 80 if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK) 81- result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index; 82+ AddInterfaceIndexToList(changedInterfaces, ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index); 83 else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR) 84- result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index; 85+ AddInterfaceIndexToList(changedInterfaces, ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index); 86 87 // Advance pNLMsg to the next message in the buffer 88 if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE) 89@@ -1704,8 +1728,6 @@ mDNSlocal mDNSu32 ProcessRoutingNo 90 else 91 break; // all done! 92 } 93- 94- return result; 95 } 96 97 #else // USES_NETLINK 98@@ -1737,14 +1759,13 @@ mDNSlocal void PrintRoutingSocketMs 99 } 100 #endif 101 102-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 103+mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces) 104 // Read through the messages on sd and if any indicate that any interface records should 105 // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. 106 { 107 ssize_t readCount; 108 char buff[4096]; 109 struct ifa_msghdr *pRSMsg = (struct ifa_msghdr*) buff; 110- mDNSu32 result = 0; 111 112 readCount = read(sd, buff, sizeof buff); 113 if (readCount < (ssize_t) sizeof(struct ifa_msghdr)) 114@@ -1759,12 +1780,10 @@ mDNSlocal mDNSu32 ProcessRoutingNo 115 pRSMsg->ifam_type == RTM_IFINFO) 116 { 117 if (pRSMsg->ifam_type == RTM_IFINFO) 118- result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; 119+ AddInterfaceIndexToList(changedInterfaces, ((struct if_msghdr*) pRSMsg)->ifm_index); 120 else 121- result |= 1 << pRSMsg->ifam_index; 122+ AddInterfaceIndexToList(changedInterfaces, pRSMsg->ifam_index); 123 } 124- 125- return result; 126 } 127 128 #endif // USES_NETLINK 129@@ -1774,7 +1793,8 @@ mDNSlocal void InterfaceChangeCallback(i 130 { 131 IfChangeRec *pChgRec = (IfChangeRec*) context; 132 fd_set readFDs; 133- mDNSu32 changedInterfaces = 0; 134+ GenLinkedList changedInterfaces; 135+ NetworkInterfaceIndex *changedInterface; 136 struct timeval zeroTimeout = { 0, 0 }; 137 138 (void)fd; // Unused 139@@ -1782,17 +1802,25 @@ mDNSlocal void InterfaceChangeCallback(i 140 FD_ZERO(&readFDs); 141 FD_SET(pChgRec->NotifySD, &readFDs); 142 143+ InitLinkedList(&changedInterfaces, offsetof(NetworkInterfaceIndex, Next)); 144+ 145 do 146 { 147- changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD); 148+ ProcessRoutingNotification(pChgRec->NotifySD, &changedInterfaces); 149 } 150 while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout)); 151 152 // Currently we rebuild the entire interface list whenever any interface change is 153 // detected. If this ever proves to be a performance issue in a multi-homed 154 // configuration, more care should be paid to changedInterfaces. 155- if (changedInterfaces) 156+ if (changedInterfaces.Head != NULL) 157 mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS); 158+ 159+ while ((changedInterface = (NetworkInterfaceIndex*)changedInterfaces.Head) != NULL) 160+ { 161+ RemoveFromList(&changedInterfaces, changedInterface); 162+ mdns_free(changedInterface); 163+ } 164 } 165 166 // Register with either a Routing Socket or RtNetLink to listen for interface changes. 167