]> git.saurik.com Git - apple/configd.git/blob - Plugins/KernelEventMonitor/ev_ipv4.c
configd-963.200.27.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / ev_ipv4.c
1 /*
2 * Copyright (c) 2002-2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * August 5, 2002 Allan Nathanson <ajn@apple.com>
28 * - split code out from eventmon.c
29 */
30
31 #include "eventmon.h"
32 #include "cache.h"
33 #include "ev_ipv4.h"
34
35 #ifndef kSCEntNetIPv4ARPCollision
36 #define kSCEntNetIPv4ARPCollision CFSTR("IPv4ARPCollision")
37 #endif /* kSCEntNetIPv4ARPCollision */
38
39 #if !TARGET_OS_IPHONE
40 #ifndef kSCEntNetIPv4PortInUse
41 #define kSCEntNetIPv4PortInUse CFSTR("PortInUse")
42 #endif /* kSCEntNetIPv4PortInUse */
43 #endif /* !TARGET_OS_IPHONE */
44
45 #define IP_FORMAT "%d.%d.%d.%d"
46 #define IP_CH(ip, i) (((u_char *)(ip))[i])
47 #define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
48
49
50 static void
51 appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct in_addr *address)
52 {
53 CFStringRef addr;
54 CFArrayRef addrs;
55 CFMutableArrayRef newAddrs;
56
57 addrs = CFDictionaryGetValue(dict, key);
58 if (addrs) {
59 newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
60 } else {
61 newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
62 }
63
64 addr = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(address));
65 CFArrayAppendValue(newAddrs, addr);
66 CFRelease(addr);
67
68 CFDictionarySetValue(dict, key, newAddrs);
69 CFRelease(newAddrs);
70 return;
71 }
72
73
74 static CFMutableDictionaryRef
75 copyIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
76 {
77 CFDictionaryRef dict = NULL;
78 CFMutableDictionaryRef newDict = NULL;
79
80 if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
81 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
82 } else {
83 dict = cache_SCDynamicStoreCopyValue(store, key);
84 if (dict) {
85 CFDictionarySetValue(oldIFs, key, dict);
86 if (isA_CFDictionary(dict)) {
87 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
88 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4Addresses);
89 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4SubnetMasks);
90 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4DestAddresses);
91 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4BroadcastAddresses);
92 }
93 CFRelease(dict);
94 }
95 }
96
97 if (!newDict) {
98 newDict = CFDictionaryCreateMutable(NULL,
99 0,
100 &kCFTypeDictionaryKeyCallBacks,
101 &kCFTypeDictionaryValueCallBacks);
102 }
103
104 return newDict;
105 }
106
107
108 static void
109 updateStore(const void *key, const void *value, void *context)
110 {
111 CFDictionaryRef dict;
112 CFDictionaryRef newDict = (CFDictionaryRef)value;
113 CFDictionaryRef oldIFs = (CFDictionaryRef)context;
114
115 dict = CFDictionaryGetValue(oldIFs, key);
116
117 if (!dict || !CFEqual(dict, newDict)) {
118 if (CFDictionaryGetCount(newDict) > 0) {
119 SC_log(LOG_DEBUG, "Update interface configuration: %@: %@", key, newDict);
120 cache_SCDynamicStoreSetValue(store, key, newDict);
121 } else if (dict) {
122 CFDictionaryRef oldDict;
123
124 oldDict = cache_SCDynamicStoreCopyValue(store, key);
125 if (oldDict != NULL) {
126 SC_log(LOG_DEBUG, "Update interface configuration: %@: <removed>", key);
127 CFRelease(oldDict);
128 }
129 cache_SCDynamicStoreRemoveValue(store, key);
130 }
131 network_changed = TRUE;
132 }
133
134 return;
135 }
136
137
138 __private_extern__
139 void
140 ipv4_interface_update(struct ifaddrs *ifap, const char *if_name)
141 {
142 struct ifaddrs *ifa;
143 struct ifaddrs *ifap_temp = NULL;
144 CFStringRef interface;
145 boolean_t interfaceFound = FALSE;
146 CFStringRef key = NULL;
147 CFMutableDictionaryRef oldIFs;
148 CFMutableDictionaryRef newDict = NULL;
149 CFMutableDictionaryRef newIFs;
150
151 oldIFs = CFDictionaryCreateMutable(NULL,
152 0,
153 &kCFTypeDictionaryKeyCallBacks,
154 &kCFTypeDictionaryValueCallBacks);
155 newIFs = CFDictionaryCreateMutable(NULL,
156 0,
157 &kCFTypeDictionaryKeyCallBacks,
158 &kCFTypeDictionaryValueCallBacks);
159
160 if (!ifap) {
161 if (getifaddrs(&ifap_temp) == -1) {
162 SC_log(LOG_NOTICE, "getifaddrs() failed: %s", strerror(errno));
163 goto error;
164 }
165 ifap = ifap_temp;
166 }
167
168 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
169 struct sockaddr_in *sin;
170
171 if (ifa->ifa_addr->sa_family != AF_INET) {
172 continue; /* sorry, not interested */
173 }
174
175 /* check if this is the requested interface */
176 if (if_name) {
177 if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
178 interfaceFound = TRUE; /* yes, this is the one I want */
179 } else {
180 continue; /* sorry, not interested */
181 }
182 }
183
184 interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
185 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
186 kSCDynamicStoreDomainState,
187 interface,
188 kSCEntNetIPv4);
189 CFRelease(interface);
190
191 newDict = copyIF(key, oldIFs, newIFs);
192
193 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
194 sin = (struct sockaddr_in *)(void *)ifa->ifa_addr;
195 appendAddress(newDict, kSCPropNetIPv4Addresses, &sin->sin_addr);
196
197 if (ifa->ifa_flags & IFF_POINTOPOINT) {
198 struct sockaddr_in *dst;
199
200 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
201 dst = (struct sockaddr_in *)(void *)ifa->ifa_dstaddr;
202 appendAddress(newDict, kSCPropNetIPv4DestAddresses, &dst->sin_addr);
203 } else {
204 struct sockaddr_in *brd;
205 struct sockaddr_in *msk;
206
207 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
208 brd = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
209 appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses,&brd->sin_addr);
210
211 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
212 msk = (struct sockaddr_in *)(void *)ifa->ifa_netmask;
213 appendAddress(newDict, kSCPropNetIPv4SubnetMasks, &msk->sin_addr);
214 }
215
216 CFDictionarySetValue(newIFs, key, newDict);
217 CFRelease(newDict);
218 CFRelease(key);
219 }
220
221 /* if the last address[es] were removed from the target interface */
222 if (if_name && !interfaceFound) {
223 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
224 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
225 kSCDynamicStoreDomainState,
226 interface,
227 kSCEntNetIPv4);
228 CFRelease(interface);
229
230 newDict = copyIF(key, oldIFs, newIFs);
231
232 CFDictionarySetValue(newIFs, key, newDict);
233 CFRelease(newDict);
234 CFRelease(key);
235 }
236
237 CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
238
239 error :
240
241 if (ifap_temp) freeifaddrs(ifap_temp);
242 CFRelease(oldIFs);
243 CFRelease(newIFs);
244
245 return;
246 }
247
248 __private_extern__
249 void
250 ipv4_arp_collision(const char *if_name, struct in_addr ip_addr, int hw_len, const void * hw_addr)
251 {
252 uint8_t * hw_addr_bytes = (uint8_t *)hw_addr;
253 int i;
254 CFStringRef if_name_cf;
255 CFMutableStringRef key;
256 CFStringRef prefix;
257
258 if_name_cf = CFStringCreateWithCString(NULL, if_name,
259 kCFStringEncodingASCII);
260 prefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
261 kSCDynamicStoreDomainState,
262 if_name_cf,
263 kSCEntNetIPv4ARPCollision);
264 key = CFStringCreateMutableCopy(NULL, 0, prefix);
265 CFStringAppendFormat(key, NULL, CFSTR("/" IP_FORMAT),
266 IP_LIST(&ip_addr));
267 for (i = 0; i < hw_len; i++) {
268 CFStringAppendFormat(key, NULL, CFSTR("%s%02x"),
269 (i == 0) ? "/" : ":", hw_addr_bytes[i]);
270 }
271 SC_log(LOG_DEBUG, "Post ARP collision: %@", key);
272 cache_SCDynamicStoreNotifyValue(store, key);
273 CFRelease(key);
274 CFRelease(prefix);
275 CFRelease(if_name_cf);
276 return;
277 }
278
279 #if !TARGET_OS_IPHONE
280 __private_extern__
281 void
282 ipv4_port_in_use(uint16_t port, pid_t req_pid)
283 {
284 CFStringRef key;
285
286 key = SCDynamicStoreKeyCreate(NULL,
287 CFSTR("%@/%@/Protocol/%@/%@/%d/%d"),
288 kSCDynamicStoreDomainState,
289 kSCCompNetwork,
290 kSCEntNetIPv4,
291 kSCEntNetIPv4PortInUse,
292 port, req_pid);
293 SC_log(LOG_DEBUG, "Post port-in-use: %@", key);
294 cache_SCDynamicStoreNotifyValue(store, key);
295 CFRelease(key);
296 return;
297 }
298 #endif /* !TARGET_OS_IPHONE */
299
300 static void
301 interface_notify_entity(const char * if_name, const char * type, CFStringRef entity)
302 {
303 CFStringRef if_name_cf;
304 CFStringRef key;
305
306 if_name_cf = CFStringCreateWithCString(NULL, if_name,
307 kCFStringEncodingASCII);
308 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
309 kSCDynamicStoreDomainState,
310 if_name_cf,
311 entity);
312 CFRelease(if_name_cf);
313 SC_log(LOG_DEBUG, "Post %s: %@", type, key);
314 cache_SCDynamicStoreNotifyValue(store, key);
315 CFRelease(key);
316 return;
317 }
318
319 __private_extern__ void
320 ipv4_router_arp_failure(const char * if_name)
321 {
322 interface_notify_entity(if_name, "Router ARP failure", kSCEntNetIPv4RouterARPFailure);
323 return;
324 }
325
326 __private_extern__ void
327 ipv4_router_arp_alive(const char * if_name)
328 {
329 interface_notify_entity(if_name, "Router ARP alive", kSCEntNetIPv4RouterARPAlive);
330 return;
331 }