this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at fixPythonPipStalling 610 lines 14 kB view raw
1/* 2 * Copyright (c) 2009, 2011, 2012, 2014, 2015, 2017-2019 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#include <dirent.h> 25#include <fcntl.h> 26#include <libgen.h> 27#include <netdb.h> 28#include <resolv.h> 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <net/if.h> 33#include <sys/dir.h> 34#include <sys/types.h> 35#include <sys/socket.h> 36#include <unistd.h> 37 38#ifdef MAIN 39#define my_log(__level, __format, ...) SCPrint(TRUE, stdout, CFSTR(__format "\n"), ## __VA_ARGS__) 40#endif // MAIN 41 42#include "dnsinfo.h" 43#include "dnsinfo_private.h" 44#include "dnsinfo_create.h" 45 46static uint32_t _dnsinfo_flatfile_flags; 47 48enum { 49 TOKEN_DOMAIN, 50 TOKEN_FLAGS, 51 TOKEN_INTERFACE, 52 TOKEN_NAMESERVER, 53 TOKEN_OPTIONS, 54 TOKEN_PORT, 55 TOKEN_SEARCH, 56 TOKEN_SEARCH_ORDER, 57 TOKEN_SORTLIST, 58 TOKEN_TIMEOUT, 59 TOKEN_MAX 60}; 61 62/* 63 * tokens 64 * The supported configuration token strings and enumerated values. 65 */ 66static const struct { 67 const char *name; 68 int token; 69 int max_count; 70} tokens [] = { 71 { "domain", TOKEN_DOMAIN, 1 }, 72 { "flags", TOKEN_FLAGS, 1 }, 73 { "interface", TOKEN_INTERFACE, 1 }, 74 { "nameserver", TOKEN_NAMESERVER, MAXNS }, 75 { "options", TOKEN_OPTIONS, 1 }, 76 { "port", TOKEN_PORT, 1 }, 77 { "search", TOKEN_SEARCH, 1 }, 78 { "search_order", TOKEN_SEARCH_ORDER, 1 }, 79 { "sortlist", TOKEN_SORTLIST, 1 }, 80 { "timeout", TOKEN_TIMEOUT, 1 }, 81}; 82 83 84/* 85 * _dnsinfo_parse_address 86 * 87 * Parse IP address 88 */ 89static struct sockaddr * 90_dnsinfo_parse_address(char *nameserver) 91{ 92 struct addrinfo *ai; 93 struct addrinfo hints; 94 int res; 95 struct sockaddr *sa = NULL; 96 97 memset(&hints, 0, sizeof(hints)); 98 hints.ai_flags = AI_NUMERICHOST; 99 100 res = getaddrinfo(nameserver, NULL, &hints, &ai); 101 if (res == 0) { 102 if ((ai->ai_family == AF_INET) || (ai->ai_family == AF_INET6)) { 103 sa = malloc(ai->ai_addrlen); 104 memcpy(sa, ai->ai_addr, ai->ai_addrlen); 105 } 106 freeaddrinfo(ai); 107 } 108 109 return sa; 110} 111 112 113/* 114 * _dnsinfo_parse_nameserver 115 * 116 * Parse arguments to the nameserver token. This is essentially a getaddrinfo(3) 117 * with AI_NUMERICHOST. However, if the conversion fails, check if the address 118 * contains an optional trailing '.' followed by a numeric port number. If found, 119 * remove the port number and retry the conversion (e.g. 127.0.0.1.55 or ::1.55). 120 */ 121static struct sockaddr * 122_dnsinfo_parse_nameserver(char *token) 123{ 124 char *dot; 125 long number; 126 struct sockaddr *sa; 127 128 sa = _dnsinfo_parse_address(token); 129 if (sa != NULL) { 130 return sa; 131 } 132 133 // if we could not parse address, attempt to remove 134 // an optional trailing port number 135 dot = strrchr(token, '.'); 136 if (dot == NULL) { 137 return NULL; 138 } 139 140 number = strtol(dot + 1, NULL, 10); 141 if ((number < 0) || (number > UINT16_MAX)) { 142 return NULL; 143 } 144 145 *dot = '\0'; 146 sa = _dnsinfo_parse_address(token); 147 if (sa != NULL) { 148 in_port_t port = htons(number); 149 150 switch (sa->sa_family) { 151 case AF_INET : 152 /* ALIGN: cast ok, sockaddr was malloc'd */ 153 ((struct sockaddr_in *)(void *)sa)->sin_port = port; 154 break; 155 case AF_INET6 : 156 /* ALIGN: cast ok, sockaddr was malloc'd */ 157 ((struct sockaddr_in6 *)(void *)sa)->sin6_port = port; 158 break; 159 } 160 } 161 162 return sa; 163} 164 165 166/* 167 * _dnsinfo_parse_sortaddr 168 * 169 * Parse arguments to the sortlist token. 170 */ 171static dns_sortaddr_t * 172_dnsinfo_parse_sortaddr(char *token) 173{ 174 struct in_addr addr; 175 struct in_addr mask; 176 struct sockaddr *sa; 177 char *slash; 178 dns_sortaddr_t *sortaddr = NULL; 179 180 slash = strchr(token, '/'); 181 if (slash != NULL) { 182 *slash = '\0'; 183 } 184 185 sa = _dnsinfo_parse_address(token); 186 if (sa == NULL) { 187 // if we could not parse the address 188 goto done; 189 } else if (sa->sa_family != AF_INET) { 190 // if not AF_INET 191 goto done; 192 } else { 193 /* ALIGN: cast ok, sockaddr was malloc'd */ 194 addr = ((struct sockaddr_in *)(void *)sa)->sin_addr; 195 free(sa); 196 sa = NULL; 197 } 198 199 if (slash != NULL) { 200 sa = _dnsinfo_parse_address(slash + 1); 201 if (sa == NULL) { 202 // if we could not parse the provided mask 203 goto done; 204 } else if (sa->sa_family != AF_INET) { 205 // if mask not AF_INET 206 goto done; 207 } else { 208 /* ALIGN: cast ok, sockaddr was malloc'd */ 209 mask = ((struct sockaddr_in *)(void *)sa)->sin_addr; 210 free(sa); 211 sa = NULL; 212 } 213 } else { 214 in_addr_t a; 215 in_addr_t m; 216 217 a = ntohl(addr.s_addr); 218 if (IN_CLASSA(a)) { 219 m = IN_CLASSA_NET; 220 } else if (IN_CLASSB(a)) { 221 m = IN_CLASSB_NET; 222 } else if (IN_CLASSC(a)) { 223 m = IN_CLASSC_NET; 224 } else { 225 goto done; 226 } 227 228 mask.s_addr = htonl(m); 229 } 230 231 sortaddr = malloc(sizeof(*sortaddr)); 232 sortaddr->address = addr; 233 sortaddr->mask = mask; 234 235 done : 236 237 if (sa != NULL) free(sa); 238 return sortaddr; 239} 240 241 242/* 243 * _dnsinfo_flatfile_set_flags 244 * 245 * Set the default resolver flags. 246 */ 247__private_extern__ 248void 249_dnsinfo_flatfile_set_flags(uint32_t flags) 250{ 251 _dnsinfo_flatfile_flags = flags; 252 return; 253} 254 255 256static void 257_dnsinfo_flatfile_update_flags(dns_create_resolver_t *_resolver) 258{ 259 uint32_t new_flags; 260 uint32_t old_flags; 261 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver; 262 263 old_flags = ntohl(resolver->resolver.flags); 264 new_flags = old_flags | _dnsinfo_flatfile_flags; 265 _dns_resolver_set_flags(_resolver, new_flags); 266 return; 267} 268 269 270/* 271 * _dnsinfo_flatfile_create_resolver 272 * 273 * Create a new dns resolver configuration from the configuration file at the 274 * specified path. (e.g. /etc/resolv.conf or /etc/resolver/apple.com) 275 */ 276static dns_create_resolver_t 277_dnsinfo_flatfile_create_resolver(const char *dir, const char *path) 278{ 279 char *buf; 280 uint32_t config_flags = 0; 281 FILE *f; 282 char filename[FILENAME_MAX]; 283 size_t len = 0; 284 char *line = NULL; 285 dns_create_resolver_t res = NULL; 286 const char *sep = " \t"; 287 int token_count[TOKEN_MAX] = { 0 }; 288 289 filename[0] = 0; 290 if (dir != NULL) { 291 strlcpy(filename, dir, sizeof(filename)); 292 strlcat(filename, "/", sizeof(filename)); 293 } 294 strlcat(filename, path, sizeof(filename)); 295 296 f = fopen(filename, "r"); 297 if (f == NULL) return NULL; 298 299 while ((buf = fgetln(f, &len)) != NULL) { 300 char *lineptr; 301 int max_count; 302 int token; 303 char *word; 304 305 if (len == 0) continue; 306 if (buf[len-1] == '\n') buf[len-1] = '\0'; 307 308 line = reallocf(line, len+1); 309 if (line == NULL) continue; 310 311 strlcpy(line, buf, len+1); 312 313 // parse the first word of the line (the config token) 314 lineptr = line; 315 word = strsep(&lineptr, sep); 316 if (word == NULL) { 317 // if empty line 318 continue; 319 } 320 if (word[0] == ';' || word[0] == '#') { 321 // if comment 322 continue; 323 } 324 325 // translate config token to enumerated value 326 token = -1; 327 for (size_t i = 0; i < sizeof(tokens) / sizeof(tokens[0]); i++) { 328 if (strcasecmp(word, tokens[i].name) == 0) { 329 token = tokens[i].token; 330 max_count = tokens[i].max_count; 331 break; 332 } 333 } 334 if (token == -1) { 335 // if not a recognized token 336 continue; 337 } 338 339 // parse the next word of the line (the config option) 340 word = strsep(&lineptr, sep); 341 if (word == NULL) { 342 // if no option 343 continue; 344 } 345 if (++token_count[token] > max_count) { 346 // if too many options 347 continue; 348 } 349 350 // create resolver 351 if (res == NULL) { 352 res = _dns_resolver_create(); 353 if (res == NULL) { 354 // if we could not create a resolver 355 goto done; 356 } 357 } 358 359 switch (token) { 360 case TOKEN_DOMAIN: { 361 size_t len; 362 363 len = strlen(word); 364 while ((len > 0) && (word[len - 1] == '.')) { 365 // trim trailing '.' 366 word[--len] = '\0'; 367 } 368 if (len > 0) { 369 _dns_resolver_set_domain(&res, word); 370 } 371 break; 372 } 373 374 case TOKEN_FLAGS: { 375 while (word != NULL) { 376 if (word[0] != '\0') { 377 if (strcasecmp(word, "scoped") == 0) { 378 config_flags |= DNS_RESOLVER_FLAGS_SCOPED; 379 } else if (strcasecmp(word, "a") == 0) { 380 config_flags |= DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS; 381 } else if (strcasecmp(word, "aaaa") == 0) { 382 config_flags |= DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS; 383 } 384 } 385 word = strsep(&lineptr, sep); 386 } 387 break; 388 } 389 390 case TOKEN_INTERFACE: { 391 unsigned int if_index; 392 393 if_index = if_nametoindex(word); 394 if (if_index > 0) { 395 _dns_resolver_set_if_index(&res, if_index, word); 396 } 397 break; 398 } 399 400 case TOKEN_NAMESERVER: { 401 struct sockaddr *sa; 402 403 sa = _dnsinfo_parse_nameserver(word); 404 if (sa != NULL) { 405 _dns_resolver_add_nameserver(&res, sa); 406 free(sa); 407 } 408 break; 409 } 410 411 case TOKEN_OPTIONS: { 412 char *options = NULL; 413 414 while (word != NULL) { 415 if (word[0] != '\0') { 416 if (options == NULL) { 417 options = malloc(len+1); 418 if (options == NULL) break; 419 420 strlcpy(options, word, len+1); 421 } else { 422 strlcat(options, " ", len+1); 423 strlcat(options, word, len+1); 424 } 425 } 426 word = strsep(&lineptr, sep); 427 } 428 429 if (options != NULL) { 430 _dns_resolver_set_options(&res, options); 431 free(options); 432 } 433 break; 434 } 435 436 case TOKEN_PORT: { 437 long number = -1; 438 439 number = strtol(word, NULL, 0); 440 if (number < 0 || number > UINT16_MAX) break; 441 _dns_resolver_set_port(&res, number); 442 break; 443 } 444 445 case TOKEN_SEARCH: { 446 int n = 0; 447 448 // multiple search domains are supported 449 while ((word != NULL) && (n++ < MAXDNSRCH)) { 450 size_t len; 451 452 len = strlen(word); 453 while ((len > 0) && (word[len - 1] == '.')) { 454 // trim trailing '.' 455 word[--len] = '\0'; 456 } 457 if (len > 0) { 458 _dns_resolver_add_search(&res, word); 459 } 460 word = strsep(&lineptr, sep); 461 } 462 break; 463 } 464 465 case TOKEN_SEARCH_ORDER: { 466 long number = -1; 467 468 number = strtol(word, NULL, 0); 469 if (number < 0 || number > (long)UINT32_MAX) break; 470 _dns_resolver_set_order(&res, (uint32_t)number); 471 break; 472 } 473 474 case TOKEN_SORTLIST: { 475 int n = 0; 476 477 while ((word != NULL) && (n++ < MAXRESOLVSORT)) { 478 dns_sortaddr_t *sortaddr; 479 480 sortaddr = _dnsinfo_parse_sortaddr(word); 481 if (sortaddr == NULL) break; 482 _dns_resolver_add_sortaddr(&res, sortaddr); 483 free(sortaddr); 484 word = strsep(&lineptr, sep); 485 } 486 break; 487 } 488 489 case TOKEN_TIMEOUT: { 490 long number = -1; 491 492 number = strtol(word, NULL, 0); 493 if (number < 0 || number > (long)UINT32_MAX) break; 494 _dns_resolver_set_timeout(&res, (uint32_t)number); 495 break; 496 } 497 } 498 } 499 500 // set the domain to the basename of the path if not specified 501 if ((res != NULL) && (token_count[TOKEN_DOMAIN] == 0)) { 502 const char *domain; 503 504 domain = strrchr(path, '/'); 505 if (domain == NULL) { 506 domain = path; 507 } else { 508 domain = domain + 1; 509 } 510 _dns_resolver_set_domain(&res, domain); 511 } 512 513 if (res != NULL) { 514 // config flags should overwrite any default flags 515 if (config_flags != 0) { 516 _dns_resolver_set_flags(&res, config_flags); 517 } else { 518 _dnsinfo_flatfile_update_flags(&res); 519 } 520 } 521 522 done : 523 524 if (line != NULL) free(line); 525 fclose(f); 526 return res; 527} 528 529 530/* 531 * _dnsinfo_flatfile_add_resolvers 532 * 533 * Parse the files in the resolver config directory (/etc/resolver) and add each 534 * resolver to the dns config. 535 */ 536__private_extern__ 537void 538_dnsinfo_flatfile_add_resolvers(dns_create_config_t *config) 539{ 540 struct dirent *de; 541 DIR *dp; 542 dns_create_resolver_t res; 543 544 dp = opendir(_PATH_RESOLVER_DIR); 545 if (dp == NULL) { 546 return; 547 } 548 549 while ((de = readdir(dp)) != NULL) { 550 if (strcmp(de->d_name, ".") == 0 || 551 strcmp(de->d_name, "..") == 0) continue; 552 553 res = _dnsinfo_flatfile_create_resolver(_PATH_RESOLVER_DIR, de->d_name); 554 if (res != NULL) { 555 _dns_configuration_add_resolver(config, res); 556 _dns_resolver_free(&res); 557 } 558 } 559 560 closedir(dp); 561 return; 562} 563 564 565#ifdef MAIN 566#undef MAIN 567 568#include "dnsinfo_logging.h" 569#include "dnsinfo_copy.c" 570 571int 572main(int argc, char **argv) 573{ 574 dns_config_t *dns_config = NULL; 575 _dns_config_buf_t *dns_config_buf = NULL; 576 dns_create_config_t dns_create_config; 577 dns_create_resolver_t dns_create_resolver; 578 579 dns_create_resolver = _dnsinfo_flatfile_create_resolver(NULL, _PATH_RESCONF); 580 _dns_resolver_free(&dns_create_resolver); 581 582 dns_create_config = _dns_configuration_create(); 583 if (dns_create_config != NULL) { 584 size_t n; 585 586 _dnsinfo_flatfile_add_resolvers(&dns_create_config); 587 588 n = sizeof(_dns_config_buf_t); 589 n += ntohl(((_dns_config_buf_t *)dns_create_config)->n_attribute); 590 dns_config_buf = _dns_configuration_buffer_create((void *)dns_create_config, n); 591 _dns_configuration_free(&dns_create_config); 592 } 593 594 if (dns_config_buf != NULL) { 595 dns_config = _dns_configuration_buffer_expand(dns_config_buf); 596 if (dns_config == NULL) { 597 // if we were unable to expand the configuration 598 _dns_configuration_buffer_free(&dns_config_buf); 599 } 600 } 601 602 if (dns_config != NULL) { 603 _dns_configuration_log(dns_config, TRUE, NULL); 604 free(dns_config); 605 } 606 607 return 0; 608} 609 610#endif