2 * Copyright (c) 2002-2003 Apple Computer, 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>
36 #define s6_addr16 __u6_addr.__u6_addr16
38 #ifndef kSCPropNetIPv6DestAddresses
39 #define kSCPropNetIPv6DestAddresses SCSTR("DestAddresses")
42 #ifndef kSCPropNetIPv6Flags
43 #define kSCPropNetIPv6Flags SCSTR("Flags")
46 #ifndef kSCPropNetIPv6PrefixLength
47 #define kSCPropNetIPv6PrefixLength SCSTR("PrefixLength")
51 #ifndef kSCPropNetIPv6ScopeID
52 #define kSCPropNetIPv6ScopeID SCSTR("ScopeID")
58 appendAddress(CFMutableDictionaryRef dict
, CFStringRef key
, struct sockaddr_in6
*sin6
)
62 CFMutableArrayRef newAddrs
;
65 addrs
= CFDictionaryGetValue(dict
, key
);
67 newAddrs
= CFArrayCreateMutableCopy(NULL
, 0, addrs
);
69 newAddrs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
72 if (inet_ntop(AF_INET6
, (const void *)&sin6
->sin6_addr
, str
, sizeof(str
)) == NULL
) {
73 SCLog(TRUE
, LOG_ERR
, CFSTR("inet_ntop() failed: %s"), strerror(errno
));
77 addr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%s"), str
);
78 CFArrayAppendValue(newAddrs
, addr
);
81 CFDictionarySetValue(dict
, key
, newAddrs
);
88 appendFlags(CFMutableDictionaryRef dict
, int flags6
)
91 CFMutableArrayRef newFlags
;
94 flags
= CFDictionaryGetValue(dict
, kSCPropNetIPv6Flags
);
96 newFlags
= CFArrayCreateMutableCopy(NULL
, 0, flags
);
98 newFlags
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
101 v6Flags
= CFNumberCreate(NULL
, kCFNumberIntType
, &flags6
);
102 CFArrayAppendValue(newFlags
, v6Flags
);
105 CFDictionarySetValue(dict
, kSCPropNetIPv6Flags
, newFlags
);
112 appendPrefixLen(CFMutableDictionaryRef dict
, struct sockaddr_in6
*sin6
)
114 register u_int8_t
*name
= &sin6
->sin6_addr
.s6_addr
[0];
115 CFNumberRef prefixLen
;
116 CFArrayRef prefixLens
;
117 CFMutableArrayRef newPrefixLens
;
123 for (byte
= 0; byte
< sizeof(struct in6_addr
); byte
++, plen
+= 8) {
124 if (name
[byte
] != 0xff) {
129 if (byte
== sizeof(struct in6_addr
)) {
133 for (bit
= 7; bit
!= 0; bit
--, plen
++) {
134 if (!(name
[byte
] & (1 << bit
))) {
139 for (; bit
!= 0; bit
--) {
140 if (name
[byte
] & (1 << bit
)) {
147 for (; byte
< sizeof(struct in6_addr
); byte
++) {
156 prefixLens
= CFDictionaryGetValue(dict
, kSCPropNetIPv6PrefixLength
);
158 newPrefixLens
= CFArrayCreateMutableCopy(NULL
, 0, prefixLens
);
160 newPrefixLens
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
163 prefixLen
= CFNumberCreate(NULL
, kCFNumberIntType
, &plen
);
164 CFArrayAppendValue(newPrefixLens
, prefixLen
);
165 CFRelease(prefixLen
);
167 CFDictionarySetValue(dict
, kSCPropNetIPv6PrefixLength
, newPrefixLens
);
168 CFRelease(newPrefixLens
);
175 appendScopeID(CFMutableDictionaryRef dict
, struct sockaddr_in6
*sin6
)
179 CFMutableArrayRef newScopes
;
181 scopes
= CFDictionaryGetValue(dict
, kSCPropNetIPv6ScopeID
);
183 newScopes
= CFArrayCreateMutableCopy(NULL
, 0, scopes
);
185 newScopes
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
188 scope
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &sin6
->sin6_scope_id
);
189 CFArrayAppendValue(newScopes
, scope
);
192 CFDictionarySetValue(dict
, kSCPropNetIPv6ScopeID
, newScopes
);
193 CFRelease(newScopes
);
199 static CFMutableDictionaryRef
200 getIF(CFStringRef key
, CFMutableDictionaryRef oldIFs
, CFMutableDictionaryRef newIFs
)
202 CFDictionaryRef dict
= NULL
;
203 CFMutableDictionaryRef newDict
= NULL
;
205 if (CFDictionaryGetValueIfPresent(newIFs
, key
, (const void **)&dict
)) {
206 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
208 dict
= cache_SCDynamicStoreCopyValue(store
, key
);
210 CFDictionarySetValue(oldIFs
, key
, dict
);
211 if (isA_CFDictionary(dict
)) {
212 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
213 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv6Addresses
);
214 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv6DestAddresses
);
215 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv6Flags
);
216 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv6PrefixLength
);
218 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv6ScopeID
);
226 newDict
= CFDictionaryCreateMutable(NULL
,
228 &kCFTypeDictionaryKeyCallBacks
,
229 &kCFTypeDictionaryValueCallBacks
);
237 updateStore(const void *key
, const void *value
, void *context
)
239 CFDictionaryRef dict
;
240 CFDictionaryRef newDict
= (CFDictionaryRef
)value
;
241 CFDictionaryRef oldIFs
= (CFDictionaryRef
)context
;
243 dict
= CFDictionaryGetValue(oldIFs
, key
);
245 if (!dict
|| !CFEqual(dict
, newDict
)) {
246 if (CFDictionaryGetCount(newDict
) > 0) {
247 cache_SCDynamicStoreSetValue(store
, key
, newDict
);
249 cache_SCDynamicStoreRemoveValue(store
, key
);
259 interface_update_ipv6(struct ifaddrs
*ifap
, const char *if_name
)
262 struct ifaddrs
*ifap_temp
= NULL
;
263 CFStringRef interface
;
264 boolean_t interfaceFound
= FALSE
;
265 CFStringRef key
= NULL
;
266 CFMutableDictionaryRef oldIFs
;
267 CFMutableDictionaryRef newDict
= NULL
;
268 CFMutableDictionaryRef newIFs
;
271 oldIFs
= CFDictionaryCreateMutable(NULL
,
273 &kCFTypeDictionaryKeyCallBacks
,
274 &kCFTypeDictionaryValueCallBacks
);
275 newIFs
= CFDictionaryCreateMutable(NULL
,
277 &kCFTypeDictionaryKeyCallBacks
,
278 &kCFTypeDictionaryValueCallBacks
);
281 if (getifaddrs(&ifap_temp
) < 0) {
282 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
288 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
289 struct in6_ifreq ifr6
;
290 #define flags6 ifr6.ifr_ifru.ifru_flags6
291 struct sockaddr_in6
*sin6
;
293 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
) {
294 continue; /* sorry, not interested */
297 /* check if this is the requested interface */
299 if (strncmp(if_name
, ifa
->ifa_name
, IFNAMSIZ
) == 0) {
300 interfaceFound
= TRUE
; /* yes, this is the one I want */
302 continue; /* sorry, not interested */
307 sock
= dgram_socket(AF_INET6
);
309 SCLog(TRUE
, LOG_NOTICE
, CFSTR("interface_update_ipv6: socket open failed, %s"), strerror(errno
));
314 /* get the current cache information */
315 interface
= CFStringCreateWithCString(NULL
, ifa
->ifa_name
, kCFStringEncodingMacRoman
);
316 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
317 kSCDynamicStoreDomainState
,
320 CFRelease(interface
);
322 newDict
= getIF(key
, oldIFs
, newIFs
);
324 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
326 /* XXX: embedded link local addr check */
327 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
330 index
= sin6
->sin6_addr
.s6_addr16
[1];
332 sin6
->sin6_addr
.s6_addr16
[1] = 0;
333 if (sin6
->sin6_scope_id
== 0) {
334 sin6
->sin6_scope_id
= ntohs(index
);
339 bzero((char *)&ifr6
, sizeof(ifr6
));
340 strncpy(ifr6
.ifr_name
, ifa
->ifa_name
, sizeof(ifr6
.ifr_name
));
341 ifr6
.ifr_addr
= *sin6
;
342 if (ioctl(sock
, SIOCGIFAFLAG_IN6
, &ifr6
) == -1) {
343 /* if flags not available for this address */
344 SCLog(TRUE
, LOG_NOTICE
, CFSTR("interface_update_ipv6: ioctl failed, %s"), strerror(errno
));
347 appendAddress (newDict
, kSCPropNetIPv6Addresses
, sin6
);
349 appendScopeID (newDict
, sin6
);
351 appendPrefixLen(newDict
, (struct sockaddr_in6
*)ifa
->ifa_netmask
);
352 appendFlags (newDict
, flags6
);
355 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
356 struct sockaddr_in6
*dst6
;
358 dst6
= (struct sockaddr_in6
*)ifa
->ifa_dstaddr
;
360 /* XXX: embedded link local addr check */
361 if (IN6_IS_ADDR_LINKLOCAL(&dst6
->sin6_addr
)) {
364 index
= dst6
->sin6_addr
.s6_addr16
[1];
366 dst6
->sin6_addr
.s6_addr16
[1] = 0;
367 if (dst6
->sin6_scope_id
== 0) {
368 dst6
->sin6_scope_id
= ntohs(index
);
373 appendAddress(newDict
, kSCPropNetIPv6DestAddresses
, dst6
);
376 CFDictionarySetValue(newIFs
, key
, newDict
);
381 /* if the last address[es] were removed from the target interface */
382 if (if_name
&& !interfaceFound
) {
383 interface
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingMacRoman
);
384 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
385 kSCDynamicStoreDomainState
,
388 CFRelease(interface
);
390 newDict
= getIF(key
, oldIFs
, newIFs
);
392 CFDictionarySetValue(newIFs
, key
, newDict
);
397 CFDictionaryApplyFunction(newIFs
, updateStore
, oldIFs
);
401 if (ifap_temp
) freeifaddrs(ifap_temp
);
402 if (sock
>= 0) close(sock
);