Annotation of embedaddon/nginx/src/core/ngx_inet.c, revision 1.1.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>