2 * Copyright (c) 2002-2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * August 5, 2002 Allan Nathanson <ajn@apple.com>
28 * - split code out from eventmon.c
33 #include "ev_appletalk.h"
36 #define DDP_MIN_NETWORK 0x0001
37 #define DDP_MAX_NETWORK 0xfffe
41 get_atalk_interface_cfg(const char *if_name
, at_if_cfg_t
*cfg
)
46 if ((fd
= socket(AF_APPLETALK
, SOCK_RAW
, 0)) == -1)
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) {
61 static CFMutableDictionaryRef
62 getIF(CFStringRef key
, CFMutableDictionaryRef oldIFs
, CFMutableDictionaryRef newIFs
)
64 CFDictionaryRef dict
= NULL
;
65 CFMutableDictionaryRef newDict
= NULL
;
67 if (CFDictionaryGetValueIfPresent(newIFs
, key
, (const void **)&dict
)) {
68 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
70 dict
= cache_SCDynamicStoreCopyValue(store
, key
);
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
);
85 newDict
= CFDictionaryCreateMutable(NULL
,
87 &kCFTypeDictionaryKeyCallBacks
,
88 &kCFTypeDictionaryValueCallBacks
);
96 updateStore(const void *key
, const void *value
, void *context
)
99 CFDictionaryRef newDict
= (CFDictionaryRef
)value
;
100 CFDictionaryRef oldIFs
= (CFDictionaryRef
)context
;
102 dict
= CFDictionaryGetValue(oldIFs
, key
);
104 if (!dict
|| !CFEqual(dict
, newDict
)) {
105 if (CFDictionaryGetCount(newDict
) > 0) {
106 cache_SCDynamicStoreSetValue(store
, key
, newDict
);
108 cache_SCDynamicStoreRemoveValue(store
, key
);
110 network_changed
= TRUE
;
119 interface_update_appletalk(struct ifaddrs
*ifap
, const char *if_name
)
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
;
130 oldIFs
= CFDictionaryCreateMutable(NULL
,
132 &kCFTypeDictionaryKeyCallBacks
,
133 &kCFTypeDictionaryValueCallBacks
);
134 newIFs
= CFDictionaryCreateMutable(NULL
,
136 &kCFTypeDictionaryKeyCallBacks
,
137 &kCFTypeDictionaryValueCallBacks
);
140 if (getifaddrs(&ifap_temp
) == -1) {
141 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
147 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
151 struct sockaddr_at
*sat
;
153 if (ifa
->ifa_addr
->sa_family
!= AF_APPLETALK
) {
154 continue; /* sorry, not interested */
157 /* check if this is the requested interface */
159 if (strncmp(if_name
, ifa
->ifa_name
, IFNAMSIZ
) == 0) {
160 interfaceFound
= TRUE
; /* yes, this is the one I want */
162 continue; /* sorry, not interested */
166 /* get the current cache information */
167 interface
= CFStringCreateWithCString(NULL
, ifa
->ifa_name
, kCFStringEncodingMacRoman
);
168 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
169 kSCDynamicStoreDomainState
,
172 CFRelease(interface
);
174 newDict
= getIF(key
, oldIFs
, newIFs
);
176 sat
= (struct sockaddr_at
*)ifa
->ifa_addr
;
178 iVal
= (int)sat
->sat_addr
.s_net
;
179 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &iVal
);
180 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkNetworkID
, num
);
183 iVal
= (int)sat
->sat_addr
.s_node
;
184 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &iVal
);
185 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkNodeID
, num
);
188 if (get_atalk_interface_cfg(ifa
->ifa_name
, &cfg
) == 0) {
192 * Set starting and ending net values
194 if (!(((cfg
.netStart
== 0) && (cfg
.netEnd
== 0)) ||
195 ((cfg
.netStart
== DDP_MIN_NETWORK
) && (cfg
.netEnd
== DDP_MAX_NETWORK
)))) {
196 CFMutableArrayRef array
;
198 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
201 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &iVal
);
202 CFArrayAppendValue(array
, num
);
206 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &iVal
);
207 CFArrayAppendValue(array
, num
);
210 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkNetworkRange
, array
);
215 * Set the default zone
217 zone
= CFStringCreateWithPascalString(NULL
,
218 (ConstStr255Param
)&cfg
.zonename
,
219 kCFStringEncodingMacRoman
);
220 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkDefaultZone
, zone
);
224 CFDictionarySetValue(newIFs
, key
, newDict
);
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
,
236 CFRelease(interface
);
238 newDict
= getIF(key
, oldIFs
, newIFs
);
240 CFDictionarySetValue(newIFs
, key
, newDict
);
245 CFDictionaryApplyFunction(newIFs
, updateStore
, oldIFs
);
249 if (ifap_temp
) freeifaddrs(ifap_temp
);
259 interface_update_atalk_address(struct kev_atalk_data
*aEvent
, const char *if_name
)
261 CFStringRef interface
;
263 CFDictionaryRef dict
;
264 CFMutableDictionaryRef newDict
= NULL
;
265 CFNumberRef newNode
, newNet
;
269 /* get the current cache information */
270 interface
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingMacRoman
);
271 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
272 kSCDynamicStoreDomainState
,
275 CFRelease(interface
);
277 dict
= cache_SCDynamicStoreCopyValue(store
, key
);
279 if (isA_CFDictionary(dict
)) {
280 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
286 newDict
= CFDictionaryCreateMutable(NULL
,
288 &kCFTypeDictionaryKeyCallBacks
,
289 &kCFTypeDictionaryValueCallBacks
);
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
;
296 newNode
= CFNumberCreate(NULL
, kCFNumberIntType
, &node
);
297 newNet
= CFNumberCreate(NULL
, kCFNumberIntType
, &net
);
299 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkNodeID
, newNode
);
300 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkNetworkID
, newNet
);
306 cache_SCDynamicStoreSetValue(store
, key
, newDict
);
307 network_changed
= TRUE
;
316 interface_update_atalk_zone(struct kev_atalk_data
*aEvent
, const char *if_name
)
318 CFStringRef interface
;
320 CFDictionaryRef dict
;
321 CFMutableDictionaryRef newDict
= NULL
;
324 /* get the current cache information */
325 interface
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingMacRoman
);
326 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
327 kSCDynamicStoreDomainState
,
330 CFRelease(interface
);
332 dict
= cache_SCDynamicStoreCopyValue(store
, key
);
334 if (isA_CFDictionary(dict
)) {
335 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
341 newDict
= CFDictionaryCreateMutable(NULL
,
343 &kCFTypeDictionaryKeyCallBacks
,
344 &kCFTypeDictionaryValueCallBacks
);
347 /* Update zone value in cache */
348 newZone
= CFStringCreateWithPascalString(NULL
, (ConstStr255Param
)&(aEvent
->node_data
.zone
), kCFStringEncodingMacRoman
);
350 CFDictionarySetValue(newDict
, kSCPropNetAppleTalkDefaultZone
, newZone
);
355 cache_SCDynamicStoreSetValue(store
, key
, newDict
);
356 network_changed
= TRUE
;
365 interface_update_shutdown_atalk()
367 CFStringRef cacheKey
;
368 CFDictionaryRef dict
;
369 CFArrayRef ifList
= NULL
;
370 CFIndex count
, index
;
371 CFStringRef interface
;
374 cacheKey
= SCDynamicStoreKeyCreateNetworkInterface(NULL
,
375 kSCDynamicStoreDomainState
);
377 dict
= cache_SCDynamicStoreCopyValue(store
, cacheKey
);
381 if (isA_CFDictionary(dict
)) {
382 /*get a list of the interfaces*/
383 ifList
= isA_CFArray(CFDictionaryGetValue(dict
, kSCPropNetInterfaces
));
385 count
= CFArrayGetCount(ifList
);
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
,
394 cache_SCDynamicStoreRemoveValue(store
, key
);
395 network_changed
= TRUE
;