1From 798bfb5e984845a27874d1a244686db6e384d7b8 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 04/11] 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> 13--- 14 mDNSPosix/mDNSPosix.c | 67 +++++++++++++++++++++++++++++++++---------- 15 1 file changed, 52 insertions(+), 15 deletions(-) 16 17diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c 18index 195d04b..bb883c1 100755 19--- a/mDNSPosix/mDNSPosix.c 20+++ b/mDNSPosix/mDNSPosix.c 21@@ -67,6 +67,14 @@ struct IfChangeRec 22 }; 23 typedef struct IfChangeRec IfChangeRec; 24 25+// Used to build a list of network interface indices 26+struct NetworkInterfaceIndex 27+{ 28+ int if_index; 29+ struct NetworkInterfaceIndex *Next; 30+}; 31+typedef struct NetworkInterfaceIndex NetworkInterfaceIndex; 32+ 33 // Note that static data is initialized to zero in (modern) C. 34 static PosixEventSource *gEventSources; // linked list of PosixEventSource's 35 static sigset_t gEventSignalSet; // Signals which event loop listens for 36@@ -1458,6 +1466,32 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD) 37 return err; 38 } 39 40+mDNSlocal mDNSBool ListContainsInterfaceIndex(GenLinkedList *list, int if_index) 41+{ 42+ NetworkInterfaceIndex *item; 43+ 44+ for (item = (NetworkInterfaceIndex*)list->Head; item != NULL; item = item->Next) 45+ { 46+ if (if_index == item->if_index) return mDNStrue; 47+ } 48+ 49+ return mDNSfalse; 50+} 51+ 52+mDNSlocal void AddInterfaceIndexToList(GenLinkedList *list, int if_index) 53+{ 54+ NetworkInterfaceIndex *item; 55+ 56+ if (ListContainsInterfaceIndex(list, if_index)) return; 57+ 58+ item = malloc(sizeof *item); 59+ if (item == NULL) return; 60+ 61+ item->if_index = if_index; 62+ item->Next = NULL; 63+ AddToTail(list, item); 64+} 65+ 66 #if MDNS_DEBUGMSGS 67 mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg) 68 { 69@@ -1485,14 +1519,13 @@ mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg) 70 } 71 #endif 72 73-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 74+mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces) 75 // Read through the messages on sd and if any indicate that any interface records should 76 // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. 77 { 78 ssize_t readCount; 79 char buff[4096]; 80 struct nlmsghdr *pNLMsg = (struct nlmsghdr*) buff; 81- mDNSu32 result = 0; 82 83 // The structure here is more complex than it really ought to be because, 84 // unfortunately, there's no good way to size a buffer in advance large 85@@ -1528,9 +1561,9 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 86 87 // Process the NetLink message 88 if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK) 89- result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index; 90+ AddInterfaceIndexToList(changedInterfaces, ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index); 91 else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR) 92- result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index; 93+ AddInterfaceIndexToList(changedInterfaces, ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index); 94 95 // Advance pNLMsg to the next message in the buffer 96 if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE) 97@@ -1541,8 +1574,6 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 98 else 99 break; // all done! 100 } 101- 102- return result; 103 } 104 105 #else // USES_NETLINK 106@@ -1574,14 +1605,13 @@ mDNSlocal void PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg) 107 } 108 #endif 109 110-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 111+mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces) 112 // Read through the messages on sd and if any indicate that any interface records should 113 // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. 114 { 115 ssize_t readCount; 116 char buff[4096]; 117 struct ifa_msghdr *pRSMsg = (struct ifa_msghdr*) buff; 118- mDNSu32 result = 0; 119 120 readCount = read(sd, buff, sizeof buff); 121 if (readCount < (ssize_t) sizeof(struct ifa_msghdr)) 122@@ -1596,12 +1626,10 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) 123 pRSMsg->ifam_type == RTM_IFINFO) 124 { 125 if (pRSMsg->ifam_type == RTM_IFINFO) 126- result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; 127+ AddInterfaceIndexToList(changedInterfaces, ((struct if_msghdr*) pRSMsg)->ifm_index); 128 else 129- result |= 1 << pRSMsg->ifam_index; 130+ AddInterfaceIndexToList(changedInterfaces, pRSMsg->ifam_index); 131 } 132- 133- return result; 134 } 135 136 #endif // USES_NETLINK 137@@ -1611,7 +1639,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) 138 { 139 IfChangeRec *pChgRec = (IfChangeRec*) context; 140 fd_set readFDs; 141- mDNSu32 changedInterfaces = 0; 142+ GenLinkedList changedInterfaces; 143+ NetworkInterfaceIndex *changedInterface; 144 struct timeval zeroTimeout = { 0, 0 }; 145 146 (void)fd; // Unused 147@@ -1619,17 +1648,25 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) 148 FD_ZERO(&readFDs); 149 FD_SET(pChgRec->NotifySD, &readFDs); 150 151+ InitLinkedList(&changedInterfaces, offsetof(NetworkInterfaceIndex, Next)); 152+ 153 do 154 { 155- changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD); 156+ ProcessRoutingNotification(pChgRec->NotifySD, &changedInterfaces); 157 } 158 while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout)); 159 160 // Currently we rebuild the entire interface list whenever any interface change is 161 // detected. If this ever proves to be a performance issue in a multi-homed 162 // configuration, more care should be paid to changedInterfaces. 163- if (changedInterfaces) 164+ if (changedInterfaces.Head != NULL) 165 mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS); 166+ 167+ while ((changedInterface = (NetworkInterfaceIndex*)changedInterfaces.Head) != NULL) 168+ { 169+ RemoveFromList(&changedInterfaces, changedInterface); 170+ free(changedInterface); 171+ } 172 } 173 174 // Register with either a Routing Socket or RtNetLink to listen for interface changes. 175-- 1762.20.1 177 178