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