]> git.saurik.com Git - apple/configd.git/blame - Plugins/KernelEventMonitor/ev_ipv4.c
configd-1109.101.1.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / ev_ipv4.c
CommitLineData
dbf6a266 1/*
afb19109 2 * Copyright (c) 2002-2018 Apple Inc. All rights reserved.
dbf6a266
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
9de8ab86 5 *
dbf6a266
A
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.
9de8ab86 12 *
dbf6a266
A
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.
9de8ab86 20 *
dbf6a266
A
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"
dbf6a266
A
32#include "ev_ipv4.h"
33
dbf6a266
A
34#define IP_FORMAT "%d.%d.%d.%d"
35#define IP_CH(ip, i) (((u_char *)(ip))[i])
36#define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
37
38
39static void
40appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct in_addr *address)
41{
42 CFStringRef addr;
43 CFArrayRef addrs;
44 CFMutableArrayRef newAddrs;
45
46 addrs = CFDictionaryGetValue(dict, key);
47 if (addrs) {
48 newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
49 } else {
50 newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
51 }
52
53 addr = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(address));
54 CFArrayAppendValue(newAddrs, addr);
55 CFRelease(addr);
56
57 CFDictionarySetValue(dict, key, newAddrs);
58 CFRelease(newAddrs);
59 return;
60}
61
62
63static CFMutableDictionaryRef
17d3ee29 64copyIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
dbf6a266
A
65{
66 CFDictionaryRef dict = NULL;
67 CFMutableDictionaryRef newDict = NULL;
68
69 if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
70 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
71 } else {
afb19109 72 dict = SCDynamicStoreCopyValue(store, key);
dbf6a266
A
73 if (dict) {
74 CFDictionarySetValue(oldIFs, key, dict);
75 if (isA_CFDictionary(dict)) {
76 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
77 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4Addresses);
78 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4SubnetMasks);
79 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4DestAddresses);
80 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4BroadcastAddresses);
81 }
82 CFRelease(dict);
83 }
84 }
85
86 if (!newDict) {
87 newDict = CFDictionaryCreateMutable(NULL,
88 0,
89 &kCFTypeDictionaryKeyCallBacks,
90 &kCFTypeDictionaryValueCallBacks);
91 }
92
93 return newDict;
94}
95
96
97static void
98updateStore(const void *key, const void *value, void *context)
99{
100 CFDictionaryRef dict;
101 CFDictionaryRef newDict = (CFDictionaryRef)value;
102 CFDictionaryRef oldIFs = (CFDictionaryRef)context;
103
104 dict = CFDictionaryGetValue(oldIFs, key);
105
106 if (!dict || !CFEqual(dict, newDict)) {
107 if (CFDictionaryGetCount(newDict) > 0) {
9de8ab86 108 SC_log(LOG_DEBUG, "Update interface configuration: %@: %@", key, newDict);
afb19109 109 SCDynamicStoreSetValue(store, key, newDict);
dbf6a266 110 } else if (dict) {
1ef45fa4
A
111 CFDictionaryRef oldDict;
112
afb19109 113 oldDict = SCDynamicStoreCopyValue(store, key);
1ef45fa4
A
114 if (oldDict != NULL) {
115 SC_log(LOG_DEBUG, "Update interface configuration: %@: <removed>", key);
116 CFRelease(oldDict);
117 }
afb19109 118 SCDynamicStoreRemoveValue(store, key);
dbf6a266 119 }
edebe297 120 network_changed = TRUE;
dbf6a266
A
121 }
122
123 return;
124}
125
126
127__private_extern__
128void
78403150 129ipv4_interface_update(struct ifaddrs *ifap, const char *if_name)
dbf6a266
A
130{
131 struct ifaddrs *ifa;
132 struct ifaddrs *ifap_temp = NULL;
133 CFStringRef interface;
134 boolean_t interfaceFound = FALSE;
135 CFStringRef key = NULL;
136 CFMutableDictionaryRef oldIFs;
137 CFMutableDictionaryRef newDict = NULL;
138 CFMutableDictionaryRef newIFs;
139
140 oldIFs = CFDictionaryCreateMutable(NULL,
141 0,
142 &kCFTypeDictionaryKeyCallBacks,
143 &kCFTypeDictionaryValueCallBacks);
144 newIFs = CFDictionaryCreateMutable(NULL,
145 0,
146 &kCFTypeDictionaryKeyCallBacks,
147 &kCFTypeDictionaryValueCallBacks);
148
149 if (!ifap) {
edebe297 150 if (getifaddrs(&ifap_temp) == -1) {
9de8ab86 151 SC_log(LOG_NOTICE, "getifaddrs() failed: %s", strerror(errno));
dbf6a266
A
152 goto error;
153 }
154 ifap = ifap_temp;
155 }
156
157 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
158 struct sockaddr_in *sin;
159
160 if (ifa->ifa_addr->sa_family != AF_INET) {
161 continue; /* sorry, not interested */
162 }
163
164 /* check if this is the requested interface */
165 if (if_name) {
166 if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
167 interfaceFound = TRUE; /* yes, this is the one I want */
168 } else {
169 continue; /* sorry, not interested */
170 }
171 }
172
173 interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
174 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
175 kSCDynamicStoreDomainState,
176 interface,
177 kSCEntNetIPv4);
178 CFRelease(interface);
179
17d3ee29 180 newDict = copyIF(key, oldIFs, newIFs);
dbf6a266 181
17d3ee29
A
182 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
183 sin = (struct sockaddr_in *)(void *)ifa->ifa_addr;
dbf6a266
A
184 appendAddress(newDict, kSCPropNetIPv4Addresses, &sin->sin_addr);
185
186 if (ifa->ifa_flags & IFF_POINTOPOINT) {
187 struct sockaddr_in *dst;
188
17d3ee29
A
189 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
190 dst = (struct sockaddr_in *)(void *)ifa->ifa_dstaddr;
dbf6a266
A
191 appendAddress(newDict, kSCPropNetIPv4DestAddresses, &dst->sin_addr);
192 } else {
193 struct sockaddr_in *brd;
194 struct sockaddr_in *msk;
195
17d3ee29
A
196 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
197 brd = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
198 appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses,&brd->sin_addr);
199
200 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
201 msk = (struct sockaddr_in *)(void *)ifa->ifa_netmask;
dbf6a266
A
202 appendAddress(newDict, kSCPropNetIPv4SubnetMasks, &msk->sin_addr);
203 }
204
205 CFDictionarySetValue(newIFs, key, newDict);
206 CFRelease(newDict);
207 CFRelease(key);
208 }
209
210 /* if the last address[es] were removed from the target interface */
211 if (if_name && !interfaceFound) {
212 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
213 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
214 kSCDynamicStoreDomainState,
215 interface,
216 kSCEntNetIPv4);
217 CFRelease(interface);
218
17d3ee29 219 newDict = copyIF(key, oldIFs, newIFs);
dbf6a266
A
220
221 CFDictionarySetValue(newIFs, key, newDict);
222 CFRelease(newDict);
223 CFRelease(key);
224 }
225
226 CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
227
228 error :
229
230 if (ifap_temp) freeifaddrs(ifap_temp);
231 CFRelease(oldIFs);
232 CFRelease(newIFs);
233
234 return;
235}
236
237__private_extern__
238void
78403150 239ipv4_arp_collision(const char *if_name, struct in_addr ip_addr, int hw_len, const void * hw_addr)
dbf6a266
A
240{
241 uint8_t * hw_addr_bytes = (uint8_t *)hw_addr;
242 int i;
243 CFStringRef if_name_cf;
244 CFMutableStringRef key;
245 CFStringRef prefix;
246
247 if_name_cf = CFStringCreateWithCString(NULL, if_name,
248 kCFStringEncodingASCII);
249 prefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
250 kSCDynamicStoreDomainState,
251 if_name_cf,
252 kSCEntNetIPv4ARPCollision);
253 key = CFStringCreateMutableCopy(NULL, 0, prefix);
254 CFStringAppendFormat(key, NULL, CFSTR("/" IP_FORMAT),
255 IP_LIST(&ip_addr));
256 for (i = 0; i < hw_len; i++) {
257 CFStringAppendFormat(key, NULL, CFSTR("%s%02x"),
258 (i == 0) ? "/" : ":", hw_addr_bytes[i]);
259 }
9de8ab86 260 SC_log(LOG_DEBUG, "Post ARP collision: %@", key);
afb19109 261 SCDynamicStoreNotifyValue(store, key);
dbf6a266
A
262 CFRelease(key);
263 CFRelease(prefix);
264 CFRelease(if_name_cf);
265 return;
266}
edebe297 267
a40a14f8 268#if !TARGET_OS_IPHONE
edebe297
A
269__private_extern__
270void
78403150 271ipv4_port_in_use(uint16_t port, pid_t req_pid)
edebe297
A
272{
273 CFStringRef key;
274
275 key = SCDynamicStoreKeyCreate(NULL,
276 CFSTR("%@/%@/Protocol/%@/%@/%d/%d"),
277 kSCDynamicStoreDomainState,
278 kSCCompNetwork,
279 kSCEntNetIPv4,
280 kSCEntNetIPv4PortInUse,
281 port, req_pid);
9de8ab86 282 SC_log(LOG_DEBUG, "Post port-in-use: %@", key);
afb19109 283 SCDynamicStoreNotifyValue(store, key);
edebe297
A
284 CFRelease(key);
285 return;
286}
a40a14f8 287#endif /* !TARGET_OS_IPHONE */
78403150
A
288
289static void
9de8ab86 290interface_notify_entity(const char * if_name, const char * type, CFStringRef entity)
78403150
A
291{
292 CFStringRef if_name_cf;
293 CFStringRef key;
294
295 if_name_cf = CFStringCreateWithCString(NULL, if_name,
296 kCFStringEncodingASCII);
297 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
298 kSCDynamicStoreDomainState,
299 if_name_cf,
300 entity);
301 CFRelease(if_name_cf);
9de8ab86 302 SC_log(LOG_DEBUG, "Post %s: %@", type, key);
afb19109 303 SCDynamicStoreNotifyValue(store, key);
78403150
A
304 CFRelease(key);
305 return;
306}
307
308__private_extern__ void
309ipv4_router_arp_failure(const char * if_name)
310{
9de8ab86 311 interface_notify_entity(if_name, "Router ARP failure", kSCEntNetIPv4RouterARPFailure);
78403150
A
312 return;
313}
314
315__private_extern__ void
316ipv4_router_arp_alive(const char * if_name)
317{
9de8ab86 318 interface_notify_entity(if_name, "Router ARP alive", kSCEntNetIPv4RouterARPAlive);
78403150
A
319 return;
320}