2 * Copyright (c) 2002-2017 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
35 #ifndef kSCEntNetIPv4ARPCollision
36 #define kSCEntNetIPv4ARPCollision CFSTR("IPv4ARPCollision")
37 #endif /* kSCEntNetIPv4ARPCollision */
40 #ifndef kSCEntNetIPv4PortInUse
41 #define kSCEntNetIPv4PortInUse CFSTR("PortInUse")
42 #endif /* kSCEntNetIPv4PortInUse */
43 #endif /* !TARGET_OS_IPHONE */
45 #define IP_FORMAT "%d.%d.%d.%d"
46 #define IP_CH(ip, i) (((u_char *)(ip))[i])
47 #define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
51 appendAddress(CFMutableDictionaryRef dict
, CFStringRef key
, struct in_addr
*address
)
55 CFMutableArrayRef newAddrs
;
57 addrs
= CFDictionaryGetValue(dict
, key
);
59 newAddrs
= CFArrayCreateMutableCopy(NULL
, 0, addrs
);
61 newAddrs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
64 addr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR(IP_FORMAT
), IP_LIST(address
));
65 CFArrayAppendValue(newAddrs
, addr
);
68 CFDictionarySetValue(dict
, key
, newAddrs
);
74 static CFMutableDictionaryRef
75 copyIF(CFStringRef key
, CFMutableDictionaryRef oldIFs
, CFMutableDictionaryRef newIFs
)
77 CFDictionaryRef dict
= NULL
;
78 CFMutableDictionaryRef newDict
= NULL
;
80 if (CFDictionaryGetValueIfPresent(newIFs
, key
, (const void **)&dict
)) {
81 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
83 dict
= cache_SCDynamicStoreCopyValue(store
, key
);
85 CFDictionarySetValue(oldIFs
, key
, dict
);
86 if (isA_CFDictionary(dict
)) {
87 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
88 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv4Addresses
);
89 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv4SubnetMasks
);
90 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv4DestAddresses
);
91 CFDictionaryRemoveValue(newDict
, kSCPropNetIPv4BroadcastAddresses
);
98 newDict
= CFDictionaryCreateMutable(NULL
,
100 &kCFTypeDictionaryKeyCallBacks
,
101 &kCFTypeDictionaryValueCallBacks
);
109 updateStore(const void *key
, const void *value
, void *context
)
111 CFDictionaryRef dict
;
112 CFDictionaryRef newDict
= (CFDictionaryRef
)value
;
113 CFDictionaryRef oldIFs
= (CFDictionaryRef
)context
;
115 dict
= CFDictionaryGetValue(oldIFs
, key
);
117 if (!dict
|| !CFEqual(dict
, newDict
)) {
118 if (CFDictionaryGetCount(newDict
) > 0) {
119 SC_log(LOG_DEBUG
, "Update interface configuration: %@: %@", key
, newDict
);
120 cache_SCDynamicStoreSetValue(store
, key
, newDict
);
122 CFDictionaryRef oldDict
;
124 oldDict
= cache_SCDynamicStoreCopyValue(store
, key
);
125 if (oldDict
!= NULL
) {
126 SC_log(LOG_DEBUG
, "Update interface configuration: %@: <removed>", key
);
129 cache_SCDynamicStoreRemoveValue(store
, key
);
131 network_changed
= TRUE
;
140 ipv4_interface_update(struct ifaddrs
*ifap
, const char *if_name
)
143 struct ifaddrs
*ifap_temp
= NULL
;
144 CFStringRef interface
;
145 boolean_t interfaceFound
= FALSE
;
146 CFStringRef key
= NULL
;
147 CFMutableDictionaryRef oldIFs
;
148 CFMutableDictionaryRef newDict
= NULL
;
149 CFMutableDictionaryRef newIFs
;
151 oldIFs
= CFDictionaryCreateMutable(NULL
,
153 &kCFTypeDictionaryKeyCallBacks
,
154 &kCFTypeDictionaryValueCallBacks
);
155 newIFs
= CFDictionaryCreateMutable(NULL
,
157 &kCFTypeDictionaryKeyCallBacks
,
158 &kCFTypeDictionaryValueCallBacks
);
161 if (getifaddrs(&ifap_temp
) == -1) {
162 SC_log(LOG_NOTICE
, "getifaddrs() failed: %s", strerror(errno
));
168 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
169 struct sockaddr_in
*sin
;
171 if (ifa
->ifa_addr
->sa_family
!= AF_INET
) {
172 continue; /* sorry, not interested */
175 /* check if this is the requested interface */
177 if (strncmp(if_name
, ifa
->ifa_name
, IFNAMSIZ
) == 0) {
178 interfaceFound
= TRUE
; /* yes, this is the one I want */
180 continue; /* sorry, not interested */
184 interface
= CFStringCreateWithCString(NULL
, ifa
->ifa_name
, kCFStringEncodingMacRoman
);
185 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
186 kSCDynamicStoreDomainState
,
189 CFRelease(interface
);
191 newDict
= copyIF(key
, oldIFs
, newIFs
);
193 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
194 sin
= (struct sockaddr_in
*)(void *)ifa
->ifa_addr
;
195 appendAddress(newDict
, kSCPropNetIPv4Addresses
, &sin
->sin_addr
);
197 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
198 struct sockaddr_in
*dst
;
200 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
201 dst
= (struct sockaddr_in
*)(void *)ifa
->ifa_dstaddr
;
202 appendAddress(newDict
, kSCPropNetIPv4DestAddresses
, &dst
->sin_addr
);
204 struct sockaddr_in
*brd
;
205 struct sockaddr_in
*msk
;
207 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
208 brd
= (struct sockaddr_in
*)(void *)ifa
->ifa_broadaddr
;
209 appendAddress(newDict
, kSCPropNetIPv4BroadcastAddresses
,&brd
->sin_addr
);
211 /* ALIGN: cast ok, this should be aligned (getifaddrs). */
212 msk
= (struct sockaddr_in
*)(void *)ifa
->ifa_netmask
;
213 appendAddress(newDict
, kSCPropNetIPv4SubnetMasks
, &msk
->sin_addr
);
216 CFDictionarySetValue(newIFs
, key
, newDict
);
221 /* if the last address[es] were removed from the target interface */
222 if (if_name
&& !interfaceFound
) {
223 interface
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingMacRoman
);
224 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
225 kSCDynamicStoreDomainState
,
228 CFRelease(interface
);
230 newDict
= copyIF(key
, oldIFs
, newIFs
);
232 CFDictionarySetValue(newIFs
, key
, newDict
);
237 CFDictionaryApplyFunction(newIFs
, updateStore
, oldIFs
);
241 if (ifap_temp
) freeifaddrs(ifap_temp
);
250 ipv4_arp_collision(const char *if_name
, struct in_addr ip_addr
, int hw_len
, const void * hw_addr
)
252 uint8_t * hw_addr_bytes
= (uint8_t *)hw_addr
;
254 CFStringRef if_name_cf
;
255 CFMutableStringRef key
;
258 if_name_cf
= CFStringCreateWithCString(NULL
, if_name
,
259 kCFStringEncodingASCII
);
260 prefix
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
261 kSCDynamicStoreDomainState
,
263 kSCEntNetIPv4ARPCollision
);
264 key
= CFStringCreateMutableCopy(NULL
, 0, prefix
);
265 CFStringAppendFormat(key
, NULL
, CFSTR("/" IP_FORMAT
),
267 for (i
= 0; i
< hw_len
; i
++) {
268 CFStringAppendFormat(key
, NULL
, CFSTR("%s%02x"),
269 (i
== 0) ? "/" : ":", hw_addr_bytes
[i
]);
271 SC_log(LOG_DEBUG
, "Post ARP collision: %@", key
);
272 cache_SCDynamicStoreNotifyValue(store
, key
);
275 CFRelease(if_name_cf
);
279 #if !TARGET_OS_IPHONE
282 ipv4_port_in_use(uint16_t port
, pid_t req_pid
)
286 key
= SCDynamicStoreKeyCreate(NULL
,
287 CFSTR("%@/%@/Protocol/%@/%@/%d/%d"),
288 kSCDynamicStoreDomainState
,
291 kSCEntNetIPv4PortInUse
,
293 SC_log(LOG_DEBUG
, "Post port-in-use: %@", key
);
294 cache_SCDynamicStoreNotifyValue(store
, key
);
298 #endif /* !TARGET_OS_IPHONE */
301 interface_notify_entity(const char * if_name
, const char * type
, CFStringRef entity
)
303 CFStringRef if_name_cf
;
306 if_name_cf
= CFStringCreateWithCString(NULL
, if_name
,
307 kCFStringEncodingASCII
);
308 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
309 kSCDynamicStoreDomainState
,
312 CFRelease(if_name_cf
);
313 SC_log(LOG_DEBUG
, "Post %s: %@", type
, key
);
314 cache_SCDynamicStoreNotifyValue(store
, key
);
319 __private_extern__
void
320 ipv4_router_arp_failure(const char * if_name
)
322 interface_notify_entity(if_name
, "Router ARP failure", kSCEntNetIPv4RouterARPFailure
);
326 __private_extern__
void
327 ipv4_router_arp_alive(const char * if_name
)
329 interface_notify_entity(if_name
, "Router ARP alive", kSCEntNetIPv4RouterARPAlive
);