blob: 1aec34f24300abf01d7d32f0db21bf6a3e07a3cf [file] [log] [blame]
Andrew Geissler517393d2023-01-13 08:55:19 -06001From 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
18diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
19index 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--
1682.35.1
169