1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_main.h> 8 9 10 #if (NXT_INET6) 11 static u_char *nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end); 12 #endif 13 14 static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr); 15 static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr); 16 static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr); 17 18 static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs); 19 static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs); 20 static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs); 21 22 23 nxt_sockaddr_t * 24 nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls) 25 { 26 size_t size; 27 uint8_t hint; 28 nxt_sockaddr_t *sa; 29 30 hint = NXT_EVENT_ENGINE_NO_MEM_HINT; 31 size = offsetof(nxt_sockaddr_t, u) + ls->socklen + ls->address_length; 32 33 sa = nxt_event_engine_mem_alloc(engine, &hint, size); 34 35 if (nxt_fast_path(sa != NULL)) { 36 /* Zero only beginning of structure up to sockaddr_un.sun_path[1]. */ 37 nxt_memzero(sa, offsetof(nxt_sockaddr_t, u.sockaddr.sa_data[1])); 38 39 sa->cache_hint = hint; 40 sa->socklen = ls->socklen; 41 sa->length = ls->address_length; 42 43 sa->type = ls->sockaddr->type; 44 /* 45 * Set address family for unspecified Unix domain socket, 46 * because these sockaddr's are not updated by old BSD systems, 47 * see comment in nxt_conn_io_accept(). 48 */ 49 sa->u.sockaddr.sa_family = ls->sockaddr->u.sockaddr.sa_family; 50 } 51 52 return sa; 53 } 54 55 56 void 57 nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c) 58 { 59 nxt_sockaddr_t *sa; 60 61 sa = c->remote; 62 63 nxt_event_engine_mem_free(engine, sa->cache_hint, sa, 0); 64 } 65 66 67 nxt_sockaddr_t * 68 nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length) 69 { 70 size_t size; 71 nxt_sockaddr_t *sa; 72 73 size = offsetof(nxt_sockaddr_t, u) + socklen + address_length; 74 75 /* 76 * The current struct sockaddr's define 32-bit fields at maximum 77 * and may define 64-bit AF_INET6 fields in the future. Alignment 78 * of memory allocated by nxt_mp_zalloc() is enough for these fields. 79 * If 128-bit alignment will be required then nxt_mem_malloc() and 80 * nxt_memzero() should be used instead. 81 */ 82 83 sa = nxt_mp_zalloc(mp, size); 84 85 if (nxt_fast_path(sa != NULL)) { 86 sa->socklen = socklen; 87 sa->length = address_length; 88 } 89 90 return sa; 91 } 92 93 94 nxt_sockaddr_t * 95 nxt_sockaddr_create(nxt_mp_t *mp, struct sockaddr *sockaddr, socklen_t length, 96 size_t address_length) 97 { 98 size_t size, copy; 99 nxt_sockaddr_t *sa; 100 101 size = length; 102 copy = length; 103 104 #if (NXT_HAVE_UNIX_DOMAIN) 105 106 /* 107 * Unspecified Unix domain sockaddr_un form and length are very 108 * platform depended (see comment in nxt_socket.h). Here they are 109 * normalized to the sockaddr_un with single zero byte sun_path[]. 110 */ 111 112 if (size <= offsetof(struct sockaddr_un, sun_path)) { 113 /* 114 * Small socket length means a short unspecified Unix domain 115 * socket address: 116 * 117 * getsockname() and getpeername() on OpenBSD prior to 5.3 118 * return zero length and does not update a passed sockaddr 119 * buffer at all. 120 * 121 * Linux returns length equal to 2, i.e. sockaddr_un without 122 * sun_path[], unix(7): 123 * 124 * unnamed: A stream socket that has not been bound 125 * to a pathname using bind(2) has no name. Likewise, 126 * the two sockets created by socketpair(2) are unnamed. 127 * When the address of an unnamed socket is returned by 128 * getsockname(2), getpeername(2), and accept(2), its 129 * length is sizeof(sa_family_t), and sun_path should 130 * not be inspected. 131 */ 132 size = offsetof(struct sockaddr_un, sun_path) + 1; 133 134 #if !(NXT_LINUX) 135 136 } else if (sockaddr->sa_family == AF_UNIX && sockaddr->sa_data[0] == '\0') { 137 /* 138 * Omit nonsignificant zeros of the unspecified Unix domain socket 139 * address. This test is disabled for Linux since Linux abstract 140 * socket address also starts with zero. However Linux unspecified 141 * Unix domain socket address is short and is handled above. 142 */ 143 size = offsetof(struct sockaddr_un, sun_path) + 1; 144 copy = size; 145 146 #endif 147 } 148 149 #endif /* NXT_HAVE_UNIX_DOMAIN */ 150 151 sa = nxt_sockaddr_alloc(mp, size, address_length); 152 153 if (nxt_fast_path(sa != NULL)) { 154 nxt_memcpy(&sa->u.sockaddr, sockaddr, copy); 155 156 #if (NXT_HAVE_UNIX_DOMAIN && NXT_OPENBSD) 157 158 if (length == 0) { 159 sa->u.sockaddr.sa_family = AF_UNIX; 160 } 161 162 #endif 163 } 164 165 return sa; 166 } 167 168 169 nxt_sockaddr_t * 170 nxt_sockaddr_copy(nxt_mp_t *mp, nxt_sockaddr_t *src) 171 { 172 size_t length; 173 nxt_sockaddr_t *dst; 174 175 length = offsetof(nxt_sockaddr_t, u) + src->socklen; 176 177 dst = nxt_mp_alloc(mp, length); 178 179 if (nxt_fast_path(dst != NULL)) { 180 nxt_memcpy(dst, src, length); 181 } 182 183 return dst; 184 } 185 186 187 nxt_sockaddr_t * 188 nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_t s) 189 { 190 int ret; 191 size_t length; 192 socklen_t socklen; 193 nxt_sockaddr_buf_t sockaddr; 194 195 socklen = NXT_SOCKADDR_LEN; 196 197 ret = getsockname(s, &sockaddr.buf, &socklen); 198 199 if (nxt_fast_path(ret == 0)) { 200 201 switch (sockaddr.buf.sa_family) { 202 #if (NXT_INET6) 203 case AF_INET6: 204 length = NXT_INET6_ADDR_STR_LEN; 205 break; 206 #endif 207 208 #if (NXT_HAVE_UNIX_DOMAIN) 209 case AF_UNIX: 210 length = nxt_length("unix:") + socklen; 211 break; 212 #endif 213 214 case AF_INET: 215 length = NXT_INET_ADDR_STR_LEN; 216 break; 217 218 default: 219 length = 0; 220 break; 221 } 222 223 return nxt_sockaddr_create(mp, &sockaddr.buf, socklen, length); 224 } 225 226 nxt_log(task, NXT_LOG_ERR, "getsockname(%d) failed %E", s, nxt_errno); 227 228 return NULL; 229 } 230 231 232 void 233 nxt_sockaddr_text(nxt_sockaddr_t *sa) 234 { 235 size_t offset; 236 u_char *p, *start, *end, *octet; 237 uint32_t port; 238 239 offset = offsetof(nxt_sockaddr_t, u) + sa->socklen; 240 sa->start = offset; 241 sa->port_start = offset; 242 243 start = nxt_pointer_to(sa, offset); 244 end = start + sa->length; 245 246 switch (sa->u.sockaddr.sa_family) { 247 248 case AF_INET: 249 sa->address_start = offset; 250 251 octet = (u_char *) &sa->u.sockaddr_in.sin_addr; 252 253 p = nxt_sprintf(start, end, "%ud.%ud.%ud.%ud", 254 octet[0], octet[1], octet[2], octet[3]); 255 256 sa->address_length = p - start; 257 sa->port_start += sa->address_length + 1; 258 259 port = sa->u.sockaddr_in.sin_port; 260 261 break; 262 263 #if (NXT_INET6) 264 265 case AF_INET6: 266 sa->address_start = offset + 1; 267 268 p = start; 269 *p++ = '['; 270 271 p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end); 272 273 sa->address_length = p - (start + 1); 274 sa->port_start += sa->address_length + 3; 275 276 *p++ = ']'; 277 278 port = sa->u.sockaddr_in6.sin6_port; 279 280 break; 281 282 #endif 283 284 #if (NXT_HAVE_UNIX_DOMAIN) 285 286 case AF_UNIX: 287 sa->address_start = offset; 288 289 p = (u_char *) sa->u.sockaddr_un.sun_path; 290 291 #if (NXT_LINUX) 292 293 if (p[0] == '\0') { 294 size_t length; 295 296 /* Linux abstract socket address has no trailing zero. */ 297 length = sa->socklen - offsetof(struct sockaddr_un, sun_path); 298 299 p = nxt_sprintf(start, end, "unix:@%*s", length - 1, p + 1); 300 301 } else { 302 p = nxt_sprintf(start, end, "unix:%s", p); 303 } 304 305 #else /* !(NXT_LINUX) */ 306 307 p = nxt_sprintf(start, end, "unix:%s", p); 308 309 #endif 310 311 sa->address_length = p - start; 312 sa->port_start += sa->address_length; 313 sa->length = p - start; 314 315 return; 316 317 #endif /* NXT_HAVE_UNIX_DOMAIN */ 318 319 default: 320 return; 321 } 322 323 p = nxt_sprintf(p, end, ":%d", ntohs(port)); 324 325 sa->length = p - start; 326 } 327 328 329 uint32_t 330 nxt_sockaddr_port_number(nxt_sockaddr_t *sa) 331 { 332 uint32_t port; 333 334 switch (sa->u.sockaddr.sa_family) { 335 336 #if (NXT_INET6) 337 338 case AF_INET6: 339 port = sa->u.sockaddr_in6.sin6_port; 340 break; 341 342 #endif 343 344 #if (NXT_HAVE_UNIX_DOMAIN) 345 346 case AF_UNIX: 347 return 0; 348 349 #endif 350 351 default: 352 port = sa->u.sockaddr_in.sin_port; 353 break; 354 } 355 356 return ntohs((uint16_t) port); 357 } 358 359 360 nxt_bool_t 361 nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) 362 { 363 if (sa1->socklen != sa2->socklen) { 364 return 0; 365 } 366 367 if (sa1->type != sa2->type) { 368 return 0; 369 } 370 371 if (sa1->u.sockaddr.sa_family != sa2->u.sockaddr.sa_family) { 372 return 0; 373 } 374 375 /* 376 * sockaddr struct's cannot be compared in whole since kernel 377 * may fill some fields in inherited sockaddr struct's. 378 */ 379 380 switch (sa1->u.sockaddr.sa_family) { 381 382 #if (NXT_INET6) 383 384 case AF_INET6: 385 if (sa1->u.sockaddr_in6.sin6_port != sa2->u.sockaddr_in6.sin6_port) { 386 return 0; 387 } 388 389 if (nxt_memcmp(&sa1->u.sockaddr_in6.sin6_addr, 390 &sa2->u.sockaddr_in6.sin6_addr, 16) 391 != 0) 392 { 393 return 0; 394 } 395 396 return 1; 397 398 #endif 399 400 #if (NXT_HAVE_UNIX_DOMAIN) 401 402 case AF_UNIX: 403 { 404 size_t length; 405 406 length = sa1->socklen - offsetof(struct sockaddr_un, sun_path); 407 408 if (nxt_memcmp(&sa1->u.sockaddr_un.sun_path, 409 &sa2->u.sockaddr_un.sun_path, length) 410 != 0) 411 { 412 return 0; 413 } 414 415 return 1; 416 } 417 418 #endif 419 420 default: /* AF_INET */ 421 if (sa1->u.sockaddr_in.sin_port != sa2->u.sockaddr_in.sin_port) { 422 return 0; 423 } 424 425 if (sa1->u.sockaddr_in.sin_addr.s_addr 426 != sa2->u.sockaddr_in.sin_addr.s_addr) 427 { 428 return 0; 429 } 430 431 return 1; 432 } 433 } 434 435 436 size_t 437 nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, u_char *end, nxt_bool_t port) 438 { 439 u_char *p; 440 441 switch (sa->u.sockaddr.sa_family) { 442 443 case AF_INET: 444 p = (u_char *) &sa->u.sockaddr_in.sin_addr; 445 446 if (port) { 447 p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud:%d", 448 p[0], p[1], p[2], p[3], 449 ntohs(sa->u.sockaddr_in.sin_port)); 450 } else { 451 p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud", 452 p[0], p[1], p[2], p[3]); 453 } 454 455 return p - buf; 456 457 #if (NXT_INET6) 458 459 case AF_INET6: 460 p = buf; 461 462 if (port) { 463 *p++ = '['; 464 } 465 466 p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end); 467 468 if (port) { 469 p = nxt_sprintf(p, end, "]:%d", 470 ntohs(sa->u.sockaddr_in6.sin6_port)); 471 } 472 473 return p - buf; 474 #endif 475 476 #if (NXT_HAVE_UNIX_DOMAIN) 477 478 case AF_UNIX: 479 480 #if (NXT_LINUX) 481 482 p = (u_char *) sa->u.sockaddr_un.sun_path; 483 484 if (p[0] == '\0') { 485 size_t length; 486 487 /* Linux abstract socket address has no trailing zero. */ 488 489 length = sa->socklen - offsetof(struct sockaddr_un, sun_path) - 1; 490 p = nxt_sprintf(buf, end, "unix:\\0%*s", length, p + 1); 491 492 } else { 493 p = nxt_sprintf(buf, end, "unix:%s", p); 494 } 495 496 #else /* !(NXT_LINUX) */ 497 498 p = nxt_sprintf(buf, end, "unix:%s", sa->u.sockaddr_un.sun_path); 499 500 #endif 501 502 return p - buf; 503 504 #endif /* NXT_HAVE_UNIX_DOMAIN */ 505 506 default: 507 return 0; 508 } 509 } 510 511 512 #if (NXT_INET6) 513 514 static u_char * 515 nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end) 516 { 517 u_char *p; 518 size_t zero_groups, last_zero_groups, ipv6_bytes; 519 nxt_uint_t i, zero_start, last_zero_start; 520 521 const size_t max_inet6_length = 522 nxt_length("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); 523 524 if (buf + max_inet6_length > end) { 525 return buf; 526 } 527 528 zero_start = 16; 529 zero_groups = 0; 530 last_zero_start = 16; 531 last_zero_groups = 0; 532 533 for (i = 0; i < 16; i += 2) { 534 535 if (addr[i] == 0 && addr[i + 1] == 0) { 536 537 if (last_zero_groups == 0) { 538 last_zero_start = i; 539 } 540 541 last_zero_groups++; 542 543 } else { 544 if (zero_groups < last_zero_groups) { 545 zero_groups = last_zero_groups; 546 zero_start = last_zero_start; 547 } 548 549 last_zero_groups = 0; 550 } 551 } 552 553 if (zero_groups < last_zero_groups) { 554 zero_groups = last_zero_groups; 555 zero_start = last_zero_start; 556 } 557 558 ipv6_bytes = 16; 559 p = buf; 560 561 if (zero_start == 0) { 562 563 /* IPv4-mapped address */ 564 if ((zero_groups == 5 && addr[10] == 0xFF && addr[11] == 0xFF) 565 /* IPv4-compatible address */ 566 || (zero_groups == 6) 567 /* not IPv6 loopback address */ 568 || (zero_groups == 7 && addr[14] != 0 && addr[15] != 1)) 569 { 570 ipv6_bytes = 12; 571 } 572 573 *p++ = ':'; 574 } 575 576 for (i = 0; i < ipv6_bytes; i += 2) { 577 578 if (i == zero_start) { 579 /* Output maximum number of consecutive zero groups as "::". */ 580 i += (zero_groups - 1) * 2; 581 *p++ = ':'; 582 continue; 583 } 584 585 p = nxt_sprintf(p, end, "%uxd", (addr[i] << 8) + addr[i + 1]); 586 587 if (i < 14) { 588 *p++ = ':'; 589 } 590 } 591 592 if (ipv6_bytes == 12) { 593 p = nxt_sprintf(p, end, "%ud.%ud.%ud.%ud", 594 addr[12], addr[13], addr[14], addr[15]); 595 } 596 597 return p; 598 } 599 600 #endif 601 602 603 nxt_sockaddr_t * 604 nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr) 605 { 606 nxt_sockaddr_t *sa; 607 608 sa = nxt_sockaddr_parse_optport(mp, addr); 609 610 if (sa != NULL 611 && sa->u.sockaddr.sa_family != AF_UNIX 612 && nxt_sockaddr_port_number(sa) == 0) 613 { 614 nxt_thread_log_error(NXT_LOG_ERR, 615 "The address \"%V\" must specify a port.", addr); 616 return NULL; 617 } 618 619 return sa; 620 } 621 622 623 nxt_sockaddr_t * 624 nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr) 625 { 626 nxt_sockaddr_t *sa; 627 628 if (addr->length == 0) { 629 nxt_thread_log_error(NXT_LOG_ERR, "socket address cannot be empty"); 630 return NULL; 631 } 632 633 if (addr->length > 6 && nxt_memcmp(addr->start, "unix:", 5) == 0) { 634 sa = nxt_sockaddr_unix_parse(mp, addr); 635 636 } else if (addr->start[0] == '[' || nxt_inet6_probe(addr)) { 637 sa = nxt_sockaddr_inet6_parse(mp, addr); 638 639 } else { 640 sa = nxt_sockaddr_inet_parse(mp, addr); 641 } 642 643 if (nxt_fast_path(sa != NULL)) { 644 nxt_sockaddr_text(sa); 645 } 646 647 return sa; 648 } 649 650 651 static nxt_sockaddr_t * 652 nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) 653 { 654 #if (NXT_HAVE_UNIX_DOMAIN) 655 size_t length, socklen; 656 u_char *path; 657 nxt_sockaddr_t *sa; 658 659 /* 660 * Actual sockaddr_un length can be lesser or even larger than defined 661 * struct sockaddr_un length (see comment in nxt_socket.h). So 662 * limit maximum Unix domain socket address length by defined sun_path[] 663 * length because some OSes accept addresses twice larger than defined 664 * struct sockaddr_un. Also reserve space for a trailing zero to avoid 665 * ambiguity, since many OSes accept Unix domain socket addresses 666 * without a trailing zero. 667 */ 668 const size_t max_len = sizeof(struct sockaddr_un) 669 - offsetof(struct sockaddr_un, sun_path) - 1; 670 671 /* Cutting "unix:". */ 672 length = addr->length - 5; 673 path = addr->start + 5; 674 675 if (length > max_len) { 676 nxt_thread_log_error(NXT_LOG_ERR, 677 "unix domain socket \"%V\" name is too long", 678 addr); 679 return NULL; 680 } 681 682 socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; 683 684 #if (NXT_LINUX) 685 686 /* 687 * Linux unix(7): 688 * 689 * abstract: an abstract socket address is distinguished by the fact 690 * that sun_path[0] is a null byte ('\0'). The socket's address in 691 * this namespace is given by the additional bytes in sun_path that 692 * are covered by the specified length of the address structure. 693 * (Null bytes in the name have no special significance.) 694 */ 695 if (path[0] == '@') { 696 path[0] = '\0'; 697 socklen--; 698 } 699 700 #endif 701 702 sa = nxt_sockaddr_alloc(mp, socklen, addr->length); 703 704 if (nxt_fast_path(sa != NULL)) { 705 sa->u.sockaddr_un.sun_family = AF_UNIX; 706 nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length); 707 } 708 709 return sa; 710 711 #else /* !(NXT_HAVE_UNIX_DOMAIN) */ 712 713 nxt_thread_log_error(NXT_LOG_ERR, 714 "unix domain socket \"%V\" is not supported", addr); 715 716 return NULL; 717 718 #endif 719 } 720 721 722 static nxt_sockaddr_t * 723 nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr) 724 { 725 #if (NXT_INET6) 726 u_char *p, *start, *end; 727 size_t length; 728 nxt_int_t ret, port; 729 nxt_sockaddr_t *sa; 730 731 if (addr->start[0] == '[') { 732 length = addr->length - 1; 733 start = addr->start + 1; 734 735 end = nxt_memchr(start, ']', length); 736 if (nxt_slow_path(end == NULL)) { 737 return NULL; 738 } 739 740 p = end + 1; 741 742 } else { 743 length = addr->length; 744 start = addr->start; 745 end = addr->start + addr->length; 746 p = NULL; 747 } 748 749 port = 0; 750 751 if (p != NULL) { 752 length = (start + length) - p; 753 754 if (length < 2 || *p != ':') { 755 nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", 756 addr); 757 return NULL; 758 } 759 760 port = nxt_int_parse(p + 1, length - 1); 761 762 if (port < 1 || port > 65535) { 763 nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr); 764 return NULL; 765 } 766 } 767 768 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), 769 NXT_INET6_ADDR_STR_LEN); 770 if (nxt_slow_path(sa == NULL)) { 771 return NULL; 772 } 773 774 ret = nxt_inet6_addr(&sa->u.sockaddr_in6.sin6_addr, start, end - start); 775 if (nxt_slow_path(ret != NXT_OK)) { 776 nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", 777 addr); 778 return NULL; 779 } 780 781 sa->u.sockaddr_in6.sin6_family = AF_INET6; 782 sa->u.sockaddr_in6.sin6_port = htons((in_port_t) port); 783 784 return sa; 785 786 #else /* !(NXT_INET6) */ 787 788 nxt_thread_log_error(NXT_LOG_ERR, "IPv6 socket \"%V\" is not supported", 789 addr); 790 return NULL; 791 792 #endif 793 } 794 795 796 static nxt_sockaddr_t * 797 nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) 798 { 799 u_char *p; 800 size_t length; 801 nxt_int_t port; 802 in_addr_t inaddr; 803 nxt_sockaddr_t *sa; 804 805 p = nxt_memchr(addr->start, ':', addr->length); 806 807 if (p == NULL) { 808 length = addr->length; 809 810 } else { 811 length = p - addr->start; 812 } 813 814 inaddr = INADDR_ANY; 815 816 if (length != 1 || addr->start[0] != '*') { 817 inaddr = nxt_inet_addr(addr->start, length); 818 if (nxt_slow_path(inaddr == INADDR_NONE)) { 819 nxt_thread_log_error(NXT_LOG_ERR, "invalid address \"%V\"", addr); 820 return NULL; 821 } 822 } 823 824 port = 0; 825 826 if (p != NULL) { 827 p++; 828 length = (addr->start + addr->length) - p; 829 830 port = nxt_int_parse(p, length); 831 832 if (port < 1 || port > 65535) { 833 nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr); 834 return NULL; 835 } 836 } 837 838 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), 839 NXT_INET_ADDR_STR_LEN); 840 if (nxt_slow_path(sa == NULL)) { 841 return NULL; 842 } 843 844 sa->u.sockaddr_in.sin_family = AF_INET; 845 sa->u.sockaddr_in.sin_addr.s_addr = inaddr; 846 sa->u.sockaddr_in.sin_port = htons((in_port_t) port); 847 848 return sa; 849 } 850 851 852 void 853 nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs) 854 { 855 u_char *p; 856 size_t length; 857 nxt_int_t ret; 858 nxt_work_handler_t handler; 859 860 nxt_job_set_name(&jbs->resolve.job, "job sockaddr parse"); 861 862 length = jbs->addr.length; 863 p = jbs->addr.start; 864 865 if (length > 6 && nxt_memcmp(p, "unix:", 5) == 0) { 866 ret = nxt_job_sockaddr_unix_parse(jbs); 867 868 } else if (length != 0 && *p == '[') { 869 ret = nxt_job_sockaddr_inet6_parse(jbs); 870 871 } else { 872 ret = nxt_job_sockaddr_inet_parse(jbs); 873 } 874 875 switch (ret) { 876 877 case NXT_OK: 878 handler = jbs->resolve.ready_handler; 879 break; 880 881 case NXT_ERROR: 882 handler = jbs->resolve.error_handler; 883 break; 884 885 default: /* NXT_AGAIN */ 886 return; 887 } 888 889 nxt_job_return(jbs->resolve.job.task, &jbs->resolve.job, handler); 890 } 891 892 893 static nxt_int_t 894 nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs) 895 { 896 #if (NXT_HAVE_UNIX_DOMAIN) 897 size_t length, socklen; 898 u_char *path; 899 nxt_mp_t *mp; 900 nxt_sockaddr_t *sa; 901 902 /* 903 * Actual sockaddr_un length can be lesser or even larger than defined 904 * struct sockaddr_un length (see comment in nxt_socket.h). So 905 * limit maximum Unix domain socket address length by defined sun_path[] 906 * length because some OSes accept addresses twice larger than defined 907 * struct sockaddr_un. Also reserve space for a trailing zero to avoid 908 * ambiguity, since many OSes accept Unix domain socket addresses 909 * without a trailing zero. 910 */ 911 const size_t max_len = sizeof(struct sockaddr_un) 912 - offsetof(struct sockaddr_un, sun_path) - 1; 913 914 /* cutting "unix:" */ 915 length = jbs->addr.length - 5; 916 path = jbs->addr.start + 5; 917 918 if (length > max_len) { 919 nxt_thread_log_error(jbs->resolve.log_level, 920 "unix domain socket \"%V\" name is too long", 921 &jbs->addr); 922 return NXT_ERROR; 923 } 924 925 socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; 926 927 #if (NXT_LINUX) 928 929 /* 930 * Linux unix(7): 931 * 932 * abstract: an abstract socket address is distinguished by the fact 933 * that sun_path[0] is a null byte ('\0'). The socket's address in 934 * this namespace is given by the additional bytes in sun_path that 935 * are covered by the specified length of the address structure. 936 * (Null bytes in the name have no special significance.) 937 */ 938 if (path[0] == '\0') { 939 socklen--; 940 } 941 942 #endif 943 944 mp = jbs->resolve.job.mem_pool; 945 946 jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); 947 948 if (nxt_fast_path(jbs->resolve.sockaddrs != NULL)) { 949 sa = nxt_sockaddr_alloc(mp, socklen, jbs->addr.length); 950 951 if (nxt_fast_path(sa != NULL)) { 952 jbs->resolve.count = 1; 953 jbs->resolve.sockaddrs[0] = sa; 954 955 sa->u.sockaddr_un.sun_family = AF_UNIX; 956 nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length); 957 958 return NXT_OK; 959 } 960 } 961 962 return NXT_ERROR; 963 964 #else /* !(NXT_HAVE_UNIX_DOMAIN) */ 965 966 nxt_thread_log_error(jbs->resolve.log_level, 967 "unix domain socket \"%V\" is not supported", 968 &jbs->addr); 969 return NXT_ERROR; 970 971 #endif 972 } 973 974 975 static nxt_int_t 976 nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs) 977 { 978 #if (NXT_INET6) 979 u_char *p, *addr, *addr_end; 980 size_t length; 981 nxt_mp_t *mp; 982 nxt_int_t port; 983 nxt_sockaddr_t *sa; 984 struct in6_addr *in6_addr; 985 986 length = jbs->addr.length - 1; 987 addr = jbs->addr.start + 1; 988 989 addr_end = nxt_memchr(addr, ']', length); 990 991 if (addr_end == NULL) { 992 goto invalid_address; 993 } 994 995 mp = jbs->resolve.job.mem_pool; 996 997 jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); 998 999 if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) { 1000 return NXT_ERROR; 1001 } 1002 1003 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), 1004 NXT_INET6_ADDR_STR_LEN); 1005 1006 if (nxt_slow_path(sa == NULL)) { 1007 return NXT_ERROR; 1008 } 1009 1010 jbs->resolve.count = 1; 1011 jbs->resolve.sockaddrs[0] = sa; 1012 1013 in6_addr = &sa->u.sockaddr_in6.sin6_addr; 1014 1015 if (nxt_inet6_addr(in6_addr, addr, addr_end - addr) != NXT_OK) { 1016 goto invalid_address; 1017 } 1018 1019 p = addr_end + 1; 1020 length = (addr + length) - p; 1021 1022 if (length == 0) { 1023 jbs->no_port = 1; 1024 port = jbs->resolve.port; 1025 goto found; 1026 } 1027 1028 if (*p == ':') { 1029 port = nxt_int_parse(p + 1, length - 1); 1030 1031 if (port >= 1 && port <= 65535) { 1032 port = htons((in_port_t) port); 1033 goto found; 1034 } 1035 } 1036 1037 nxt_thread_log_error(jbs->resolve.log_level, 1038 "invalid port in \"%V\"", &jbs->addr); 1039 1040 return NXT_ERROR; 1041 1042 found: 1043 1044 sa->u.sockaddr_in6.sin6_family = AF_INET6; 1045 sa->u.sockaddr_in6.sin6_port = (in_port_t) port; 1046 1047 if (IN6_IS_ADDR_UNSPECIFIED(in6_addr)) { 1048 jbs->wildcard = 1; 1049 } 1050 1051 return NXT_OK; 1052 1053 invalid_address: 1054 1055 nxt_thread_log_error(jbs->resolve.log_level, 1056 "invalid IPv6 address in \"%V\"", &jbs->addr); 1057 return NXT_ERROR; 1058 1059 #else 1060 1061 nxt_thread_log_error(jbs->resolve.log_level, 1062 "IPv6 socket \"%V\" is not supported", &jbs->addr); 1063 return NXT_ERROR; 1064 1065 #endif 1066 } 1067 1068 1069 static nxt_int_t 1070 nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs) 1071 { 1072 u_char *p, *host; 1073 size_t length; 1074 nxt_mp_t *mp; 1075 nxt_int_t port; 1076 in_addr_t addr; 1077 nxt_sockaddr_t *sa; 1078 1079 addr = INADDR_ANY; 1080 1081 length = jbs->addr.length; 1082 host = jbs->addr.start; 1083 1084 p = nxt_memchr(host, ':', length); 1085 1086 if (p == NULL) { 1087 1088 /* single value port, address, or host name */ 1089 1090 port = nxt_int_parse(host, length); 1091 1092 if (port > 0) { 1093 if (port > 65535) { 1094 goto invalid_port; 1095 } 1096 1097 /* "*:XX" */ 1098 port = htons((in_port_t) port); 1099 jbs->resolve.port = (in_port_t) port; 1100 1101 } else { 1102 jbs->no_port = 1; 1103 1104 addr = nxt_inet_addr(host, length); 1105 1106 if (addr == INADDR_NONE) { 1107 jbs->resolve.name.length = length; 1108 jbs->resolve.name.start = host; 1109 1110 nxt_job_resolve(&jbs->resolve); 1111 return NXT_AGAIN; 1112 } 1113 1114 /* "x.x.x.x" */ 1115 port = jbs->resolve.port; 1116 } 1117 1118 } else { 1119 1120 /* x.x.x.x:XX or host:XX */ 1121 1122 p++; 1123 length = (host + length) - p; 1124 port = nxt_int_parse(p, length); 1125 1126 if (port < 1 || port > 65535) { 1127 goto invalid_port; 1128 } 1129 1130 port = htons((in_port_t) port); 1131 1132 length = (p - 1) - host; 1133 1134 if (length != 1 || host[0] != '*') { 1135 addr = nxt_inet_addr(host, length); 1136 1137 if (addr == INADDR_NONE) { 1138 jbs->resolve.name.length = length; 1139 jbs->resolve.name.start = host; 1140 jbs->resolve.port = (in_port_t) port; 1141 1142 nxt_job_resolve(&jbs->resolve); 1143 return NXT_AGAIN; 1144 } 1145 1146 /* "x.x.x.x:XX" */ 1147 } 1148 } 1149 1150 mp = jbs->resolve.job.mem_pool; 1151 1152 jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); 1153 if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) { 1154 return NXT_ERROR; 1155 } 1156 1157 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), 1158 NXT_INET_ADDR_STR_LEN); 1159 1160 if (nxt_fast_path(sa != NULL)) { 1161 jbs->resolve.count = 1; 1162 jbs->resolve.sockaddrs[0] = sa; 1163 1164 jbs->wildcard = (addr == INADDR_ANY); 1165 1166 sa->u.sockaddr_in.sin_family = AF_INET; 1167 sa->u.sockaddr_in.sin_port = (in_port_t) port; 1168 sa->u.sockaddr_in.sin_addr.s_addr = addr; 1169 1170 return NXT_OK; 1171 } 1172 1173 return NXT_ERROR; 1174 1175 invalid_port: 1176 1177 nxt_thread_log_error(jbs->resolve.log_level, 1178 "invalid port in \"%V\"", &jbs->addr); 1179 1180 return NXT_ERROR; 1181 } 1182 1183 1184 in_addr_t 1185 nxt_inet_addr(u_char *buf, size_t length) 1186 { 1187 u_char c, *end; 1188 in_addr_t addr; 1189 nxt_uint_t digit, octet, dots; 1190 1191 if (nxt_slow_path(*(buf + length - 1) == '.')) { 1192 return INADDR_NONE; 1193 } 1194 1195 addr = 0; 1196 octet = 0; 1197 dots = 0; 1198 1199 end = buf + length; 1200 1201 while (buf < end) { 1202 1203 c = *buf++; 1204 1205 digit = c - '0'; 1206 /* values below '0' become large unsigned integers */ 1207 1208 if (digit < 10) { 1209 octet = octet * 10 + digit; 1210 continue; 1211 } 1212 1213 if (c == '.' && octet < 256) { 1214 addr = (addr << 8) + octet; 1215 octet = 0; 1216 dots++; 1217 continue; 1218 } 1219 1220 return INADDR_NONE; 1221 } 1222 1223 if (dots == 3 && octet < 256) { 1224 addr = (addr << 8) + octet; 1225 return htonl(addr); 1226 } 1227 1228 return INADDR_NONE; 1229 } 1230 1231 1232 #if (NXT_INET6) 1233 1234 nxt_int_t 1235 nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf, size_t length) 1236 { 1237 u_char c, *addr, *zero_start, *ipv4, *dst, *src, *end; 1238 nxt_uint_t digit, group, nibbles, groups_left; 1239 1240 if (length == 0) { 1241 return NXT_ERROR; 1242 } 1243 1244 end = buf + length; 1245 1246 if (buf[0] == ':') { 1247 buf++; 1248 } 1249 1250 addr = in6_addr->s6_addr; 1251 zero_start = NULL; 1252 groups_left = 8; 1253 nibbles = 0; 1254 group = 0; 1255 ipv4 = NULL; 1256 1257 while (buf < end) { 1258 c = *buf++; 1259 1260 if (c == ':') { 1261 if (nibbles != 0) { 1262 ipv4 = buf; 1263 1264 *addr++ = (u_char) (group >> 8); 1265 *addr++ = (u_char) (group & 0xFF); 1266 groups_left--; 1267 1268 if (groups_left != 0) { 1269 nibbles = 0; 1270 group = 0; 1271 continue; 1272 } 1273 1274 } else { 1275 if (zero_start == NULL) { 1276 ipv4 = buf; 1277 zero_start = addr; 1278 continue; 1279 } 1280 } 1281 1282 return NXT_ERROR; 1283 } 1284 1285 if (c == '.' && nibbles != 0) { 1286 1287 if (groups_left < 2 || ipv4 == NULL) { 1288 return NXT_ERROR; 1289 } 1290 1291 group = nxt_inet_addr(ipv4, end - ipv4); 1292 if (group == INADDR_NONE) { 1293 return NXT_ERROR; 1294 } 1295 1296 group = ntohl(group); 1297 1298 *addr++ = (u_char) ((group >> 24) & 0xFF); 1299 *addr++ = (u_char) ((group >> 16) & 0xFF); 1300 groups_left--; 1301 1302 /* the low 16-bit are copied below */ 1303 break; 1304 } 1305 1306 nibbles++; 1307 1308 if (nibbles > 4) { 1309 return NXT_ERROR; 1310 } 1311 1312 group <<= 4; 1313 1314 digit = c - '0'; 1315 /* values below '0' become large unsigned integers */ 1316 1317 if (digit < 10) { 1318 group += digit; 1319 continue; 1320 } 1321 1322 c |= 0x20; 1323 digit = c - 'a'; 1324 /* values below 'a' become large unsigned integers */ 1325 1326 if (digit < 6) { 1327 group += 10 + digit; 1328 continue; 1329 } 1330 1331 return NXT_ERROR; 1332 } 1333 1334 if (nibbles == 0 && zero_start == NULL) { 1335 return NXT_ERROR; 1336 } 1337 1338 *addr++ = (u_char) (group >> 8); 1339 *addr++ = (u_char) (group & 0xFF); 1340 groups_left--; 1341 1342 if (groups_left != 0) { 1343 1344 if (zero_start != NULL) { 1345 1346 /* moving part before consecutive zero groups to the end */ 1347 1348 groups_left *= 2; 1349 src = addr - 1; 1350 dst = src + groups_left; 1351 1352 while (src >= zero_start) { 1353 *dst-- = *src--; 1354 } 1355 1356 nxt_memzero(zero_start, groups_left); 1357 1358 return NXT_OK; 1359 } 1360 1361 } else { 1362 if (zero_start == NULL) { 1363 return NXT_OK; 1364 } 1365 } 1366 1367 return NXT_ERROR; 1368 } 1369 1370 #endif 1371 1372 1373 nxt_bool_t 1374 nxt_inet6_probe(nxt_str_t *str) 1375 { 1376 u_char *colon, *end; 1377 1378 colon = nxt_memchr(str->start, ':', str->length); 1379 1380 if (colon != NULL) { 1381 end = str->start + str->length; 1382 colon = nxt_memchr(colon + 1, ':', end - (colon + 1)); 1383 } 1384 1385 return (colon != NULL); 1386 } 1387