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