aboutsummaryrefslogtreecommitdiffstats
path: root/meta-networking/recipes-protocols/mdns/files/0004-Use-list-for-changed-interfaces.patch
blob: 05ad49b9f9052940f6a355965bdf69f810dbd42d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
From e1f483510a1011e37540fdee8f3bc36111fa45a0 Mon Sep 17 00:00:00 2001
From: Nate Karstens <nate.karstens@garmin.com>
Date: Thu, 13 Jul 2017 09:00:00 -0500
Subject: [PATCH 04/11] Use list for changed interfaces

Uses a linked list to store the index of changed network interfaces
instead of a bitfield. This allows for network interfaces with an
index greater than 31 (an index of 36 was seen on Android).

Upstream-Status: Submitted [dts@apple.com]

Signed-off-by: Nate Karstens <nate.karstens@garmin.com>
---
 mDNSPosix/mDNSPosix.c | 67 +++++++++++++++++++++++++++++++++----------
 1 file changed, 52 insertions(+), 15 deletions(-)

diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
index 8fe22be..699855a 100644
--- a/mDNSPosix/mDNSPosix.c
+++ b/mDNSPosix/mDNSPosix.c
@@ -75,6 +75,14 @@ struct IfChangeRec
 };
 typedef struct IfChangeRec IfChangeRec;
 
+// Used to build a list of network interface indices
+struct NetworkInterfaceIndex
+{
+    int if_index;
+    struct NetworkInterfaceIndex *Next;
+};
+typedef struct NetworkInterfaceIndex NetworkInterfaceIndex;
+
 // Note that static data is initialized to zero in (modern) C.
 static fd_set gEventFDs;
 static int gMaxFD;                              // largest fd in gEventFDs
@@ -1071,6 +1079,32 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
     return err;
 }
 
+mDNSlocal mDNSBool ListContainsInterfaceIndex(GenLinkedList *list, int if_index)
+{
+    NetworkInterfaceIndex *item;
+
+    for (item = (NetworkInterfaceIndex*)list->Head; item != NULL; item = item->Next)
+    {
+        if (if_index == item->if_index) return mDNStrue;
+    }
+
+    return mDNSfalse;
+}
+
+mDNSlocal void AddInterfaceIndexToList(GenLinkedList *list, int if_index)
+{
+    NetworkInterfaceIndex *item;
+
+    if (ListContainsInterfaceIndex(list, if_index)) return;
+
+    item = malloc(sizeof *item);
+    if (item == NULL) return;
+
+    item->if_index = if_index;
+    item->Next = NULL;
+    AddToTail(list, item);
+}
+
 #if MDNS_DEBUGMSGS
 mDNSlocal void      PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
 {
@@ -1098,14 +1132,13 @@ mDNSlocal void      PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
 }
 #endif
 
-mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
+mDNSlocal void          ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces)
 // Read through the messages on sd and if any indicate that any interface records should
 // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
 {
     ssize_t readCount;
     char buff[4096];
     struct nlmsghdr         *pNLMsg = (struct nlmsghdr*) buff;
-    mDNSu32 result = 0;
 
     // The structure here is more complex than it really ought to be because,
     // unfortunately, there's no good way to size a buffer in advance large
@@ -1141,9 +1174,9 @@ mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
 
         // Process the NetLink message
         if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
-            result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
+            AddInterfaceIndexToList(changedInterfaces, ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index);
         else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
-            result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
+            AddInterfaceIndexToList(changedInterfaces, ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index);
 
         // Advance pNLMsg to the next message in the buffer
         if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
@@ -1154,8 +1187,6 @@ mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
         else
             break;  // all done!
     }
-
-    return result;
 }
 
 #else // USES_NETLINK
@@ -1187,14 +1218,13 @@ mDNSlocal void      PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
 }
 #endif
 
-mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
+mDNSlocal void          ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces)
 // Read through the messages on sd and if any indicate that any interface records should
 // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
 {
     ssize_t readCount;
     char buff[4096];
     struct ifa_msghdr       *pRSMsg = (struct ifa_msghdr*) buff;
-    mDNSu32 result = 0;
 
     readCount = read(sd, buff, sizeof buff);
     if (readCount < (ssize_t) sizeof(struct ifa_msghdr))
@@ -1209,12 +1239,10 @@ mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
         pRSMsg->ifam_type == RTM_IFINFO)
     {
         if (pRSMsg->ifam_type == RTM_IFINFO)
-            result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index;
+            AddInterfaceIndexToList(changedInterfaces, ((struct if_msghdr*) pRSMsg)->ifm_index);
         else
-            result |= 1 << pRSMsg->ifam_index;
+            AddInterfaceIndexToList(changedInterfaces, pRSMsg->ifam_index);
     }
-
-    return result;
 }
 
 #endif // USES_NETLINK
@@ -1224,7 +1252,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, short filter, void *context)
 {
     IfChangeRec     *pChgRec = (IfChangeRec*) context;
     fd_set readFDs;
-    mDNSu32 changedInterfaces = 0;
+    GenLinkedList changedInterfaces;
+    NetworkInterfaceIndex *changedInterface;
     struct timeval zeroTimeout = { 0, 0 };
 
     (void)fd; // Unused
@@ -1233,17 +1262,25 @@ mDNSlocal void InterfaceChangeCallback(int fd, short filter, void *context)
     FD_ZERO(&readFDs);
     FD_SET(pChgRec->NotifySD, &readFDs);
 
+    InitLinkedList(&changedInterfaces, offsetof(NetworkInterfaceIndex, Next));
+
     do
     {
-        changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD);
+        ProcessRoutingNotification(pChgRec->NotifySD, &changedInterfaces);
     }
     while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout));
 
     // Currently we rebuild the entire interface list whenever any interface change is
     // detected. If this ever proves to be a performance issue in a multi-homed
     // configuration, more care should be paid to changedInterfaces.
-    if (changedInterfaces)
+    if (changedInterfaces.Head != NULL)
         mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS);
+
+    while ((changedInterface = (NetworkInterfaceIndex*)changedInterfaces.Head) != NULL)
+    {
+        RemoveFromList(&changedInterfaces, changedInterface);
+        free(changedInterface);
+    }
 }
 
 // Register with either a Routing Socket or RtNetLink to listen for interface changes.
-- 
2.17.1