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>
28 * - split code out from eventmon.c
35 #ifndef kSCEntNetIPv4ARPCollision
36 #define kSCEntNetIPv4ARPCollision CFSTR("IPv4ARPCollision")
37 #endif kSCEntNetIPv4ARPCollision
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)
45 appendAddress(CFMutableDictionaryRef dict
, CFStringRef key
, struct in_addr
*address
)
49 CFMutableArrayRef newAddrs
;
51 addrs
= CFDictionaryGetValue(dict
, key
);
53 newAddrs
= CFArrayCreateMutableCopy(NULL
, 0, addrs
);
55 newAddrs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
58 addr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR(IP_FORMAT
), IP_LIST(address
));
59 CFArrayAppendValue(newAddrs
, addr
);
62 CFDictionarySetValue(dict
, key
, newAddrs
);
68 static CFMutableDictionaryRef
69 getIF(CFStringRef key
, CFMutableDictionaryRef oldIFs
, CFMutableDictionaryRef newIFs
)
71 CFDictionaryRef dict
= NULL
;
72 CFMutableDictionaryRef newDict
= NULL
;
74 if (CFDictionaryGetValueIfPresent(newIFs
, key
, (const void **)&dict
)) {
75 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
77 dict
= cache_SCDynamicStoreCopyValue(store
, key
);
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
);
92 newDict
= CFDictionaryCreateMutable(NULL
,
94 &kCFTypeDictionaryKeyCallBacks
,
95 &kCFTypeDictionaryValueCallBacks
);
103 updateStore(const void *key
, const void *value
, void *context
)
105 CFDictionaryRef dict
;
106 CFDictionaryRef newDict
= (CFDictionaryRef
)value
;
107 CFDictionaryRef oldIFs
= (CFDictionaryRef
)context
;
109 dict
= CFDictionaryGetValue(oldIFs
, key
);
111 if (!dict
|| !CFEqual(dict
, newDict
)) {
112 if (CFDictionaryGetCount(newDict
) > 0) {
113 cache_SCDynamicStoreSetValue(store
, key
, newDict
);
115 cache_SCDynamicStoreRemoveValue(store
, key
);
125 interface_update_ipv4(struct ifaddrs
*ifap
, const char *if_name
)
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
;
136 oldIFs
= CFDictionaryCreateMutable(NULL
,
138 &kCFTypeDictionaryKeyCallBacks
,
139 &kCFTypeDictionaryValueCallBacks
);
140 newIFs
= CFDictionaryCreateMutable(NULL
,
142 &kCFTypeDictionaryKeyCallBacks
,
143 &kCFTypeDictionaryValueCallBacks
);
146 if (getifaddrs(&ifap_temp
) < 0) {
147 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
153 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
154 struct sockaddr_in
*sin
;
156 if (ifa
->ifa_addr
->sa_family
!= AF_INET
) {
157 continue; /* sorry, not interested */
160 /* check if this is the requested interface */
162 if (strncmp(if_name
, ifa
->ifa_name
, IFNAMSIZ
) == 0) {
163 interfaceFound
= TRUE
; /* yes, this is the one I want */
165 continue; /* sorry, not interested */
169 interface
= CFStringCreateWithCString(NULL
, ifa
->ifa_name
, kCFStringEncodingMacRoman
);
170 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
171 kSCDynamicStoreDomainState
,
174 CFRelease(interface
);
176 newDict
= getIF(key
, oldIFs
, newIFs
);
178 sin
= (struct sockaddr_in
*)ifa
->ifa_addr
;
179 appendAddress(newDict
, kSCPropNetIPv4Addresses
, &sin
->sin_addr
);
181 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
182 struct sockaddr_in
*dst
;
184 dst
= (struct sockaddr_in
*)ifa
->ifa_dstaddr
;
185 appendAddress(newDict
, kSCPropNetIPv4DestAddresses
, &dst
->sin_addr
);
187 struct sockaddr_in
*brd
;
188 struct sockaddr_in
*msk
;
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
);
196 CFDictionarySetValue(newIFs
, key
, newDict
);
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
,
208 CFRelease(interface
);
210 newDict
= getIF(key
, oldIFs
, newIFs
);
212 CFDictionarySetValue(newIFs
, key
, newDict
);
217 CFDictionaryApplyFunction(newIFs
, updateStore
, oldIFs
);
221 if (ifap_temp
) freeifaddrs(ifap_temp
);
230 interface_collision_ipv4(const char *if_name
, struct in_addr ip_addr
, int hw_len
, const void * hw_addr
)
232 uint8_t * hw_addr_bytes
= (uint8_t *)hw_addr
;
234 CFStringRef if_name_cf
;
235 CFMutableStringRef key
;
238 if_name_cf
= CFStringCreateWithCString(NULL
, if_name
,
239 kCFStringEncodingASCII
);
240 prefix
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
241 kSCDynamicStoreDomainState
,
243 kSCEntNetIPv4ARPCollision
);
244 key
= CFStringCreateMutableCopy(NULL
, 0, prefix
);
245 CFStringAppendFormat(key
, NULL
, CFSTR("/" IP_FORMAT
),
247 for (i
= 0; i
< hw_len
; i
++) {
248 CFStringAppendFormat(key
, NULL
, CFSTR("%s%02x"),
249 (i
== 0) ? "/" : ":", hw_addr_bytes
[i
]);
251 cache_SCDynamicStoreNotifyValue(store
, key
);
254 CFRelease(if_name_cf
);