nxt_sockaddr.c (98:4077decf847b) nxt_sockaddr.c (99:f7ff1263f690)
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)
11static u_char *nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end);
12#endif
13
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)
11static u_char *nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end);
12#endif
13
14static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr);
15static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr);
16static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr);
17
14static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs);
15static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs);
16static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs);
17
18
19nxt_sockaddr_t *
20nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length)
21{

--- 534 unchanged lines hidden (view full) ---

556 }
557
558 return p;
559}
560
561#endif
562
563
18static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs);
19static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs);
20static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs);
21
22
23nxt_sockaddr_t *
24nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length)
25{

--- 534 unchanged lines hidden (view full) ---

560 }
561
562 return p;
563}
564
565#endif
566
567
568nxt_sockaddr_t *
569nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr)
570{
571 nxt_sockaddr_t *sa;
572
573 if (addr->length > 6 && nxt_memcmp(addr->start, "unix:", 5) == 0) {
574 sa = nxt_sockaddr_unix_parse(mp, addr);
575
576 } else if (addr->length != 0 && addr->start[0] == '[') {
577 sa = nxt_sockaddr_inet6_parse(mp, addr);
578
579 } else {
580 sa = nxt_sockaddr_inet_parse(mp, addr);
581 }
582
583 if (nxt_fast_path(sa != NULL)) {
584 nxt_sockaddr_text(sa);
585 }
586
587 return sa;
588}
589
590
591static nxt_sockaddr_t *
592nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr)
593{
594#if (NXT_HAVE_UNIX_DOMAIN)
595 size_t length, socklen;
596 u_char *path;
597 nxt_sockaddr_t *sa;
598
599 /*
600 * Actual sockaddr_un length can be lesser or even larger than defined
601 * struct sockaddr_un length (see comment in unix/nxt_socket.h). So
602 * limit maximum Unix domain socket address length by defined sun_path[]
603 * length because some OSes accept addresses twice larger than defined
604 * struct sockaddr_un. Also reserve space for a trailing zero to avoid
605 * ambiguity, since many OSes accept Unix domain socket addresses
606 * without a trailing zero.
607 */
608 const size_t max_len = sizeof(struct sockaddr_un)
609 - offsetof(struct sockaddr_un, sun_path) - 1;
610
611 /* Cutting "unix:". */
612 length = addr->length - 5;
613 path = addr->start + 5;
614
615 if (length > max_len) {
616 nxt_thread_log_error(NXT_LOG_ERR,
617 "unix domain socket \"%V\" name is too long",
618 addr);
619 return NULL;
620 }
621
622 socklen = offsetof(struct sockaddr_un, sun_path) + length + 1;
623
624#if (NXT_LINUX)
625
626 /*
627 * Linux unix(7):
628 *
629 * abstract: an abstract socket address is distinguished by the fact
630 * that sun_path[0] is a null byte ('\0'). The socket's address in
631 * this namespace is given by the additional bytes in sun_path that
632 * are covered by the specified length of the address structure.
633 * (Null bytes in the name have no special significance.)
634 */
635 if (path[0] == '@') {
636 path[0] = '\0';
637 socklen--;
638 }
639
640#endif
641
642 sa = nxt_sockaddr_alloc(mp, socklen, addr->length);
643
644 if (nxt_fast_path(sa != NULL)) {
645 sa->u.sockaddr_un.sun_family = AF_UNIX;
646 nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length);
647 }
648
649 return sa;
650
651#else /* !(NXT_HAVE_UNIX_DOMAIN) */
652
653 nxt_thread_log_error(NXT_LOG_ERR,
654 "unix domain socket \"%V\" is not supported", addr);
655
656 return NULL;
657
658#endif
659}
660
661
662static nxt_sockaddr_t *
663nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr)
664{
665#if (NXT_INET6)
666 u_char *p, *start, *end;
667 size_t length;
668 nxt_int_t ret, port;
669 nxt_sockaddr_t *sa;
670
671 length = addr->length - 1;
672 start = addr->start + 1;
673
674 end = nxt_memchr(start, ']', length);
675
676 if (end != NULL) {
677 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6),
678 NXT_INET6_ADDR_STR_LEN);
679 if (nxt_slow_path(sa == NULL)) {
680 return NULL;
681 }
682
683 ret = nxt_inet6_addr(&sa->u.sockaddr_in6.sin6_addr, start, end - start);
684
685 if (nxt_fast_path(ret == NXT_OK)) {
686 p = end + 1;
687 length = (start + length) - p;
688
689 if (length > 2 && *p == ':') {
690 port = nxt_int_parse(p + 1, length - 1);
691
692 if (port > 0 && port < 65536) {
693 sa->u.sockaddr_in6.sin6_port = htons((in_port_t) port);
694 sa->u.sockaddr_in6.sin6_family = AF_INET6;
695
696 return sa;
697 }
698 }
699
700 nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr);
701
702 return NULL;
703 }
704 }
705
706 nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", addr);
707
708 return NULL;
709
710#else /* !(NXT_INET6) */
711
712 nxt_thread_log_error(NXT_LOG_ERR, "IPv6 socket \"%V\" is not supported",
713 addr);
714 return NULL;
715
716#endif
717}
718
719
720static nxt_sockaddr_t *
721nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr)
722{
723 u_char *p;
724 size_t length;
725 nxt_int_t port;
726 in_addr_t inaddr;
727 nxt_sockaddr_t *sa;
728
729 p = nxt_memchr(addr->start, ':', addr->length);
730
731 if (nxt_fast_path(p != NULL)) {
732 inaddr = INADDR_ANY;
733 length = p - addr->start;
734
735 if (length != 1 || addr->start[0] != '*') {
736 inaddr = nxt_inet_addr(addr->start, length);
737
738 if (nxt_slow_path(inaddr == INADDR_NONE)) {
739 nxt_thread_log_error(NXT_LOG_ERR, "invalid address \"%V\"",
740 addr);
741 return NULL;
742 }
743 }
744
745 p++;
746 length = (addr->start + addr->length) - p;
747 port = nxt_int_parse(p, length);
748
749 if (port > 0 && port < 65536) {
750 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in),
751 NXT_INET_ADDR_STR_LEN);
752
753 if (nxt_slow_path(sa != NULL)) {
754 sa->u.sockaddr_in.sin_family = AF_INET;
755 sa->u.sockaddr_in.sin_port = htons((in_port_t) port);
756 sa->u.sockaddr_in.sin_addr.s_addr = inaddr;
757 }
758
759 return sa;
760 }
761 }
762
763 nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr);
764
765 return NULL;
766}
767
768
564void
565nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs)
566{
567 u_char *p;
568 size_t length;
569 nxt_int_t ret;
570 nxt_work_handler_t handler;
571

--- 135 unchanged lines hidden (view full) ---

707 mp = jbs->resolve.job.mem_pool;
708
709 jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
710
711 if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) {
712 return NXT_ERROR;
713 }
714
769void
770nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs)
771{
772 u_char *p;
773 size_t length;
774 nxt_int_t ret;
775 nxt_work_handler_t handler;
776

--- 135 unchanged lines hidden (view full) ---

912 mp = jbs->resolve.job.mem_pool;
913
914 jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
915
916 if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) {
917 return NXT_ERROR;
918 }
919
715 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6));
920 sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6),
921 NXT_INET6_ADDR_STR_LEN);
716
717 if (nxt_slow_path(sa == NULL)) {
718 return NXT_ERROR;
719 }
720
721 jbs->resolve.count = 1;
722 jbs->resolve.sockaddrs[0] = sa;
723

--- 354 unchanged lines hidden ---
922
923 if (nxt_slow_path(sa == NULL)) {
924 return NXT_ERROR;
925 }
926
927 jbs->resolve.count = 1;
928 jbs->resolve.sockaddrs[0] = sa;
929

--- 354 unchanged lines hidden ---