Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame^] | 1 | From e79f81f5cd626ad77ec64de4325f6645cf253c5e Mon Sep 17 00:00:00 2001 |
| 2 | From: Nate Karstens <nate.karstens@garmin.com> |
| 3 | Date: Thu, 13 Jul 2017 09:00:00 -0500 |
| 4 | Subject: [PATCH 5/8] 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 | Signed-off-by: Alex Kiernan <alex.kiernan@gmail.com> |
| 14 | --- |
| 15 | mDNSPosix/mDNSPosix.c | 58 ++++++++++++++++++++++++++++++++----------- |
| 16 | 1 file changed, 43 insertions(+), 15 deletions(-) |
| 17 | |
| 18 | diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c |
| 19 | index 02a19b438e03..e20adda92229 100644 |
| 20 | --- a/mDNSPosix/mDNSPosix.c |
| 21 | +++ b/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 *pFD) |
| 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(const struct nlmsghdr *pNLMsg) |
| 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 ProcessRoutingNotification(int sd) |
| 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 ProcessRoutingNotification(int sd) |
| 90 | else |
| 91 | break; // all done! |
| 92 | } |
| 93 | - |
| 94 | - return result; |
| 95 | } |
| 96 | |
| 97 | #else // USES_NETLINK |
| 98 | @@ -1737,14 +1759,13 @@ mDNSlocal void PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg) |
| 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 ProcessRoutingNotification(int sd) |
| 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(int fd, void *context) |
| 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(int fd, void *context) |
| 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 | -- |
| 168 | 2.35.1 |
| 169 | |