this repo has no description
at fixPythonPipStalling 478 lines 13 kB view raw
1/* 2 * Copyright (c) 2002-2007, 2011, 2013, 2015, 2017, 2018 Apple 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 * - initial revision 29 */ 30 31 32#include "eventmon.h" 33#include "ev_ipv6.h" 34 35#define s6_addr16 __u6_addr.__u6_addr16 36 37#ifdef NOTYET 38#ifndef kSCPropNetIPv6ScopeID 39#define kSCPropNetIPv6ScopeID SCSTR("ScopeID") 40#endif 41#endif /* NOTYET */ 42 43#ifndef kSCEntNetIPv6DuplicatedAddress 44#define kSCEntNetIPv6DuplicatedAddress CFSTR("IPv6DuplicatedAddress") 45#endif /* kSCEntNetIPv6DuplicatedAddress */ 46 47static void 48appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct sockaddr_in6 *sin6) 49{ 50 CFStringRef addr; 51 CFArrayRef addrs; 52 CFMutableArrayRef newAddrs; 53 char str[INET6_ADDRSTRLEN]; 54 55 addrs = CFDictionaryGetValue(dict, key); 56 if (addrs) { 57 newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs); 58 } else { 59 newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 60 } 61 62 if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr, str, sizeof(str)) == NULL) { 63 SC_log(LOG_INFO, "inet_ntop() failed: %s", strerror(errno)); 64 str[0] = '\0'; 65 } 66 67 addr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), str); 68 CFArrayAppendValue(newAddrs, addr); 69 CFRelease(addr); 70 71 CFDictionarySetValue(dict, key, newAddrs); 72 CFRelease(newAddrs); 73 return; 74} 75 76 77static void 78appendFlags(CFMutableDictionaryRef dict, int flags6) 79{ 80 CFArrayRef flags; 81 CFMutableArrayRef newFlags; 82 CFNumberRef v6Flags; 83 84 flags = CFDictionaryGetValue(dict, kSCPropNetIPv6Flags); 85 if (flags) { 86 newFlags = CFArrayCreateMutableCopy(NULL, 0, flags); 87 } else { 88 newFlags = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 89 } 90 91 v6Flags = CFNumberCreate(NULL, kCFNumberIntType, &flags6); 92 CFArrayAppendValue(newFlags, v6Flags); 93 CFRelease(v6Flags); 94 95 CFDictionarySetValue(dict, kSCPropNetIPv6Flags, newFlags); 96 CFRelease(newFlags); 97 return; 98} 99 100 101static void 102appendPrefixLen(CFMutableDictionaryRef dict, struct sockaddr_in6 *sin6) 103{ 104 register u_int8_t *name = &sin6->sin6_addr.s6_addr[0]; 105 CFNumberRef prefixLen; 106 CFArrayRef prefixLens; 107 CFMutableArrayRef newPrefixLens; 108 109 register size_t byte; 110 register int bit; 111 int plen = 0; 112 113 for (byte = 0; byte < sizeof(struct in6_addr); byte++, plen += 8) { 114 if (name[byte] != 0xff) { 115 break; 116 } 117 } 118 119 if (byte == sizeof(struct in6_addr)) { 120 goto append; 121 } 122 123 for (bit = 7; bit != 0; bit--, plen++) { 124 if (!(name[byte] & (1 << bit))) { 125 break; 126 } 127 } 128 129 for (; bit != 0; bit--) { 130 if (name[byte] & (1 << bit)) { 131 plen = 0; 132 goto append; 133 } 134 } 135 136 byte++; 137 for (; byte < sizeof(struct in6_addr); byte++) { 138 if (name[byte]) { 139 plen = 0; 140 goto append; 141 } 142 } 143 144 append : 145 146 prefixLens = CFDictionaryGetValue(dict, kSCPropNetIPv6PrefixLength); 147 if (prefixLens) { 148 newPrefixLens = CFArrayCreateMutableCopy(NULL, 0, prefixLens); 149 } else { 150 newPrefixLens = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 151 } 152 153 prefixLen = CFNumberCreate(NULL, kCFNumberIntType, &plen); 154 CFArrayAppendValue(newPrefixLens, prefixLen); 155 CFRelease(prefixLen); 156 157 CFDictionarySetValue(dict, kSCPropNetIPv6PrefixLength, newPrefixLens); 158 CFRelease(newPrefixLens); 159 return; 160} 161 162 163#ifdef NOTYET 164static void 165appendScopeID(CFMutableDictionaryRef dict, struct sockaddr_in6 *sin6) 166{ 167 CFNumberRef scope; 168 CFArrayRef scopes; 169 CFMutableArrayRef newScopes; 170 171 scopes = CFDictionaryGetValue(dict, kSCPropNetIPv6ScopeID); 172 if (scopes) { 173 newScopes = CFArrayCreateMutableCopy(NULL, 0, scopes); 174 } else { 175 newScopes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 176 } 177 178 scope = CFNumberCreate(NULL, kCFNumberSInt32Type, &sin6->sin6_scope_id); 179 CFArrayAppendValue(newScopes, scope); 180 CFRelease(scope); 181 182 CFDictionarySetValue(dict, kSCPropNetIPv6ScopeID, newScopes); 183 CFRelease(newScopes); 184 return; 185} 186#endif /* NOTYET */ 187 188 189static CFMutableDictionaryRef 190copyIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs) 191{ 192 CFDictionaryRef dict = NULL; 193 CFMutableDictionaryRef newDict = NULL; 194 195 if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) { 196 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 197 } else { 198 dict = SCDynamicStoreCopyValue(store, key); 199 if (dict) { 200 CFDictionarySetValue(oldIFs, key, dict); 201 if (isA_CFDictionary(dict)) { 202 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 203 CFDictionaryRemoveValue(newDict, kSCPropNetIPv6Addresses); 204 CFDictionaryRemoveValue(newDict, kSCPropNetIPv6DestAddresses); 205 CFDictionaryRemoveValue(newDict, kSCPropNetIPv6Flags); 206 CFDictionaryRemoveValue(newDict, kSCPropNetIPv6PrefixLength); 207#ifdef NOTYET 208 CFDictionaryRemoveValue(newDict, kSCPropNetIPv6ScopeID); 209#endif /* NOTYET */ 210 } 211 CFRelease(dict); 212 } 213 } 214 215 if (!newDict) { 216 newDict = CFDictionaryCreateMutable(NULL, 217 0, 218 &kCFTypeDictionaryKeyCallBacks, 219 &kCFTypeDictionaryValueCallBacks); 220 } 221 222 return newDict; 223} 224 225 226static void 227updateStore(const void *key, const void *value, void *context) 228{ 229 CFDictionaryRef dict; 230 CFDictionaryRef newDict = (CFDictionaryRef)value; 231 CFDictionaryRef oldIFs = (CFDictionaryRef)context; 232 233 dict = CFDictionaryGetValue(oldIFs, key); 234 235 if (!dict || !CFEqual(dict, newDict)) { 236 if (CFDictionaryGetCount(newDict) > 0) { 237 SC_log(LOG_DEBUG, "Update interface configuration: %@: %@", key, newDict); 238 SCDynamicStoreSetValue(store, key, newDict); 239 } else if (dict) { 240 CFDictionaryRef oldDict; 241 242 oldDict = SCDynamicStoreCopyValue(store, key); 243 if (oldDict != NULL) { 244 SC_log(LOG_DEBUG, "Update interface configuration: %@: <removed>", key); 245 CFRelease(oldDict); 246 } 247 SCDynamicStoreRemoveValue(store, key); 248 } 249 network_changed = TRUE; 250 } 251 252 return; 253} 254 255 256__private_extern__ 257void 258interface_update_ipv6(struct ifaddrs *ifap, const char *if_name) 259{ 260 struct ifaddrs *ifa; 261 struct ifaddrs *ifap_temp = NULL; 262 CFStringRef interface; 263 boolean_t interfaceFound = FALSE; 264 CFStringRef key = NULL; 265 CFMutableDictionaryRef oldIFs; 266 CFMutableDictionaryRef newDict = NULL; 267 CFMutableDictionaryRef newIFs; 268 int sock = -1; 269 270 oldIFs = CFDictionaryCreateMutable(NULL, 271 0, 272 &kCFTypeDictionaryKeyCallBacks, 273 &kCFTypeDictionaryValueCallBacks); 274 newIFs = CFDictionaryCreateMutable(NULL, 275 0, 276 &kCFTypeDictionaryKeyCallBacks, 277 &kCFTypeDictionaryValueCallBacks); 278 279 if (!ifap) { 280 if (getifaddrs(&ifap_temp) == -1) { 281 SC_log(LOG_NOTICE, "getifaddrs() failed: %s", strerror(errno)); 282 goto error; 283 } 284 ifap = ifap_temp; 285 } 286 287 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 288 struct in6_ifreq ifr6; 289#define flags6 ifr6.ifr_ifru.ifru_flags6 290 struct sockaddr_in6 *sin6; 291 292 if (ifa->ifa_addr->sa_family != AF_INET6) { 293 continue; /* sorry, not interested */ 294 } 295 296 /* check if this is the requested interface */ 297 if (if_name) { 298 if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) { 299 interfaceFound = TRUE; /* yes, this is the one I want */ 300 } else { 301 continue; /* sorry, not interested */ 302 } 303 } 304 305 if (sock == -1) { 306 sock = dgram_socket(AF_INET6); 307 if (sock == -1) { 308 goto error; 309 } 310 } 311 312 /* get the current cache information */ 313 interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman); 314 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 315 kSCDynamicStoreDomainState, 316 interface, 317 kSCEntNetIPv6); 318 CFRelease(interface); 319 320 newDict = copyIF(key, oldIFs, newIFs); 321 322 /* ALIGN: ifa->ifa_addr aligned (getifaddrs), cast ok. */ 323 sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr; 324 325 /* XXX: embedded link local addr check */ 326 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) { 327 u_int16_t index; 328 329 index = sin6->sin6_addr.s6_addr16[1]; 330 if (index != 0) { 331 sin6->sin6_addr.s6_addr16[1] = 0; 332 if (sin6->sin6_scope_id == 0) { 333 sin6->sin6_scope_id = ntohs(index); 334 } 335 } 336 } 337 338 memset((char *)&ifr6, 0, sizeof(ifr6)); 339 strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name)); 340 ifr6.ifr_addr = *sin6; 341 if (ioctl(sock, SIOCGIFAFLAG_IN6, &ifr6) == -1) { 342 /* if flags not available for this address */ 343 SC_log((errno != EADDRNOTAVAIL) ? LOG_NOTICE : LOG_DEBUG, "ioctl() failed: %s", 344 strerror(errno)); 345 } 346 347 appendAddress (newDict, kSCPropNetIPv6Addresses, sin6); 348#ifdef NOTYET 349 appendScopeID (newDict, sin6); 350#endif /* NOTYET */ 351 /* ALIGN: ifa should be aligned (from getifaddrs), cast ok. 352 * appendPrefixLen expect byte alignment */ 353 appendPrefixLen(newDict, (struct sockaddr_in6 *)(void *)ifa->ifa_netmask); 354 appendFlags (newDict, flags6); 355 356 357 if (ifa->ifa_flags & IFF_POINTOPOINT 358 && ifa->ifa_dstaddr != NULL) { 359 struct sockaddr_in6 *dst6; 360 361 /* ALIGN: ifa should be aligned (from getifaddrs), cast ok. */ 362 dst6 = (struct sockaddr_in6 *)(void *)ifa->ifa_dstaddr; 363 364 /* XXX: embedded link local addr check */ 365 if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&dst6->sin6_addr)) { 366 u_int16_t index; 367 368 index = dst6->sin6_addr.s6_addr16[1]; 369 if (index != 0) { 370 dst6->sin6_addr.s6_addr16[1] = 0; 371 if (dst6->sin6_scope_id == 0) { 372 dst6->sin6_scope_id = ntohs(index); 373 } 374 } 375 } 376 377 appendAddress(newDict, kSCPropNetIPv6DestAddresses, dst6); 378 } 379 380 CFDictionarySetValue(newIFs, key, newDict); 381 CFRelease(newDict); 382 CFRelease(key); 383 } 384 385 /* if the last address[es] were removed from the target interface */ 386 if (if_name && !interfaceFound) { 387 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman); 388 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 389 kSCDynamicStoreDomainState, 390 interface, 391 kSCEntNetIPv6); 392 CFRelease(interface); 393 394 newDict = copyIF(key, oldIFs, newIFs); 395 396 CFDictionarySetValue(newIFs, key, newDict); 397 CFRelease(newDict); 398 CFRelease(key); 399 } 400 401 CFDictionaryApplyFunction(newIFs, updateStore, oldIFs); 402 403 error : 404 405 if (ifap_temp) freeifaddrs(ifap_temp); 406 if (sock != -1) close(sock); 407 CFRelease(oldIFs); 408 CFRelease(newIFs); 409 410 return; 411} 412 413__private_extern__ 414void 415ipv6_duplicated_address(const char * if_name, const struct in6_addr * addr, 416 int hw_len, const void * hw_addr) 417{ 418 uint8_t * hw_addr_bytes = (uint8_t *)hw_addr; 419 int i; 420 CFStringRef if_name_cf; 421 CFMutableStringRef key; 422 char ntopbuf[INET6_ADDRSTRLEN]; 423 CFStringRef prefix; 424 425 if_name_cf = CFStringCreateWithCString(NULL, if_name, 426 kCFStringEncodingASCII); 427 prefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 428 kSCDynamicStoreDomainState, 429 if_name_cf, 430 kSCEntNetIPv6DuplicatedAddress); 431 ntopbuf[0] = '\0'; 432 (void)inet_ntop(AF_INET6, addr, ntopbuf, sizeof(ntopbuf)); 433 key = CFStringCreateMutableCopy(NULL, 0, prefix); 434 CFStringAppendFormat(key, NULL, CFSTR("/%s"), ntopbuf); 435 for (i = 0; i < hw_len; i++) { 436 CFStringAppendFormat(key, NULL, CFSTR("%s%02x"), 437 (i == 0) ? "/" : ":", hw_addr_bytes[i]); 438 } 439 SCDynamicStoreNotifyValue(store, key); 440 CFRelease(key); 441 CFRelease(prefix); 442 CFRelease(if_name_cf); 443} 444 445__private_extern__ 446void 447nat64_prefix_request(const char *if_name) 448{ 449 CFStringRef if_name_cf; 450 CFStringRef key; 451 452 if_name_cf = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII); 453 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 454 kSCDynamicStoreDomainState, 455 if_name_cf, 456 kSCEntNetNAT64PrefixRequest); 457 CFRelease(if_name_cf); 458 SC_log(LOG_DEBUG, "Post NAT64 prefix request: %@", key); 459 SCDynamicStoreNotifyValue(store, key); 460 CFRelease(key); 461} 462 463__private_extern__ void 464ipv6_router_expired(const char *if_name) 465{ 466 CFStringRef if_name_cf; 467 CFStringRef key; 468 469 if_name_cf = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII); 470 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 471 kSCDynamicStoreDomainState, 472 if_name_cf, 473 kSCEntNetIPv6RouterExpired); 474 CFRelease(if_name_cf); 475 SC_log(LOG_DEBUG, "Post IPv6 Router Expired: %@", key); 476 SCDynamicStoreNotifyValue(store, key); 477 CFRelease(key); 478}