Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / core / ngx_inet.c
blob7757ab7d9053d96b450e809b30905be2d2429406
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
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);
17 in_addr_t
18 ngx_inet_addr(u_char *text, size_t len)
20 u_char *p, c;
21 in_addr_t addr;
22 ngx_uint_t octet, n;
24 addr = 0;
25 octet = 0;
26 n = 0;
28 for (p = text; p < text + len; p++) {
30 c = *p;
32 if (c >= '0' && c <= '9') {
33 octet = octet * 10 + (c - '0');
34 continue;
37 if (c == '.' && octet < 256) {
38 addr = (addr << 8) + octet;
39 octet = 0;
40 n++;
41 continue;
44 return INADDR_NONE;
47 if (n == 3 && octet < 256) {
48 addr = (addr << 8) + octet;
49 return htonl(addr);
52 return INADDR_NONE;
56 #if (NGX_HAVE_INET6)
58 ngx_int_t
59 ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
61 u_char c, *zero, *digit, *s, *d;
62 size_t len4;
63 ngx_uint_t n, nibbles, word;
65 if (len == 0) {
66 return NGX_ERROR;
69 zero = NULL;
70 digit = NULL;
71 len4 = 0;
72 nibbles = 0;
73 word = 0;
74 n = 8;
76 if (p[0] == ':') {
77 p++;
78 len--;
81 for (/* void */; len; len--) {
82 c = *p++;
84 if (c == ':') {
85 if (nibbles) {
86 digit = p;
87 len4 = len;
88 *addr++ = (u_char) (word >> 8);
89 *addr++ = (u_char) (word & 0xff);
91 if (--n) {
92 nibbles = 0;
93 word = 0;
94 continue;
97 } else {
98 if (zero == NULL) {
99 digit = p;
100 len4 = len;
101 zero = addr;
102 continue;
106 return NGX_ERROR;
109 if (c == '.' && nibbles) {
110 if (n < 2 || digit == NULL) {
111 return NGX_ERROR;
114 word = ngx_inet_addr(digit, len4 - 1);
115 if (word == INADDR_NONE) {
116 return NGX_ERROR;
119 word = ntohl(word);
120 *addr++ = (u_char) ((word >> 24) & 0xff);
121 *addr++ = (u_char) ((word >> 16) & 0xff);
122 n--;
123 break;
126 if (++nibbles > 4) {
127 return NGX_ERROR;
130 if (c >= '0' && c <= '9') {
131 word = word * 16 + (c - '0');
132 continue;
135 c |= 0x20;
137 if (c >= 'a' && c <= 'f') {
138 word = word * 16 + (c - 'a') + 10;
139 continue;
142 return NGX_ERROR;
145 if (nibbles == 0 && zero == NULL) {
146 return NGX_ERROR;
149 *addr++ = (u_char) (word >> 8);
150 *addr++ = (u_char) (word & 0xff);
152 if (--n) {
153 if (zero) {
154 n *= 2;
155 s = addr - 1;
156 d = s + n;
157 while (s >= zero) {
158 *d-- = *s--;
160 ngx_memzero(zero, n);
161 return NGX_OK;
164 } else {
165 if (zero == NULL) {
166 return NGX_OK;
170 return NGX_ERROR;
173 #endif
176 size_t
177 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
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
189 switch (sa->sa_family) {
191 case AF_INET:
193 sin = (struct sockaddr_in *) sa;
194 p = (u_char *) &sin->sin_addr;
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]);
204 return (p - text);
206 #if (NGX_HAVE_INET6)
208 case AF_INET6:
210 sin6 = (struct sockaddr_in6 *) sa;
212 n = 0;
214 if (port) {
215 text[n++] = '[';
218 n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
220 if (port) {
221 n = ngx_sprintf(&text[1 + n], "]:%d",
222 ntohs(sin6->sin6_port)) - text;
225 return n;
226 #endif
228 #if (NGX_HAVE_UNIX_DOMAIN)
230 case AF_UNIX:
231 saun = (struct sockaddr_un *) sa;
233 /* we do not include trailing zero in address length */
235 return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
237 #endif
239 default:
240 return 0;
245 size_t
246 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
248 u_char *p;
250 switch (family) {
252 case AF_INET:
254 p = addr;
256 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
257 p[0], p[1], p[2], p[3])
258 - text;
260 #if (NGX_HAVE_INET6)
262 case AF_INET6:
263 return ngx_inet6_ntop(addr, text, len);
265 #endif
267 default:
268 return 0;
273 #if (NGX_HAVE_INET6)
275 size_t
276 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
278 u_char *dst;
279 size_t max, n;
280 ngx_uint_t i, zero, last;
282 if (len < NGX_INET6_ADDRSTRLEN) {
283 return 0;
286 zero = (ngx_uint_t) -1;
287 last = (ngx_uint_t) -1;
288 max = 1;
289 n = 0;
291 for (i = 0; i < 16; i += 2) {
293 if (p[i] || p[i + 1]) {
295 if (max < n) {
296 zero = last;
297 max = n;
300 n = 0;
301 continue;
304 if (n++ == 0) {
305 last = i;
309 if (max < n) {
310 zero = last;
311 max = n;
314 dst = text;
315 n = 16;
317 if (zero == 0) {
319 if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
320 || (max == 6)
321 || (max == 7 && p[14] != 0 && p[15] != 1))
323 n = 12;
326 *dst++ = ':';
329 for (i = 0; i < n; i += 2) {
331 if (i == zero) {
332 *dst++ = ':';
333 i += (max - 1) * 2;
334 continue;
337 dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
339 if (i < 14) {
340 *dst++ = ':';
344 if (n == 12) {
345 dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
348 return dst - text;
351 #endif
354 ngx_int_t
355 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
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
365 addr = text->data;
366 last = addr + text->len;
368 mask = ngx_strlchr(addr, last, '/');
369 len = (mask ? mask : last) - addr;
371 cidr->u.in.addr = ngx_inet_addr(addr, len);
373 if (cidr->u.in.addr != INADDR_NONE) {
374 cidr->family = AF_INET;
376 if (mask == NULL) {
377 cidr->u.in.mask = 0xffffffff;
378 return NGX_OK;
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;
385 if (mask == NULL) {
386 ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
387 return NGX_OK;
390 #endif
391 } else {
392 return NGX_ERROR;
395 mask++;
397 shift = ngx_atoi(mask, last - mask);
398 if (shift == NGX_ERROR) {
399 return NGX_ERROR;
402 switch (cidr->family) {
404 #if (NGX_HAVE_INET6)
405 case AF_INET6:
406 if (shift > 128) {
407 return NGX_ERROR;
410 addr = cidr->u.in6.addr.s6_addr;
411 mask = cidr->u.in6.mask.s6_addr;
412 rc = NGX_OK;
414 for (i = 0; i < 16; i++) {
416 s = (shift > 8) ? 8 : shift;
417 shift -= s;
419 mask[i] = (u_char) (0xffu << (8 - s));
421 if (addr[i] != (addr[i] & mask[i])) {
422 rc = NGX_DONE;
423 addr[i] &= mask[i];
427 return rc;
428 #endif
430 default: /* AF_INET */
431 if (shift > 32) {
432 return NGX_ERROR;
435 if (shift) {
436 cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
438 } else {
439 /* x86 compilers use a shl instruction that shifts by modulo 32 */
440 cidr->u.in.mask = 0;
443 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
444 return NGX_OK;
447 cidr->u.in.addr &= cidr->u.in.mask;
449 return NGX_DONE;
454 ngx_int_t
455 ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
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;
465 * prevent MSVC8 warning:
466 * potentially uninitialized local variable 'inaddr6' used
468 ngx_memzero(&inaddr6, sizeof(struct in6_addr));
469 #endif
471 inaddr = ngx_inet_addr(text, len);
473 if (inaddr != INADDR_NONE) {
474 family = AF_INET;
475 len = sizeof(struct sockaddr_in);
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);
482 #endif
483 } else {
484 return NGX_DECLINED;
487 addr->sockaddr = ngx_pcalloc(pool, len);
488 if (addr->sockaddr == NULL) {
489 return NGX_ERROR;
492 addr->sockaddr->sa_family = (u_char) family;
493 addr->socklen = len;
495 switch (family) {
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
504 default: /* AF_INET */
505 sin = (struct sockaddr_in *) addr->sockaddr;
506 sin->sin_addr.s_addr = inaddr;
507 break;
510 return NGX_OK;
514 ngx_int_t
515 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
517 u_char *p;
519 p = u->url.data;
521 if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
522 return ngx_parse_unix_domain_url(pool, u);
525 if (p[0] == '[') {
526 return ngx_parse_inet6_url(pool, u);
529 return ngx_parse_inet_url(pool, u);
533 static ngx_int_t
534 ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
536 #if (NGX_HAVE_UNIX_DOMAIN)
537 u_char *path, *uri, *last;
538 size_t len;
539 struct sockaddr_un *saun;
541 len = u->url.len;
542 path = u->url.data;
544 path += 5;
545 len -= 5;
547 if (u->uri_part) {
549 last = path + len;
550 uri = ngx_strlchr(path, last, ':');
552 if (uri) {
553 len = uri - path;
554 uri++;
555 u->uri.len = last - uri;
556 u->uri.data = uri;
560 if (len == 0) {
561 u->err = "no path in the unix domain socket";
562 return NGX_ERROR;
565 u->host.len = len++;
566 u->host.data = path;
568 if (len > sizeof(saun->sun_path)) {
569 u->err = "too long path in the unix domain socket";
570 return NGX_ERROR;
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);
578 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
579 if (u->addrs == NULL) {
580 return NGX_ERROR;
583 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
584 if (saun == NULL) {
585 return NGX_ERROR;
588 u->family = AF_UNIX;
589 u->naddrs = 1;
591 saun->sun_family = AF_UNIX;
592 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
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;
599 return NGX_OK;
601 #else
603 u->err = "the unix domain sockets are not supported on this platform";
605 return NGX_ERROR;
607 #endif
611 static ngx_int_t
612 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
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
622 u->socklen = sizeof(struct sockaddr_in);
623 sin = (struct sockaddr_in *) &u->sockaddr;
624 sin->sin_family = AF_INET;
626 u->family = AF_INET;
628 host = u->url.data;
630 last = host + u->url.len;
632 port = ngx_strlchr(host, last, ':');
634 uri = ngx_strlchr(host, last, '/');
636 args = ngx_strlchr(host, last, '?');
638 if (args) {
639 if (uri == NULL || args < uri) {
640 uri = args;
644 if (uri) {
645 if (u->listen || !u->uri_part) {
646 u->err = "invalid host";
647 return NGX_ERROR;
650 u->uri.len = last - uri;
651 u->uri.data = uri;
653 last = uri;
655 if (uri < port) {
656 port = NULL;
660 if (port) {
661 port++;
663 len = last - port;
665 n = ngx_atoi(port, len);
667 if (n < 1 || n > 65535) {
668 u->err = "invalid port";
669 return NGX_ERROR;
672 u->port = (in_port_t) n;
673 sin->sin_port = htons((in_port_t) n);
675 u->port_text.len = len;
676 u->port_text.data = port;
678 last = port - 1;
680 } else {
681 if (uri == NULL) {
683 if (u->listen) {
685 /* test value as port only */
687 n = ngx_atoi(host, last - host);
689 if (n != NGX_ERROR) {
691 if (n < 1 || n > 65535) {
692 u->err = "invalid port";
693 return NGX_ERROR;
696 u->port = (in_port_t) n;
697 sin->sin_port = htons((in_port_t) n);
699 u->port_text.len = last - host;
700 u->port_text.data = host;
702 u->wildcard = 1;
704 return NGX_OK;
709 u->no_port = 1;
710 u->port = u->default_port;
711 sin->sin_port = htons(u->default_port);
714 len = last - host;
716 if (len == 0) {
717 u->err = "no host";
718 return NGX_ERROR;
721 u->host.len = len;
722 u->host.data = host;
724 if (u->listen && len == 1 && *host == '*') {
725 sin->sin_addr.s_addr = INADDR_ANY;
726 u->wildcard = 1;
727 return NGX_OK;
730 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
732 if (sin->sin_addr.s_addr != INADDR_NONE) {
734 if (sin->sin_addr.s_addr == INADDR_ANY) {
735 u->wildcard = 1;
738 u->naddrs = 1;
740 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
741 if (u->addrs == NULL) {
742 return NGX_ERROR;
745 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
746 if (sin == NULL) {
747 return NGX_ERROR;
750 ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in));
752 u->addrs[0].sockaddr = (struct sockaddr *) sin;
753 u->addrs[0].socklen = sizeof(struct sockaddr_in);
755 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
756 if (p == NULL) {
757 return NGX_ERROR;
760 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
761 &u->host, u->port) - p;
762 u->addrs[0].name.data = p;
764 return NGX_OK;
767 if (u->no_resolve) {
768 return NGX_OK;
771 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
772 return NGX_ERROR;
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);
779 switch (u->family) {
781 #if (NGX_HAVE_INET6)
782 case AF_INET6:
783 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
785 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
786 u->wildcard = 1;
789 break;
790 #endif
792 default: /* AF_INET */
793 sin = (struct sockaddr_in *) &u->sockaddr;
795 if (sin->sin_addr.s_addr == INADDR_ANY) {
796 u->wildcard = 1;
799 break;
802 return NGX_OK;
806 static ngx_int_t
807 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
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;
815 u->socklen = sizeof(struct sockaddr_in6);
816 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
817 sin6->sin6_family = AF_INET6;
819 host = u->url.data + 1;
821 last = u->url.data + u->url.len;
823 p = ngx_strlchr(host, last, ']');
825 if (p == NULL) {
826 u->err = "invalid host";
827 return NGX_ERROR;
830 if (last - p) {
832 port = p + 1;
834 uri = ngx_strlchr(port, last, '/');
836 if (uri) {
837 if (u->listen || !u->uri_part) {
838 u->err = "invalid host";
839 return NGX_ERROR;
842 u->uri.len = last - uri;
843 u->uri.data = uri;
845 last = uri;
848 if (*port == ':') {
849 port++;
851 len = last - port;
853 n = ngx_atoi(port, len);
855 if (n < 1 || n > 65535) {
856 u->err = "invalid port";
857 return NGX_ERROR;
860 u->port = (in_port_t) n;
861 sin6->sin6_port = htons((in_port_t) n);
863 u->port_text.len = len;
864 u->port_text.data = port;
866 } else {
867 u->no_port = 1;
868 u->port = u->default_port;
869 sin6->sin6_port = htons(u->default_port);
873 len = p - host;
875 if (len == 0) {
876 u->err = "no host";
877 return NGX_ERROR;
880 u->host.len = len + 2;
881 u->host.data = host - 1;
883 if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
884 u->err = "invalid IPv6 address";
885 return NGX_ERROR;
888 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
889 u->wildcard = 1;
892 u->family = AF_INET6;
893 u->naddrs = 1;
895 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
896 if (u->addrs == NULL) {
897 return NGX_ERROR;
900 sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
901 if (sin6 == NULL) {
902 return NGX_ERROR;
905 ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6));
907 u->addrs[0].sockaddr = (struct sockaddr *) sin6;
908 u->addrs[0].socklen = sizeof(struct sockaddr_in6);
910 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
911 if (p == NULL) {
912 return NGX_ERROR;
915 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
916 &u->host, u->port) - p;
917 u->addrs[0].name.data = p;
919 return NGX_OK;
921 #else
923 u->err = "the INET6 sockets are not supported on this platform";
925 return NGX_ERROR;
927 #endif
931 #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
933 ngx_int_t
934 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
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;
944 port = htons(u->port);
946 host = ngx_alloc(u->host.len + 1, pool->log);
947 if (host == NULL) {
948 return NGX_ERROR;
951 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
953 ngx_memzero(&hints, sizeof(struct addrinfo));
954 hints.ai_family = AF_UNSPEC;
955 hints.ai_socktype = SOCK_STREAM;
957 if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
958 u->err = "host not found";
959 ngx_free(host);
960 return NGX_ERROR;
963 ngx_free(host);
965 for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) {
967 switch (rp->ai_family) {
969 case AF_INET:
970 case AF_INET6:
971 break;
973 default:
974 continue;
977 i++;
980 if (i == 0) {
981 u->err = "host not found";
982 goto failed;
985 /* MP: ngx_shared_palloc() */
987 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
988 if (u->addrs == NULL) {
989 goto failed;
992 u->naddrs = i;
994 i = 0;
996 /* AF_INET addresses first */
998 for (rp = res; rp != NULL; rp = rp->ai_next) {
1000 if (rp->ai_family != AF_INET) {
1001 continue;
1004 sin = ngx_pcalloc(pool, rp->ai_addrlen);
1005 if (sin == NULL) {
1006 goto failed;
1009 ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
1011 sin->sin_port = port;
1013 u->addrs[i].sockaddr = (struct sockaddr *) sin;
1014 u->addrs[i].socklen = rp->ai_addrlen;
1016 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
1018 p = ngx_pnalloc(pool, len);
1019 if (p == NULL) {
1020 goto failed;
1023 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
1025 u->addrs[i].name.len = len;
1026 u->addrs[i].name.data = p;
1028 i++;
1031 for (rp = res; rp != NULL; rp = rp->ai_next) {
1033 if (rp->ai_family != AF_INET6) {
1034 continue;
1037 sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
1038 if (sin6 == NULL) {
1039 goto failed;
1042 ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
1044 sin6->sin6_port = port;
1046 u->addrs[i].sockaddr = (struct sockaddr *) sin6;
1047 u->addrs[i].socklen = rp->ai_addrlen;
1049 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
1051 p = ngx_pnalloc(pool, len);
1052 if (p == NULL) {
1053 goto failed;
1056 len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
1058 u->addrs[i].name.len = len;
1059 u->addrs[i].name.data = p;
1061 i++;
1064 freeaddrinfo(res);
1065 return NGX_OK;
1067 failed:
1069 freeaddrinfo(res);
1070 return NGX_ERROR;
1073 #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
1075 ngx_int_t
1076 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
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;
1086 /* AF_INET only */
1088 port = htons(u->port);
1090 in_addr = ngx_inet_addr(u->host.data, u->host.len);
1092 if (in_addr == INADDR_NONE) {
1093 host = ngx_alloc(u->host.len + 1, pool->log);
1094 if (host == NULL) {
1095 return NGX_ERROR;
1098 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
1100 h = gethostbyname((char *) host);
1102 ngx_free(host);
1104 if (h == NULL || h->h_addr_list[0] == NULL) {
1105 u->err = "host not found";
1106 return NGX_ERROR;
1109 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
1111 /* MP: ngx_shared_palloc() */
1113 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
1114 if (u->addrs == NULL) {
1115 return NGX_ERROR;
1118 u->naddrs = i;
1120 for (i = 0; i < u->naddrs; i++) {
1122 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
1123 if (sin == NULL) {
1124 return NGX_ERROR;
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]);
1131 u->addrs[i].sockaddr = (struct sockaddr *) sin;
1132 u->addrs[i].socklen = sizeof(struct sockaddr_in);
1134 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
1136 p = ngx_pnalloc(pool, len);
1137 if (p == NULL) {
1138 return NGX_ERROR;
1141 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
1143 u->addrs[i].name.len = len;
1144 u->addrs[i].name.data = p;
1147 } else {
1149 /* MP: ngx_shared_palloc() */
1151 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
1152 if (u->addrs == NULL) {
1153 return NGX_ERROR;
1156 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
1157 if (sin == NULL) {
1158 return NGX_ERROR;
1161 u->naddrs = 1;
1163 sin->sin_family = AF_INET;
1164 sin->sin_port = port;
1165 sin->sin_addr.s_addr = in_addr;
1167 u->addrs[0].sockaddr = (struct sockaddr *) sin;
1168 u->addrs[0].socklen = sizeof(struct sockaddr_in);
1170 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
1171 if (p == NULL) {
1172 return NGX_ERROR;
1175 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
1176 &u->host, ntohs(port)) - p;
1177 u->addrs[0].name.data = p;
1180 return NGX_OK;
1183 #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */