]> git.saurik.com Git - apple/configd.git/blob - Plugins/KernelEventMonitor/ev_ipv4.c
configd-204.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / ev_ipv4.c
1 /*
2 * Copyright (c) 2002-2005, 2007 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 #ifndef kSCEntNetIPv4PortInUse
40 #define kSCEntNetIPv4PortInUse CFSTR("PortInUse")
41 #endif /* kSCEntNetIPv4PortInUse */
42
43 #define IP_FORMAT "%d.%d.%d.%d"
44 #define IP_CH(ip, i) (((u_char *)(ip))[i])
45 #define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
46
47
48 static void
49 appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct in_addr *address)
50 {
51 CFStringRef addr;
52 CFArrayRef addrs;
53 CFMutableArrayRef newAddrs;
54
55 addrs = CFDictionaryGetValue(dict, key);
56 if (addrs) {
57 newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
58 } else {
59 newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
60 }
61
62 addr = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(address));
63 CFArrayAppendValue(newAddrs, addr);
64 CFRelease(addr);
65
66 CFDictionarySetValue(dict, key, newAddrs);
67 CFRelease(newAddrs);
68 return;
69 }
70
71
72 static CFMutableDictionaryRef
73 getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
74 {
75 CFDictionaryRef dict = NULL;
76 CFMutableDictionaryRef newDict = NULL;
77
78 if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
79 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
80 } else {
81 dict = cache_SCDynamicStoreCopyValue(store, key);
82 if (dict) {
83 CFDictionarySetValue(oldIFs, key, dict);
84 if (isA_CFDictionary(dict)) {
85 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
86 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4Addresses);
87 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4SubnetMasks);
88 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4DestAddresses);
89 CFDictionaryRemoveValue(newDict, kSCPropNetIPv4BroadcastAddresses);
90 }
91 CFRelease(dict);
92 }
93 }
94
95 if (!newDict) {
96 newDict = CFDictionaryCreateMutable(NULL,
97 0,
98 &kCFTypeDictionaryKeyCallBacks,
99 &kCFTypeDictionaryValueCallBacks);
100 }
101
102 return newDict;
103 }
104
105
106 static void
107 updateStore(const void *key, const void *value, void *context)
108 {
109 CFDictionaryRef dict;
110 CFDictionaryRef newDict = (CFDictionaryRef)value;
111 CFDictionaryRef oldIFs = (CFDictionaryRef)context;
112
113 dict = CFDictionaryGetValue(oldIFs, key);
114
115 if (!dict || !CFEqual(dict, newDict)) {
116 if (CFDictionaryGetCount(newDict) > 0) {
117 cache_SCDynamicStoreSetValue(store, key, newDict);
118 } else if (dict) {
119 cache_SCDynamicStoreRemoveValue(store, key);
120 }
121 network_changed = TRUE;
122 }
123
124 return;
125 }
126
127
128 __private_extern__
129 void
130 interface_update_ipv4(struct ifaddrs *ifap, const char *if_name)
131 {
132 struct ifaddrs *ifa;
133 struct ifaddrs *ifap_temp = NULL;
134 CFStringRef interface;
135 boolean_t interfaceFound = FALSE;
136 CFStringRef key = NULL;
137 CFMutableDictionaryRef oldIFs;
138 CFMutableDictionaryRef newDict = NULL;
139 CFMutableDictionaryRef newIFs;
140
141 oldIFs = CFDictionaryCreateMutable(NULL,
142 0,
143 &kCFTypeDictionaryKeyCallBacks,
144 &kCFTypeDictionaryValueCallBacks);
145 newIFs = CFDictionaryCreateMutable(NULL,
146 0,
147 &kCFTypeDictionaryKeyCallBacks,
148 &kCFTypeDictionaryValueCallBacks);
149
150 if (!ifap) {
151 if (getifaddrs(&ifap_temp) == -1) {
152 SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
153 goto error;
154 }
155 ifap = ifap_temp;
156 }
157
158 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
159 struct sockaddr_in *sin;
160
161 if (ifa->ifa_addr->sa_family != AF_INET) {
162 continue; /* sorry, not interested */
163 }
164
165 /* check if this is the requested interface */
166 if (if_name) {
167 if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
168 interfaceFound = TRUE; /* yes, this is the one I want */
169 } else {
170 continue; /* sorry, not interested */
171 }
172 }
173
174 interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
175 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
176 kSCDynamicStoreDomainState,
177 interface,
178 kSCEntNetIPv4);
179 CFRelease(interface);
180
181 newDict = getIF(key, oldIFs, newIFs);
182
183 sin = (struct sockaddr_in *)ifa->ifa_addr;
184 appendAddress(newDict, kSCPropNetIPv4Addresses, &sin->sin_addr);
185
186 if (ifa->ifa_flags & IFF_POINTOPOINT) {
187 struct sockaddr_in *dst;
188
189 dst = (struct sockaddr_in *)ifa->ifa_dstaddr;
190 appendAddress(newDict, kSCPropNetIPv4DestAddresses, &dst->sin_addr);
191 } else {
192 struct sockaddr_in *brd;
193 struct sockaddr_in *msk;
194
195 brd = (struct sockaddr_in *)ifa->ifa_broadaddr;
196 appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses, &brd->sin_addr);
197 msk = (struct sockaddr_in *)ifa->ifa_netmask;
198 appendAddress(newDict, kSCPropNetIPv4SubnetMasks, &msk->sin_addr);
199 }
200
201 CFDictionarySetValue(newIFs, key, newDict);
202 CFRelease(newDict);
203 CFRelease(key);
204 }
205
206 /* if the last address[es] were removed from the target interface */
207 if (if_name && !interfaceFound) {
208 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
209 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
210 kSCDynamicStoreDomainState,
211 interface,
212 kSCEntNetIPv4);
213 CFRelease(interface);
214
215 newDict = getIF(key, oldIFs, newIFs);
216
217 CFDictionarySetValue(newIFs, key, newDict);
218 CFRelease(newDict);
219 CFRelease(key);
220 }
221
222 CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
223
224 error :
225
226 if (ifap_temp) freeifaddrs(ifap_temp);
227 CFRelease(oldIFs);
228 CFRelease(newIFs);
229
230 return;
231 }
232
233 __private_extern__
234 void
235 interface_collision_ipv4(const char *if_name, struct in_addr ip_addr, int hw_len, const void * hw_addr)
236 {
237 uint8_t * hw_addr_bytes = (uint8_t *)hw_addr;
238 int i;
239 CFStringRef if_name_cf;
240 CFMutableStringRef key;
241 CFStringRef prefix;
242
243 if_name_cf = CFStringCreateWithCString(NULL, if_name,
244 kCFStringEncodingASCII);
245 prefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
246 kSCDynamicStoreDomainState,
247 if_name_cf,
248 kSCEntNetIPv4ARPCollision);
249 key = CFStringCreateMutableCopy(NULL, 0, prefix);
250 CFStringAppendFormat(key, NULL, CFSTR("/" IP_FORMAT),
251 IP_LIST(&ip_addr));
252 for (i = 0; i < hw_len; i++) {
253 CFStringAppendFormat(key, NULL, CFSTR("%s%02x"),
254 (i == 0) ? "/" : ":", hw_addr_bytes[i]);
255 }
256 cache_SCDynamicStoreNotifyValue(store, key);
257 CFRelease(key);
258 CFRelease(prefix);
259 CFRelease(if_name_cf);
260 return;
261 }
262
263 __private_extern__
264 void
265 port_in_use_ipv4(uint16_t port, pid_t req_pid)
266 {
267 CFStringRef key;
268
269 key = SCDynamicStoreKeyCreate(NULL,
270 CFSTR("%@/%@/Protocol/%@/%@/%d/%d"),
271 kSCDynamicStoreDomainState,
272 kSCCompNetwork,
273 kSCEntNetIPv4,
274 kSCEntNetIPv4PortInUse,
275 port, req_pid);
276 cache_SCDynamicStoreNotifyValue(store, key);
277 CFRelease(key);
278 return;
279 }