Annotation of embedaddon/nginx/src/core/ngx_inet.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10:
! 11:
! 12: static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
! 13: static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
! 14: static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
! 15:
! 16:
! 17: in_addr_t
! 18: ngx_inet_addr(u_char *text, size_t len)
! 19: {
! 20: u_char *p, c;
! 21: in_addr_t addr;
! 22: ngx_uint_t octet, n;
! 23:
! 24: addr = 0;
! 25: octet = 0;
! 26: n = 0;
! 27:
! 28: for (p = text; p < text + len; p++) {
! 29:
! 30: c = *p;
! 31:
! 32: if (c >= '0' && c <= '9') {
! 33: octet = octet * 10 + (c - '0');
! 34: continue;
! 35: }
! 36:
! 37: if (c == '.' && octet < 256) {
! 38: addr = (addr << 8) + octet;
! 39: octet = 0;
! 40: n++;
! 41: continue;
! 42: }
! 43:
! 44: return INADDR_NONE;
! 45: }
! 46:
! 47: if (n == 3 && octet < 256) {
! 48: addr = (addr << 8) + octet;
! 49: return htonl(addr);
! 50: }
! 51:
! 52: return INADDR_NONE;
! 53: }
! 54:
! 55:
! 56: #if (NGX_HAVE_INET6)
! 57:
! 58: ngx_int_t
! 59: ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
! 60: {
! 61: u_char c, *zero, *digit, *s, *d;
! 62: size_t len4;
! 63: ngx_uint_t n, nibbles, word;
! 64:
! 65: if (len == 0) {
! 66: return NGX_ERROR;
! 67: }
! 68:
! 69: zero = NULL;
! 70: digit = NULL;
! 71: len4 = 0;
! 72: nibbles = 0;
! 73: word = 0;
! 74: n = 8;
! 75:
! 76: if (p[0] == ':') {
! 77: p++;
! 78: len--;
! 79: }
! 80:
! 81: for (/* void */; len; len--) {
! 82: c = *p++;
! 83:
! 84: if (c == ':') {
! 85: if (nibbles) {
! 86: digit = p;
! 87: len4 = len;
! 88: *addr++ = (u_char) (word >> 8);
! 89: *addr++ = (u_char) (word & 0xff);
! 90:
! 91: if (--n) {
! 92: nibbles = 0;
! 93: word = 0;
! 94: continue;
! 95: }
! 96:
! 97: } else {
! 98: if (zero == NULL) {
! 99: digit = p;
! 100: len4 = len;
! 101: zero = addr;
! 102: continue;
! 103: }
! 104: }
! 105:
! 106: return NGX_ERROR;
! 107: }
! 108:
! 109: if (c == '.' && nibbles) {
! 110: if (n < 2 || digit == NULL) {
! 111: return NGX_ERROR;
! 112: }
! 113:
! 114: word = ngx_inet_addr(digit, len4 - 1);
! 115: if (word == INADDR_NONE) {
! 116: return NGX_ERROR;
! 117: }
! 118:
! 119: word = ntohl(word);
! 120: *addr++ = (u_char) ((word >> 24) & 0xff);
! 121: *addr++ = (u_char) ((word >> 16) & 0xff);
! 122: n--;
! 123: break;
! 124: }
! 125:
! 126: if (++nibbles > 4) {
! 127: return NGX_ERROR;
! 128: }
! 129:
! 130: if (c >= '0' && c <= '9') {
! 131: word = word * 16 + (c - '0');
! 132: continue;
! 133: }
! 134:
! 135: c |= 0x20;
! 136:
! 137: if (c >= 'a' && c <= 'f') {
! 138: word = word * 16 + (c - 'a') + 10;
! 139: continue;
! 140: }
! 141:
! 142: return NGX_ERROR;
! 143: }
! 144:
! 145: if (nibbles == 0 && zero == NULL) {
! 146: return NGX_ERROR;
! 147: }
! 148:
! 149: *addr++ = (u_char) (word >> 8);
! 150: *addr++ = (u_char) (word & 0xff);
! 151:
! 152: if (--n) {
! 153: if (zero) {
! 154: n *= 2;
! 155: s = addr - 1;
! 156: d = s + n;
! 157: while (s >= zero) {
! 158: *d-- = *s--;
! 159: }
! 160: ngx_memzero(zero, n);
! 161: return NGX_OK;
! 162: }
! 163:
! 164: } else {
! 165: if (zero == NULL) {
! 166: return NGX_OK;
! 167: }
! 168: }
! 169:
! 170: return NGX_ERROR;
! 171: }
! 172:
! 173: #endif
! 174:
! 175:
! 176: size_t
! 177: ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
! 178: {
! 179: u_char *p;
! 180: struct sockaddr_in *sin;
! 181: #if (NGX_HAVE_INET6)
! 182: size_t n;
! 183: struct sockaddr_in6 *sin6;
! 184: #endif
! 185: #if (NGX_HAVE_UNIX_DOMAIN)
! 186: struct sockaddr_un *saun;
! 187: #endif
! 188:
! 189: switch (sa->sa_family) {
! 190:
! 191: case AF_INET:
! 192:
! 193: sin = (struct sockaddr_in *) sa;
! 194: p = (u_char *) &sin->sin_addr;
! 195:
! 196: if (port) {
! 197: p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
! 198: p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
! 199: } else {
! 200: p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
! 201: p[0], p[1], p[2], p[3]);
! 202: }
! 203:
! 204: return (p - text);
! 205:
! 206: #if (NGX_HAVE_INET6)
! 207:
! 208: case AF_INET6:
! 209:
! 210: sin6 = (struct sockaddr_in6 *) sa;
! 211:
! 212: n = 0;
! 213:
! 214: if (port) {
! 215: text[n++] = '[';
! 216: }
! 217:
! 218: n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
! 219:
! 220: if (port) {
! 221: n = ngx_sprintf(&text[1 + n], "]:%d",
! 222: ntohs(sin6->sin6_port)) - text;
! 223: }
! 224:
! 225: return n;
! 226: #endif
! 227:
! 228: #if (NGX_HAVE_UNIX_DOMAIN)
! 229:
! 230: case AF_UNIX:
! 231: saun = (struct sockaddr_un *) sa;
! 232:
! 233: /* we do not include trailing zero in address length */
! 234:
! 235: return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
! 236:
! 237: #endif
! 238:
! 239: default:
! 240: return 0;
! 241: }
! 242: }
! 243:
! 244:
! 245: size_t
! 246: ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
! 247: {
! 248: u_char *p;
! 249:
! 250: switch (family) {
! 251:
! 252: case AF_INET:
! 253:
! 254: p = addr;
! 255:
! 256: return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
! 257: p[0], p[1], p[2], p[3])
! 258: - text;
! 259:
! 260: #if (NGX_HAVE_INET6)
! 261:
! 262: case AF_INET6:
! 263: return ngx_inet6_ntop(addr, text, len);
! 264:
! 265: #endif
! 266:
! 267: default:
! 268: return 0;
! 269: }
! 270: }
! 271:
! 272:
! 273: #if (NGX_HAVE_INET6)
! 274:
! 275: size_t
! 276: ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
! 277: {
! 278: u_char *dst;
! 279: size_t max, n;
! 280: ngx_uint_t i, zero, last;
! 281:
! 282: if (len < NGX_INET6_ADDRSTRLEN) {
! 283: return 0;
! 284: }
! 285:
! 286: zero = (ngx_uint_t) -1;
! 287: last = (ngx_uint_t) -1;
! 288: max = 1;
! 289: n = 0;
! 290:
! 291: for (i = 0; i < 16; i += 2) {
! 292:
! 293: if (p[i] || p[i + 1]) {
! 294:
! 295: if (max < n) {
! 296: zero = last;
! 297: max = n;
! 298: }
! 299:
! 300: n = 0;
! 301: continue;
! 302: }
! 303:
! 304: if (n++ == 0) {
! 305: last = i;
! 306: }
! 307: }
! 308:
! 309: if (max < n) {
! 310: zero = last;
! 311: max = n;
! 312: }
! 313:
! 314: dst = text;
! 315: n = 16;
! 316:
! 317: if (zero == 0) {
! 318:
! 319: if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
! 320: || (max == 6)
! 321: || (max == 7 && p[14] != 0 && p[15] != 1))
! 322: {
! 323: n = 12;
! 324: }
! 325:
! 326: *dst++ = ':';
! 327: }
! 328:
! 329: for (i = 0; i < n; i += 2) {
! 330:
! 331: if (i == zero) {
! 332: *dst++ = ':';
! 333: i += (max - 1) * 2;
! 334: continue;
! 335: }
! 336:
! 337: dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
! 338:
! 339: if (i < 14) {
! 340: *dst++ = ':';
! 341: }
! 342: }
! 343:
! 344: if (n == 12) {
! 345: dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
! 346: }
! 347:
! 348: return dst - text;
! 349: }
! 350:
! 351: #endif
! 352:
! 353:
! 354: ngx_int_t
! 355: ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
! 356: {
! 357: u_char *addr, *mask, *last;
! 358: size_t len;
! 359: ngx_int_t shift;
! 360: #if (NGX_HAVE_INET6)
! 361: ngx_int_t rc;
! 362: ngx_uint_t s, i;
! 363: #endif
! 364:
! 365: addr = text->data;
! 366: last = addr + text->len;
! 367:
! 368: mask = ngx_strlchr(addr, last, '/');
! 369: len = (mask ? mask : last) - addr;
! 370:
! 371: cidr->u.in.addr = ngx_inet_addr(addr, len);
! 372:
! 373: if (cidr->u.in.addr != INADDR_NONE) {
! 374: cidr->family = AF_INET;
! 375:
! 376: if (mask == NULL) {
! 377: cidr->u.in.mask = 0xffffffff;
! 378: return NGX_OK;
! 379: }
! 380:
! 381: #if (NGX_HAVE_INET6)
! 382: } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
! 383: cidr->family = AF_INET6;
! 384:
! 385: if (mask == NULL) {
! 386: ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
! 387: return NGX_OK;
! 388: }
! 389:
! 390: #endif
! 391: } else {
! 392: return NGX_ERROR;
! 393: }
! 394:
! 395: mask++;
! 396:
! 397: shift = ngx_atoi(mask, last - mask);
! 398: if (shift == NGX_ERROR) {
! 399: return NGX_ERROR;
! 400: }
! 401:
! 402: switch (cidr->family) {
! 403:
! 404: #if (NGX_HAVE_INET6)
! 405: case AF_INET6:
! 406: if (shift > 128) {
! 407: return NGX_ERROR;
! 408: }
! 409:
! 410: addr = cidr->u.in6.addr.s6_addr;
! 411: mask = cidr->u.in6.mask.s6_addr;
! 412: rc = NGX_OK;
! 413:
! 414: for (i = 0; i < 16; i++) {
! 415:
! 416: s = (shift > 8) ? 8 : shift;
! 417: shift -= s;
! 418:
! 419: mask[i] = (u_char) (0xffu << (8 - s));
! 420:
! 421: if (addr[i] != (addr[i] & mask[i])) {
! 422: rc = NGX_DONE;
! 423: addr[i] &= mask[i];
! 424: }
! 425: }
! 426:
! 427: return rc;
! 428: #endif
! 429:
! 430: default: /* AF_INET */
! 431: if (shift > 32) {
! 432: return NGX_ERROR;
! 433: }
! 434:
! 435: if (shift) {
! 436: cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
! 437:
! 438: } else {
! 439: /* x86 compilers use a shl instruction that shifts by modulo 32 */
! 440: cidr->u.in.mask = 0;
! 441: }
! 442:
! 443: if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
! 444: return NGX_OK;
! 445: }
! 446:
! 447: cidr->u.in.addr &= cidr->u.in.mask;
! 448:
! 449: return NGX_DONE;
! 450: }
! 451: }
! 452:
! 453:
! 454: ngx_int_t
! 455: ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
! 456: {
! 457: in_addr_t inaddr;
! 458: ngx_uint_t family;
! 459: struct sockaddr_in *sin;
! 460: #if (NGX_HAVE_INET6)
! 461: struct in6_addr inaddr6;
! 462: struct sockaddr_in6 *sin6;
! 463:
! 464: /*
! 465: * prevent MSVC8 warning:
! 466: * potentially uninitialized local variable 'inaddr6' used
! 467: */
! 468: ngx_memzero(&inaddr6, sizeof(struct in6_addr));
! 469: #endif
! 470:
! 471: inaddr = ngx_inet_addr(text, len);
! 472:
! 473: if (inaddr != INADDR_NONE) {
! 474: family = AF_INET;
! 475: len = sizeof(struct sockaddr_in);
! 476:
! 477: #if (NGX_HAVE_INET6)
! 478: } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
! 479: family = AF_INET6;
! 480: len = sizeof(struct sockaddr_in6);
! 481:
! 482: #endif
! 483: } else {
! 484: return NGX_DECLINED;
! 485: }
! 486:
! 487: addr->sockaddr = ngx_pcalloc(pool, len);
! 488: if (addr->sockaddr == NULL) {
! 489: return NGX_ERROR;
! 490: }
! 491:
! 492: addr->sockaddr->sa_family = (u_char) family;
! 493: addr->socklen = len;
! 494:
! 495: switch (family) {
! 496:
! 497: #if (NGX_HAVE_INET6)
! 498: case AF_INET6:
! 499: sin6 = (struct sockaddr_in6 *) addr->sockaddr;
! 500: ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
! 501: break;
! 502: #endif
! 503:
! 504: default: /* AF_INET */
! 505: sin = (struct sockaddr_in *) addr->sockaddr;
! 506: sin->sin_addr.s_addr = inaddr;
! 507: break;
! 508: }
! 509:
! 510: return NGX_OK;
! 511: }
! 512:
! 513:
! 514: ngx_int_t
! 515: ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
! 516: {
! 517: u_char *p;
! 518:
! 519: p = u->url.data;
! 520:
! 521: if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
! 522: return ngx_parse_unix_domain_url(pool, u);
! 523: }
! 524:
! 525: if (p[0] == '[') {
! 526: return ngx_parse_inet6_url(pool, u);
! 527: }
! 528:
! 529: return ngx_parse_inet_url(pool, u);
! 530: }
! 531:
! 532:
! 533: static ngx_int_t
! 534: ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
! 535: {
! 536: #if (NGX_HAVE_UNIX_DOMAIN)
! 537: u_char *path, *uri, *last;
! 538: size_t len;
! 539: struct sockaddr_un *saun;
! 540:
! 541: len = u->url.len;
! 542: path = u->url.data;
! 543:
! 544: path += 5;
! 545: len -= 5;
! 546:
! 547: if (u->uri_part) {
! 548:
! 549: last = path + len;
! 550: uri = ngx_strlchr(path, last, ':');
! 551:
! 552: if (uri) {
! 553: len = uri - path;
! 554: uri++;
! 555: u->uri.len = last - uri;
! 556: u->uri.data = uri;
! 557: }
! 558: }
! 559:
! 560: if (len == 0) {
! 561: u->err = "no path in the unix domain socket";
! 562: return NGX_ERROR;
! 563: }
! 564:
! 565: u->host.len = len++;
! 566: u->host.data = path;
! 567:
! 568: if (len > sizeof(saun->sun_path)) {
! 569: u->err = "too long path in the unix domain socket";
! 570: return NGX_ERROR;
! 571: }
! 572:
! 573: u->socklen = sizeof(struct sockaddr_un);
! 574: saun = (struct sockaddr_un *) &u->sockaddr;
! 575: saun->sun_family = AF_UNIX;
! 576: (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
! 577:
! 578: u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
! 579: if (u->addrs == NULL) {
! 580: return NGX_ERROR;
! 581: }
! 582:
! 583: saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
! 584: if (saun == NULL) {
! 585: return NGX_ERROR;
! 586: }
! 587:
! 588: u->family = AF_UNIX;
! 589: u->naddrs = 1;
! 590:
! 591: saun->sun_family = AF_UNIX;
! 592: (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
! 593:
! 594: u->addrs[0].sockaddr = (struct sockaddr *) saun;
! 595: u->addrs[0].socklen = sizeof(struct sockaddr_un);
! 596: u->addrs[0].name.len = len + 4;
! 597: u->addrs[0].name.data = u->url.data;
! 598:
! 599: return NGX_OK;
! 600:
! 601: #else
! 602:
! 603: u->err = "the unix domain sockets are not supported on this platform";
! 604:
! 605: return NGX_ERROR;
! 606:
! 607: #endif
! 608: }
! 609:
! 610:
! 611: static ngx_int_t
! 612: ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
! 613: {
! 614: u_char *p, *host, *port, *last, *uri, *args;
! 615: size_t len;
! 616: ngx_int_t n;
! 617: struct sockaddr_in *sin;
! 618: #if (NGX_HAVE_INET6)
! 619: struct sockaddr_in6 *sin6;
! 620: #endif
! 621:
! 622: u->socklen = sizeof(struct sockaddr_in);
! 623: sin = (struct sockaddr_in *) &u->sockaddr;
! 624: sin->sin_family = AF_INET;
! 625:
! 626: u->family = AF_INET;
! 627:
! 628: host = u->url.data;
! 629:
! 630: last = host + u->url.len;
! 631:
! 632: port = ngx_strlchr(host, last, ':');
! 633:
! 634: uri = ngx_strlchr(host, last, '/');
! 635:
! 636: args = ngx_strlchr(host, last, '?');
! 637:
! 638: if (args) {
! 639: if (uri == NULL || args < uri) {
! 640: uri = args;
! 641: }
! 642: }
! 643:
! 644: if (uri) {
! 645: if (u->listen || !u->uri_part) {
! 646: u->err = "invalid host";
! 647: return NGX_ERROR;
! 648: }
! 649:
! 650: u->uri.len = last - uri;
! 651: u->uri.data = uri;
! 652:
! 653: last = uri;
! 654:
! 655: if (uri < port) {
! 656: port = NULL;
! 657: }
! 658: }
! 659:
! 660: if (port) {
! 661: port++;
! 662:
! 663: len = last - port;
! 664:
! 665: n = ngx_atoi(port, len);
! 666:
! 667: if (n < 1 || n > 65535) {
! 668: u->err = "invalid port";
! 669: return NGX_ERROR;
! 670: }
! 671:
! 672: u->port = (in_port_t) n;
! 673: sin->sin_port = htons((in_port_t) n);
! 674:
! 675: u->port_text.len = len;
! 676: u->port_text.data = port;
! 677:
! 678: last = port - 1;
! 679:
! 680: } else {
! 681: if (uri == NULL) {
! 682:
! 683: if (u->listen) {
! 684:
! 685: /* test value as port only */
! 686:
! 687: n = ngx_atoi(host, last - host);
! 688:
! 689: if (n != NGX_ERROR) {
! 690:
! 691: if (n < 1 || n > 65535) {
! 692: u->err = "invalid port";
! 693: return NGX_ERROR;
! 694: }
! 695:
! 696: u->port = (in_port_t) n;
! 697: sin->sin_port = htons((in_port_t) n);
! 698:
! 699: u->port_text.len = last - host;
! 700: u->port_text.data = host;
! 701:
! 702: u->wildcard = 1;
! 703:
! 704: return NGX_OK;
! 705: }
! 706: }
! 707: }
! 708:
! 709: u->no_port = 1;
! 710: u->port = u->default_port;
! 711: sin->sin_port = htons(u->default_port);
! 712: }
! 713:
! 714: len = last - host;
! 715:
! 716: if (len == 0) {
! 717: u->err = "no host";
! 718: return NGX_ERROR;
! 719: }
! 720:
! 721: u->host.len = len;
! 722: u->host.data = host;
! 723:
! 724: if (u->listen && len == 1 && *host == '*') {
! 725: sin->sin_addr.s_addr = INADDR_ANY;
! 726: u->wildcard = 1;
! 727: return NGX_OK;
! 728: }
! 729:
! 730: sin->sin_addr.s_addr = ngx_inet_addr(host, len);
! 731:
! 732: if (sin->sin_addr.s_addr != INADDR_NONE) {
! 733:
! 734: if (sin->sin_addr.s_addr == INADDR_ANY) {
! 735: u->wildcard = 1;
! 736: }
! 737:
! 738: u->naddrs = 1;
! 739:
! 740: u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
! 741: if (u->addrs == NULL) {
! 742: return NGX_ERROR;
! 743: }
! 744:
! 745: sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
! 746: if (sin == NULL) {
! 747: return NGX_ERROR;
! 748: }
! 749:
! 750: ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in));
! 751:
! 752: u->addrs[0].sockaddr = (struct sockaddr *) sin;
! 753: u->addrs[0].socklen = sizeof(struct sockaddr_in);
! 754:
! 755: p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
! 756: if (p == NULL) {
! 757: return NGX_ERROR;
! 758: }
! 759:
! 760: u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
! 761: &u->host, u->port) - p;
! 762: u->addrs[0].name.data = p;
! 763:
! 764: return NGX_OK;
! 765: }
! 766:
! 767: if (u->no_resolve) {
! 768: return NGX_OK;
! 769: }
! 770:
! 771: if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
! 772: return NGX_ERROR;
! 773: }
! 774:
! 775: u->family = u->addrs[0].sockaddr->sa_family;
! 776: u->socklen = u->addrs[0].socklen;
! 777: ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
! 778:
! 779: switch (u->family) {
! 780:
! 781: #if (NGX_HAVE_INET6)
! 782: case AF_INET6:
! 783: sin6 = (struct sockaddr_in6 *) &u->sockaddr;
! 784:
! 785: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
! 786: u->wildcard = 1;
! 787: }
! 788:
! 789: break;
! 790: #endif
! 791:
! 792: default: /* AF_INET */
! 793: sin = (struct sockaddr_in *) &u->sockaddr;
! 794:
! 795: if (sin->sin_addr.s_addr == INADDR_ANY) {
! 796: u->wildcard = 1;
! 797: }
! 798:
! 799: break;
! 800: }
! 801:
! 802: return NGX_OK;
! 803: }
! 804:
! 805:
! 806: static ngx_int_t
! 807: ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
! 808: {
! 809: #if (NGX_HAVE_INET6)
! 810: u_char *p, *host, *port, *last, *uri;
! 811: size_t len;
! 812: ngx_int_t n;
! 813: struct sockaddr_in6 *sin6;
! 814:
! 815: u->socklen = sizeof(struct sockaddr_in6);
! 816: sin6 = (struct sockaddr_in6 *) &u->sockaddr;
! 817: sin6->sin6_family = AF_INET6;
! 818:
! 819: host = u->url.data + 1;
! 820:
! 821: last = u->url.data + u->url.len;
! 822:
! 823: p = ngx_strlchr(host, last, ']');
! 824:
! 825: if (p == NULL) {
! 826: u->err = "invalid host";
! 827: return NGX_ERROR;
! 828: }
! 829:
! 830: if (last - p) {
! 831:
! 832: port = p + 1;
! 833:
! 834: uri = ngx_strlchr(port, last, '/');
! 835:
! 836: if (uri) {
! 837: if (u->listen || !u->uri_part) {
! 838: u->err = "invalid host";
! 839: return NGX_ERROR;
! 840: }
! 841:
! 842: u->uri.len = last - uri;
! 843: u->uri.data = uri;
! 844:
! 845: last = uri;
! 846: }
! 847:
! 848: if (*port == ':') {
! 849: port++;
! 850:
! 851: len = last - port;
! 852:
! 853: n = ngx_atoi(port, len);
! 854:
! 855: if (n < 1 || n > 65535) {
! 856: u->err = "invalid port";
! 857: return NGX_ERROR;
! 858: }
! 859:
! 860: u->port = (in_port_t) n;
! 861: sin6->sin6_port = htons((in_port_t) n);
! 862:
! 863: u->port_text.len = len;
! 864: u->port_text.data = port;
! 865:
! 866: } else {
! 867: u->no_port = 1;
! 868: u->port = u->default_port;
! 869: sin6->sin6_port = htons(u->default_port);
! 870: }
! 871: }
! 872:
! 873: len = p - host;
! 874:
! 875: if (len == 0) {
! 876: u->err = "no host";
! 877: return NGX_ERROR;
! 878: }
! 879:
! 880: u->host.len = len + 2;
! 881: u->host.data = host - 1;
! 882:
! 883: if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
! 884: u->err = "invalid IPv6 address";
! 885: return NGX_ERROR;
! 886: }
! 887:
! 888: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
! 889: u->wildcard = 1;
! 890: }
! 891:
! 892: u->family = AF_INET6;
! 893: u->naddrs = 1;
! 894:
! 895: u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
! 896: if (u->addrs == NULL) {
! 897: return NGX_ERROR;
! 898: }
! 899:
! 900: sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
! 901: if (sin6 == NULL) {
! 902: return NGX_ERROR;
! 903: }
! 904:
! 905: ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6));
! 906:
! 907: u->addrs[0].sockaddr = (struct sockaddr *) sin6;
! 908: u->addrs[0].socklen = sizeof(struct sockaddr_in6);
! 909:
! 910: p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
! 911: if (p == NULL) {
! 912: return NGX_ERROR;
! 913: }
! 914:
! 915: u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
! 916: &u->host, u->port) - p;
! 917: u->addrs[0].name.data = p;
! 918:
! 919: return NGX_OK;
! 920:
! 921: #else
! 922:
! 923: u->err = "the INET6 sockets are not supported on this platform";
! 924:
! 925: return NGX_ERROR;
! 926:
! 927: #endif
! 928: }
! 929:
! 930:
! 931: #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
! 932:
! 933: ngx_int_t
! 934: ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
! 935: {
! 936: u_char *p, *host;
! 937: size_t len;
! 938: in_port_t port;
! 939: ngx_uint_t i;
! 940: struct addrinfo hints, *res, *rp;
! 941: struct sockaddr_in *sin;
! 942: struct sockaddr_in6 *sin6;
! 943:
! 944: port = htons(u->port);
! 945:
! 946: host = ngx_alloc(u->host.len + 1, pool->log);
! 947: if (host == NULL) {
! 948: return NGX_ERROR;
! 949: }
! 950:
! 951: (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
! 952:
! 953: ngx_memzero(&hints, sizeof(struct addrinfo));
! 954: hints.ai_family = AF_UNSPEC;
! 955: hints.ai_socktype = SOCK_STREAM;
! 956:
! 957: if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
! 958: u->err = "host not found";
! 959: ngx_free(host);
! 960: return NGX_ERROR;
! 961: }
! 962:
! 963: ngx_free(host);
! 964:
! 965: for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) {
! 966:
! 967: switch (rp->ai_family) {
! 968:
! 969: case AF_INET:
! 970: case AF_INET6:
! 971: break;
! 972:
! 973: default:
! 974: continue;
! 975: }
! 976:
! 977: i++;
! 978: }
! 979:
! 980: if (i == 0) {
! 981: u->err = "host not found";
! 982: goto failed;
! 983: }
! 984:
! 985: /* MP: ngx_shared_palloc() */
! 986:
! 987: u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
! 988: if (u->addrs == NULL) {
! 989: goto failed;
! 990: }
! 991:
! 992: u->naddrs = i;
! 993:
! 994: i = 0;
! 995:
! 996: /* AF_INET addresses first */
! 997:
! 998: for (rp = res; rp != NULL; rp = rp->ai_next) {
! 999:
! 1000: if (rp->ai_family != AF_INET) {
! 1001: continue;
! 1002: }
! 1003:
! 1004: sin = ngx_pcalloc(pool, rp->ai_addrlen);
! 1005: if (sin == NULL) {
! 1006: goto failed;
! 1007: }
! 1008:
! 1009: ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
! 1010:
! 1011: sin->sin_port = port;
! 1012:
! 1013: u->addrs[i].sockaddr = (struct sockaddr *) sin;
! 1014: u->addrs[i].socklen = rp->ai_addrlen;
! 1015:
! 1016: len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
! 1017:
! 1018: p = ngx_pnalloc(pool, len);
! 1019: if (p == NULL) {
! 1020: goto failed;
! 1021: }
! 1022:
! 1023: len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
! 1024:
! 1025: u->addrs[i].name.len = len;
! 1026: u->addrs[i].name.data = p;
! 1027:
! 1028: i++;
! 1029: }
! 1030:
! 1031: for (rp = res; rp != NULL; rp = rp->ai_next) {
! 1032:
! 1033: if (rp->ai_family != AF_INET6) {
! 1034: continue;
! 1035: }
! 1036:
! 1037: sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
! 1038: if (sin6 == NULL) {
! 1039: goto failed;
! 1040: }
! 1041:
! 1042: ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
! 1043:
! 1044: sin6->sin6_port = port;
! 1045:
! 1046: u->addrs[i].sockaddr = (struct sockaddr *) sin6;
! 1047: u->addrs[i].socklen = rp->ai_addrlen;
! 1048:
! 1049: len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
! 1050:
! 1051: p = ngx_pnalloc(pool, len);
! 1052: if (p == NULL) {
! 1053: goto failed;
! 1054: }
! 1055:
! 1056: len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
! 1057:
! 1058: u->addrs[i].name.len = len;
! 1059: u->addrs[i].name.data = p;
! 1060:
! 1061: i++;
! 1062: }
! 1063:
! 1064: freeaddrinfo(res);
! 1065: return NGX_OK;
! 1066:
! 1067: failed:
! 1068:
! 1069: freeaddrinfo(res);
! 1070: return NGX_ERROR;
! 1071: }
! 1072:
! 1073: #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
! 1074:
! 1075: ngx_int_t
! 1076: ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
! 1077: {
! 1078: u_char *p, *host;
! 1079: size_t len;
! 1080: in_port_t port;
! 1081: in_addr_t in_addr;
! 1082: ngx_uint_t i;
! 1083: struct hostent *h;
! 1084: struct sockaddr_in *sin;
! 1085:
! 1086: /* AF_INET only */
! 1087:
! 1088: port = htons(u->port);
! 1089:
! 1090: in_addr = ngx_inet_addr(u->host.data, u->host.len);
! 1091:
! 1092: if (in_addr == INADDR_NONE) {
! 1093: host = ngx_alloc(u->host.len + 1, pool->log);
! 1094: if (host == NULL) {
! 1095: return NGX_ERROR;
! 1096: }
! 1097:
! 1098: (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
! 1099:
! 1100: h = gethostbyname((char *) host);
! 1101:
! 1102: ngx_free(host);
! 1103:
! 1104: if (h == NULL || h->h_addr_list[0] == NULL) {
! 1105: u->err = "host not found";
! 1106: return NGX_ERROR;
! 1107: }
! 1108:
! 1109: for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
! 1110:
! 1111: /* MP: ngx_shared_palloc() */
! 1112:
! 1113: u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
! 1114: if (u->addrs == NULL) {
! 1115: return NGX_ERROR;
! 1116: }
! 1117:
! 1118: u->naddrs = i;
! 1119:
! 1120: for (i = 0; i < u->naddrs; i++) {
! 1121:
! 1122: sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
! 1123: if (sin == NULL) {
! 1124: return NGX_ERROR;
! 1125: }
! 1126:
! 1127: sin->sin_family = AF_INET;
! 1128: sin->sin_port = port;
! 1129: sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
! 1130:
! 1131: u->addrs[i].sockaddr = (struct sockaddr *) sin;
! 1132: u->addrs[i].socklen = sizeof(struct sockaddr_in);
! 1133:
! 1134: len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
! 1135:
! 1136: p = ngx_pnalloc(pool, len);
! 1137: if (p == NULL) {
! 1138: return NGX_ERROR;
! 1139: }
! 1140:
! 1141: len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
! 1142:
! 1143: u->addrs[i].name.len = len;
! 1144: u->addrs[i].name.data = p;
! 1145: }
! 1146:
! 1147: } else {
! 1148:
! 1149: /* MP: ngx_shared_palloc() */
! 1150:
! 1151: u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
! 1152: if (u->addrs == NULL) {
! 1153: return NGX_ERROR;
! 1154: }
! 1155:
! 1156: sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
! 1157: if (sin == NULL) {
! 1158: return NGX_ERROR;
! 1159: }
! 1160:
! 1161: u->naddrs = 1;
! 1162:
! 1163: sin->sin_family = AF_INET;
! 1164: sin->sin_port = port;
! 1165: sin->sin_addr.s_addr = in_addr;
! 1166:
! 1167: u->addrs[0].sockaddr = (struct sockaddr *) sin;
! 1168: u->addrs[0].socklen = sizeof(struct sockaddr_in);
! 1169:
! 1170: p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
! 1171: if (p == NULL) {
! 1172: return NGX_ERROR;
! 1173: }
! 1174:
! 1175: u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
! 1176: &u->host, ntohs(port)) - p;
! 1177: u->addrs[0].name.data = p;
! 1178: }
! 1179:
! 1180: return NGX_OK;
! 1181: }
! 1182:
! 1183: #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>