blob: db3a63ea483fc8ced24b35f242d8777128b6ff19 [file] [log] [blame]
Andrew Geisslerd688a012020-09-18 13:36:00 -05001From 798bfb5e984845a27874d1a244686db6e384d7b8 Mon Sep 17 00:00:00 2001
Andrew Geissler82c905d2020-04-13 13:39:40 -05002From: 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
Andrew Geisslerd688a012020-09-18 13:36:00 -050018index 195d04b..bb883c1 100755
Andrew Geissler82c905d2020-04-13 13:39:40 -050019--- a/mDNSPosix/mDNSPosix.c
20+++ b/mDNSPosix/mDNSPosix.c
Andrew Geisslerd688a012020-09-18 13:36:00 -050021@@ -67,6 +67,14 @@ struct IfChangeRec
Andrew Geissler82c905d2020-04-13 13:39:40 -050022 };
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 Geisslerd688a012020-09-18 13:36:00 -050034 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 Geissler82c905d2020-04-13 13:39:40 -050037 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 Geisslerd688a012020-09-18 13:36:00 -050069@@ -1485,14 +1519,13 @@ mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
Andrew Geissler82c905d2020-04-13 13:39:40 -050070 }
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 Geisslerd688a012020-09-18 13:36:00 -050085@@ -1528,9 +1561,9 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
Andrew Geissler82c905d2020-04-13 13:39:40 -050086
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 Geisslerd688a012020-09-18 13:36:00 -050097@@ -1541,8 +1574,6 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
Andrew Geissler82c905d2020-04-13 13:39:40 -050098 else
99 break; // all done!
100 }
101-
102- return result;
103 }
104
105 #else // USES_NETLINK
Andrew Geisslerd688a012020-09-18 13:36:00 -0500106@@ -1574,14 +1605,13 @@ mDNSlocal void PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500107 }
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 Geisslerd688a012020-09-18 13:36:00 -0500122@@ -1596,12 +1626,10 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500123 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 Geisslerd688a012020-09-18 13:36:00 -0500137@@ -1611,7 +1639,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500138 {
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 Geisslerd688a012020-09-18 13:36:00 -0500147@@ -1619,17 +1648,25 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500148 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 Geisslerd688a012020-09-18 13:36:00 -05001762.20.1
Andrew Geissler82c905d2020-04-13 13:39:40 -0500177