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