]> git.saurik.com Git - apple/configd.git/blob - Plugins/KernelEventMonitor/ev_appletalk.c
configd-293.8.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / ev_appletalk.c
1 /*
2 * Copyright (c) 2002-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_appletalk.h"
34
35 // from <netat/ddp.h>
36 #define DDP_MIN_NETWORK 0x0001
37 #define DDP_MAX_NETWORK 0xfffe
38
39
40 static int
41 get_atalk_interface_cfg(const char *if_name, at_if_cfg_t *cfg)
42 {
43 int fd;
44
45 /* open socket */
46 if ((fd = socket(AF_APPLETALK, SOCK_RAW, 0)) == -1)
47 return -1;
48
49 /* get config info for given interface */
50 strncpy(cfg->ifr_name, if_name, sizeof(cfg->ifr_name));
51 if (ioctl(fd, AIOCGETIFCFG, (caddr_t)cfg) == -1) {
52 (void)close(fd);
53 return -1;
54 }
55
56 (void)close(fd);
57 return 0;
58 }
59
60
61 static CFMutableDictionaryRef
62 getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
63 {
64 CFDictionaryRef dict = NULL;
65 CFMutableDictionaryRef newDict = NULL;
66
67 if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
68 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
69 } else {
70 dict = cache_SCDynamicStoreCopyValue(store, key);
71 if (dict) {
72 CFDictionarySetValue(oldIFs, key, dict);
73 if (isA_CFDictionary(dict)) {
74 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
75 CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkID);
76 CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNodeID);
77 CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkRange);
78 CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkDefaultZone);
79 }
80 CFRelease(dict);
81 }
82 }
83
84 if (!newDict) {
85 newDict = CFDictionaryCreateMutable(NULL,
86 0,
87 &kCFTypeDictionaryKeyCallBacks,
88 &kCFTypeDictionaryValueCallBacks);
89 }
90
91 return newDict;
92 }
93
94
95 static void
96 updateStore(const void *key, const void *value, void *context)
97 {
98 CFDictionaryRef dict;
99 CFDictionaryRef newDict = (CFDictionaryRef)value;
100 CFDictionaryRef oldIFs = (CFDictionaryRef)context;
101
102 dict = CFDictionaryGetValue(oldIFs, key);
103
104 if (!dict || !CFEqual(dict, newDict)) {
105 if (CFDictionaryGetCount(newDict) > 0) {
106 cache_SCDynamicStoreSetValue(store, key, newDict);
107 } else if (dict) {
108 cache_SCDynamicStoreRemoveValue(store, key);
109 }
110 network_changed = TRUE;
111 }
112
113 return;
114 }
115
116
117 __private_extern__
118 void
119 interface_update_appletalk(struct ifaddrs *ifap, const char *if_name)
120 {
121 struct ifaddrs *ifa;
122 struct ifaddrs *ifap_temp = NULL;
123 CFStringRef interface;
124 boolean_t interfaceFound = FALSE;
125 CFStringRef key = NULL;
126 CFMutableDictionaryRef oldIFs;
127 CFMutableDictionaryRef newDict = NULL;
128 CFMutableDictionaryRef newIFs;
129
130 oldIFs = CFDictionaryCreateMutable(NULL,
131 0,
132 &kCFTypeDictionaryKeyCallBacks,
133 &kCFTypeDictionaryValueCallBacks);
134 newIFs = CFDictionaryCreateMutable(NULL,
135 0,
136 &kCFTypeDictionaryKeyCallBacks,
137 &kCFTypeDictionaryValueCallBacks);
138
139 if (!ifap) {
140 if (getifaddrs(&ifap_temp) == -1) {
141 SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
142 goto error;
143 }
144 ifap = ifap_temp;
145 }
146
147 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
148 at_if_cfg_t cfg;
149 int iVal;
150 CFNumberRef num;
151 struct sockaddr_at *sat;
152
153 if (ifa->ifa_addr->sa_family != AF_APPLETALK) {
154 continue; /* sorry, not interested */
155 }
156
157 /* check if this is the requested interface */
158 if (if_name) {
159 if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
160 interfaceFound = TRUE; /* yes, this is the one I want */
161 } else {
162 continue; /* sorry, not interested */
163 }
164 }
165
166 /* get the current cache information */
167 interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
168 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
169 kSCDynamicStoreDomainState,
170 interface,
171 kSCEntNetAppleTalk);
172 CFRelease(interface);
173
174 newDict = getIF(key, oldIFs, newIFs);
175
176 sat = (struct sockaddr_at *)ifa->ifa_addr;
177
178 iVal = (int)sat->sat_addr.s_net;
179 num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
180 CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, num);
181 CFRelease(num);
182
183 iVal = (int)sat->sat_addr.s_node;
184 num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
185 CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, num);
186 CFRelease(num);
187
188 if (get_atalk_interface_cfg(ifa->ifa_name, &cfg) == 0) {
189 CFStringRef zone;
190
191 /*
192 * Set starting and ending net values
193 */
194 if (!(((cfg.netStart == 0) && (cfg.netEnd == 0)) ||
195 ((cfg.netStart == DDP_MIN_NETWORK) && (cfg.netEnd == DDP_MAX_NETWORK)))) {
196 CFMutableArrayRef array;
197
198 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
199
200 iVal = cfg.netStart;
201 num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
202 CFArrayAppendValue(array, num);
203 CFRelease(num);
204
205 iVal = cfg.netEnd;
206 num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
207 CFArrayAppendValue(array, num);
208 CFRelease(num);
209
210 CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkRange, array);
211 CFRelease(array);
212 }
213
214 /*
215 * Set the default zone
216 */
217 zone = CFStringCreateWithPascalString(NULL,
218 (ConstStr255Param)&cfg.zonename,
219 kCFStringEncodingMacRoman);
220 CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, zone);
221 CFRelease(zone);
222 }
223
224 CFDictionarySetValue(newIFs, key, newDict);
225 CFRelease(newDict);
226 CFRelease(key);
227 }
228
229 /* if the last address[es] were removed from the target interface */
230 if (if_name && !interfaceFound) {
231 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
232 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
233 kSCDynamicStoreDomainState,
234 interface,
235 kSCEntNetAppleTalk);
236 CFRelease(interface);
237
238 newDict = getIF(key, oldIFs, newIFs);
239
240 CFDictionarySetValue(newIFs, key, newDict);
241 CFRelease(newDict);
242 CFRelease(key);
243 }
244
245 CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
246
247 error :
248
249 if (ifap_temp) freeifaddrs(ifap_temp);
250 CFRelease(oldIFs);
251 CFRelease(newIFs);
252
253 return;
254 }
255
256
257 __private_extern__
258 void
259 interface_update_atalk_address(struct kev_atalk_data *aEvent, const char *if_name)
260 {
261 CFStringRef interface;
262 CFStringRef key;
263 CFDictionaryRef dict;
264 CFMutableDictionaryRef newDict = NULL;
265 CFNumberRef newNode, newNet;
266 int node;
267 int net;
268
269 /* get the current cache information */
270 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
271 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
272 kSCDynamicStoreDomainState,
273 interface,
274 kSCEntNetAppleTalk);
275 CFRelease(interface);
276
277 dict = cache_SCDynamicStoreCopyValue(store, key);
278 if (dict) {
279 if (isA_CFDictionary(dict)) {
280 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
281 }
282 CFRelease(dict);
283 }
284
285 if (!newDict) {
286 newDict = CFDictionaryCreateMutable(NULL,
287 0,
288 &kCFTypeDictionaryKeyCallBacks,
289 &kCFTypeDictionaryValueCallBacks);
290 }
291
292 /* Update node/net values in cache */
293 node = (int)aEvent->node_data.address.s_node;
294 net = (int)aEvent->node_data.address.s_net;
295
296 newNode = CFNumberCreate(NULL, kCFNumberIntType, &node);
297 newNet = CFNumberCreate(NULL, kCFNumberIntType, &net);
298
299 CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, newNode);
300 CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, newNet);
301
302 CFRelease(newNode);
303 CFRelease(newNet);
304
305 /* update cache */
306 cache_SCDynamicStoreSetValue(store, key, newDict);
307 network_changed = TRUE;
308 CFRelease(newDict);
309 CFRelease(key);
310 return;
311 }
312
313
314 __private_extern__
315 void
316 interface_update_atalk_zone(struct kev_atalk_data *aEvent, const char *if_name)
317 {
318 CFStringRef interface;
319 CFStringRef key;
320 CFDictionaryRef dict;
321 CFMutableDictionaryRef newDict = NULL;
322 CFStringRef newZone;
323
324 /* get the current cache information */
325 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
326 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
327 kSCDynamicStoreDomainState,
328 interface,
329 kSCEntNetAppleTalk);
330 CFRelease(interface);
331
332 dict = cache_SCDynamicStoreCopyValue(store, key);
333 if (dict) {
334 if (isA_CFDictionary(dict)) {
335 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
336 }
337 CFRelease(dict);
338 }
339
340 if (!newDict) {
341 newDict = CFDictionaryCreateMutable(NULL,
342 0,
343 &kCFTypeDictionaryKeyCallBacks,
344 &kCFTypeDictionaryValueCallBacks);
345 }
346
347 /* Update zone value in cache */
348 newZone = CFStringCreateWithPascalString(NULL, (ConstStr255Param)&(aEvent->node_data.zone), kCFStringEncodingMacRoman);
349
350 CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, newZone);
351
352 CFRelease(newZone);
353
354 /* update cache */
355 cache_SCDynamicStoreSetValue(store, key, newDict);
356 network_changed = TRUE;
357 CFRelease(newDict);
358 CFRelease(key);
359 return;
360 }
361
362
363 __private_extern__
364 void
365 interface_update_shutdown_atalk()
366 {
367 CFStringRef cacheKey;
368 CFDictionaryRef dict;
369 CFArrayRef ifList = NULL;
370 CFIndex count, index;
371 CFStringRef interface;
372 CFStringRef key;
373
374 cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
375 kSCDynamicStoreDomainState);
376
377 dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
378 CFRelease(cacheKey);
379
380 if (dict) {
381 if (isA_CFDictionary(dict)) {
382 /*get a list of the interfaces*/
383 ifList = isA_CFArray(CFDictionaryGetValue(dict, kSCPropNetInterfaces));
384 if (ifList) {
385 count = CFArrayGetCount(ifList);
386
387 /*iterate through list and remove AppleTalk data*/
388 for (index = 0; index < count; index++) {
389 interface = CFArrayGetValueAtIndex(ifList, index);
390 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
391 kSCDynamicStoreDomainState,
392 interface,
393 kSCEntNetAppleTalk);
394 cache_SCDynamicStoreRemoveValue(store, key);
395 network_changed = TRUE;
396 CFRelease(key);
397 }
398 }
399 }
400 CFRelease(dict);
401 }
402
403 return;
404 }