Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 1 | From 798bfb5e984845a27874d1a244686db6e384d7b8 Mon Sep 17 00:00:00 2001 |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 2 | From: Nate Karstens <nate.karstens@garmin.com> |
| 3 | Date: Thu, 13 Jul 2017 09:00:00 -0500 |
| 4 | Subject: [PATCH 04/11] Use list for changed interfaces |
| 5 | |
| 6 | Uses a linked list to store the index of changed network interfaces |
| 7 | instead of a bitfield. This allows for network interfaces with an |
| 8 | index greater than 31 (an index of 36 was seen on Android). |
| 9 | |
| 10 | Upstream-Status: Submitted [dts@apple.com] |
| 11 | |
| 12 | Signed-off-by: Nate Karstens <nate.karstens@garmin.com> |
| 13 | --- |
| 14 | mDNSPosix/mDNSPosix.c | 67 +++++++++++++++++++++++++++++++++---------- |
| 15 | 1 file changed, 52 insertions(+), 15 deletions(-) |
| 16 | |
| 17 | diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 18 | index 195d04b..bb883c1 100755 |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 19 | --- a/mDNSPosix/mDNSPosix.c |
| 20 | +++ b/mDNSPosix/mDNSPosix.c |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 21 | @@ -67,6 +67,14 @@ struct IfChangeRec |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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. |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 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) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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 | { |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 69 | @@ -1485,14 +1519,13 @@ mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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 |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 85 | @@ -1528,9 +1561,9 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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) |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 97 | @@ -1541,8 +1574,6 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 98 | else |
| 99 | break; // all done! |
| 100 | } |
| 101 | - |
| 102 | - return result; |
| 103 | } |
| 104 | |
| 105 | #else // USES_NETLINK |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 106 | @@ -1574,14 +1605,13 @@ mDNSlocal void PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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)) |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 122 | @@ -1596,12 +1626,10 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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 |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 137 | @@ -1611,7 +1639,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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 |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 147 | @@ -1619,17 +1648,25 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 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 | -- |
Andrew Geissler | d688a01 | 2020-09-18 13:36:00 -0500 | [diff] [blame] | 176 | 2.20.1 |
Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 177 | |