comparison src/core/ngx_inet.c @ 578:f3a9e57d2e17

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 11 Mar 2010 21:27:17 +0300
parents 25255878df91
children bb20316269e4
comparison
equal deleted inserted replaced
539:5f4de8cf0d9d 578:f3a9e57d2e17
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 9
10 10
11 #if (NGX_HAVE_INET6)
12 static size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
13 #endif
14 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); 11 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
15 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); 12 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
16 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); 13 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
17 14
18 15
57 54
58 return INADDR_NONE; 55 return INADDR_NONE;
59 } 56 }
60 57
61 58
59 #if (NGX_HAVE_INET6)
60
61 ngx_int_t
62 ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
63 {
64 u_char c, *zero, *digit, *s, *d;
65 size_t len4;
66 ngx_uint_t n, nibbles, word;
67
68 if (len == 0) {
69 return NGX_ERROR;
70 }
71
72 zero = NULL;
73 digit = NULL;
74 len4 = 0;
75 nibbles = 0;
76 word = 0;
77 n = 8;
78
79 if (p[0] == ':') {
80 p++;
81 len--;
82 }
83
84 for (/* void */; len; len--) {
85 c = *p++;
86
87 if (c == ':') {
88 if (nibbles) {
89 digit = p;
90 len4 = len;
91 *addr++ = (u_char) (word >> 8);
92 *addr++ = (u_char) (word & 0xff);
93
94 if (--n) {
95 nibbles = 0;
96 word = 0;
97 continue;
98 }
99
100 } else {
101 if (zero == NULL) {
102 digit = p;
103 len4 = len;
104 zero = addr;
105 continue;
106 }
107 }
108
109 return NGX_ERROR;
110 }
111
112 if (c == '.' && nibbles) {
113 if (n < 2) {
114 return NGX_ERROR;
115 }
116
117 word = ngx_inet_addr(digit, len4 - 1);
118 if (word == INADDR_NONE) {
119 return NGX_ERROR;
120 }
121
122 word = ntohl(word);
123 *addr++ = (u_char) ((word >> 24) & 0xff);
124 *addr++ = (u_char) ((word >> 16) & 0xff);
125 n--;
126 break;
127 }
128
129 if (++nibbles > 4) {
130 return NGX_ERROR;
131 }
132
133 if (c >= '0' && c <= '9') {
134 word = word * 16 + (c - '0');
135 continue;
136 }
137
138 c |= 0x20;
139
140 if (c >= 'a' && c <= 'f') {
141 word = word * 16 + (c - 'a') + 10;
142 continue;
143 }
144
145 return NGX_ERROR;
146 }
147
148 if (nibbles == 0 && zero == NULL) {
149 return NGX_ERROR;
150 }
151
152 *addr++ = (u_char) (word >> 8);
153 *addr++ = (u_char) (word & 0xff);
154
155 if (--n) {
156 if (zero) {
157 n *= 2;
158 s = addr - 1;
159 d = s + n;
160 while (s >= zero) {
161 *d-- = *s--;
162 }
163 ngx_memzero(zero, n);
164 return NGX_OK;
165 }
166
167 } else {
168 if (zero == NULL) {
169 return NGX_OK;
170 }
171 }
172
173 return NGX_ERROR;
174 }
175
176 #endif
177
178
62 size_t 179 size_t
63 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port) 180 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
64 { 181 {
65 u_char *p; 182 u_char *p;
66 struct sockaddr_in *sin; 183 struct sockaddr_in *sin;
67 #if (NGX_HAVE_INET6) 184 #if (NGX_HAVE_INET6)
68 size_t n; 185 size_t n;
69 struct sockaddr_in6 *sin6; 186 struct sockaddr_in6 *sin6;
187 #endif
188 #if (NGX_HAVE_UNIX_DOMAIN)
189 struct sockaddr_un *saun;
70 #endif 190 #endif
71 191
72 switch (sa->sa_family) { 192 switch (sa->sa_family) {
73 193
74 case AF_INET: 194 case AF_INET:
96 216
97 if (port) { 217 if (port) {
98 text[n++] = '['; 218 text[n++] = '[';
99 } 219 }
100 220
101 n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len); 221 n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
102 222
103 if (port) { 223 if (port) {
104 n = ngx_sprintf(&text[1 + n], "]:%d", 224 n = ngx_sprintf(&text[1 + n], "]:%d",
105 ntohs(sin6->sin6_port)) - text; 225 ntohs(sin6->sin6_port)) - text;
106 } 226 }
107 227
108 return n; 228 return n;
109 #endif 229 #endif
110 230
231 #if (NGX_HAVE_UNIX_DOMAIN)
232
233 case AF_UNIX:
234 saun = (struct sockaddr_un *) sa;
235
236 /* we do not include trailing zero in address length */
237
238 return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
239
240 #endif
241
111 default: 242 default:
112 return 0; 243 return 0;
113 } 244 }
114 } 245 }
115 246
142 } 273 }
143 274
144 275
145 #if (NGX_HAVE_INET6) 276 #if (NGX_HAVE_INET6)
146 277
147 static size_t 278 size_t
148 ngx_inet6_ntop(u_char *p, u_char *text, size_t len) 279 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
149 { 280 {
150 u_char *dst; 281 u_char *dst;
151 size_t max, n; 282 size_t max, n;
152 ngx_uint_t i, zero, last; 283 ngx_uint_t i, zero, last;
221 } 352 }
222 353
223 #endif 354 #endif
224 355
225 356
226 /* AF_INET only */
227
228 ngx_int_t 357 ngx_int_t
229 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr) 358 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
230 { 359 {
231 u_char *addr, *mask, *last; 360 u_char *addr, *mask, *last;
232 ngx_int_t shift; 361 size_t len;
362 ngx_int_t shift;
363 #if (NGX_HAVE_INET6)
364 ngx_int_t rc;
365 ngx_uint_t s, i;
366 #endif
233 367
234 addr = text->data; 368 addr = text->data;
235 last = addr + text->len; 369 last = addr + text->len;
236 370
237 mask = ngx_strlchr(addr, last, '/'); 371 mask = ngx_strlchr(addr, last, '/');
238 372 len = (mask ? mask : last) - addr;
239 cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr); 373
240 374 cidr->u.in.addr = ngx_inet_addr(addr, len);
241 if (cidr->u.in.addr == INADDR_NONE) { 375
242 return NGX_ERROR; 376 if (cidr->u.in.addr != INADDR_NONE) {
243 }
244
245 if (mask == NULL) {
246 cidr->family = AF_INET; 377 cidr->family = AF_INET;
247 cidr->u.in.mask = 0xffffffff; 378
248 return NGX_OK; 379 if (mask == NULL) {
380 cidr->u.in.mask = 0xffffffff;
381 return NGX_OK;
382 }
383
384 #if (NGX_HAVE_INET6)
385 } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
386 cidr->family = AF_INET6;
387
388 if (mask == NULL) {
389 ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
390 return NGX_OK;
391 }
392
393 #endif
394 } else {
395 return NGX_ERROR;
249 } 396 }
250 397
251 mask++; 398 mask++;
252 399
253 shift = ngx_atoi(mask, last - mask); 400 shift = ngx_atoi(mask, last - mask);
254 if (shift == NGX_ERROR) { 401 if (shift == NGX_ERROR) {
255 return NGX_ERROR; 402 return NGX_ERROR;
256 } 403 }
257 404
258 cidr->family = AF_INET; 405 switch (cidr->family) {
259 406
260 if (shift == 0) { 407 #if (NGX_HAVE_INET6)
261 408 case AF_INET6:
262 /* the x86 compilers use the shl instruction that shifts by modulo 32 */ 409 addr = cidr->u.in6.addr.s6_addr;
263 410 mask = cidr->u.in6.mask.s6_addr;
264 cidr->u.in.mask = 0; 411 rc = NGX_OK;
265 412
266 if (cidr->u.in.addr == 0) { 413 for (i = 0; i < 16; i++) {
414
415 s = (shift > 8) ? 8 : shift;
416 shift -= s;
417
418 mask[i] = (u_char) (0 - (1 << (8 - s)));
419
420 if (addr[i] != (addr[i] & mask[i])) {
421 rc = NGX_DONE;
422 addr[i] &= mask[i];
423 }
424 }
425
426 return rc;
427 #endif
428
429 default: /* AF_INET */
430
431 if (shift) {
432 cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
433
434 } else {
435 /* x86 compilers use a shl instruction that shifts by modulo 32 */
436 cidr->u.in.mask = 0;
437 }
438
439 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
267 return NGX_OK; 440 return NGX_OK;
268 } 441 }
269 442
443 cidr->u.in.addr &= cidr->u.in.mask;
444
270 return NGX_DONE; 445 return NGX_DONE;
271 } 446 }
272 447 }
273 cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift)))); 448
274 449
275 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) { 450 ngx_int_t
276 return NGX_OK; 451 ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
277 } 452 {
278 453 in_addr_t inaddr;
279 cidr->u.in.addr &= cidr->u.in.mask; 454 ngx_uint_t family;
280 455 struct sockaddr_in *sin;
281 return NGX_DONE; 456 #if (NGX_HAVE_INET6)
457 struct in6_addr inaddr6;
458 struct sockaddr_in6 *sin6;
459
460 /*
461 * prevent MSVC8 waring:
462 * potentially uninitialized local variable 'inaddr6' used
463 */
464 ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
465 #endif
466
467 inaddr = ngx_inet_addr(text, len);
468
469 if (inaddr != INADDR_NONE) {
470 family = AF_INET;
471 len = sizeof(struct sockaddr_in);
472
473 #if (NGX_HAVE_INET6)
474 } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
475 family = AF_INET6;
476 len = sizeof(struct sockaddr_in6);
477
478 #endif
479 } else {
480 return NGX_DECLINED;
481 }
482
483 addr->sockaddr = ngx_pcalloc(pool, len);
484 if (addr->sockaddr == NULL) {
485 return NGX_ERROR;
486 }
487
488 addr->sockaddr->sa_family = (u_char) family;
489 addr->socklen = len;
490
491 switch (family) {
492
493 #if (NGX_HAVE_INET6)
494 case AF_INET6:
495 sin6 = (struct sockaddr_in6 *) addr->sockaddr;
496 ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
497 break;
498 #endif
499
500 default: /* AF_INET */
501 sin = (struct sockaddr_in *) addr->sockaddr;
502 sin->sin_addr.s_addr = inaddr;
503 break;
504 }
505
506 return NGX_OK;
282 } 507 }
283 508
284 509
285 ngx_int_t 510 ngx_int_t
286 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) 511 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
349 u->socklen = sizeof(struct sockaddr_un); 574 u->socklen = sizeof(struct sockaddr_un);
350 saun = (struct sockaddr_un *) &u->sockaddr; 575 saun = (struct sockaddr_un *) &u->sockaddr;
351 saun->sun_family = AF_UNIX; 576 saun->sun_family = AF_UNIX;
352 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); 577 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
353 578
354 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); 579 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
355 if (u->addrs == NULL) { 580 if (u->addrs == NULL) {
356 return NGX_ERROR; 581 return NGX_ERROR;
357 } 582 }
358 583
359 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un)); 584 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
507 732
508 if (u->no_resolve) { 733 if (u->no_resolve) {
509 return NGX_OK; 734 return NGX_OK;
510 } 735 }
511 736
512 if (len++) { 737 if (len) {
513 738 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
514 p = ngx_alloc(len, pool->log);
515 if (p == NULL) {
516 return NGX_ERROR;
517 }
518
519 (void) ngx_cpystrn(p, host, len);
520
521 sin->sin_addr.s_addr = inet_addr((const char *) p);
522 739
523 if (sin->sin_addr.s_addr == INADDR_NONE) { 740 if (sin->sin_addr.s_addr == INADDR_NONE) {
741 p = ngx_alloc(++len, pool->log);
742 if (p == NULL) {
743 return NGX_ERROR;
744 }
745
746 (void) ngx_cpystrn(p, host, len);
747
524 h = gethostbyname((const char *) p); 748 h = gethostbyname((const char *) p);
525 749
750 ngx_free(p);
751
526 if (h == NULL || h->h_addr_list[0] == NULL) { 752 if (h == NULL || h->h_addr_list[0] == NULL) {
527 ngx_free(p);
528 u->err = "host not found"; 753 u->err = "host not found";
529 return NGX_ERROR; 754 return NGX_ERROR;
530 } 755 }
531 756
532 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]); 757 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
533 } 758 }
534 759
535 if (sin->sin_addr.s_addr == INADDR_ANY) { 760 if (sin->sin_addr.s_addr == INADDR_ANY) {
536 u->wildcard = 1; 761 u->wildcard = 1;
537 } 762 }
538
539 ngx_free(p);
540 763
541 } else { 764 } else {
542 sin->sin_addr.s_addr = INADDR_ANY; 765 sin->sin_addr.s_addr = INADDR_ANY;
543 u->wildcard = 1; 766 u->wildcard = 1;
544 } 767 }
562 785
563 static ngx_int_t 786 static ngx_int_t
564 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) 787 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
565 { 788 {
566 #if (NGX_HAVE_INET6) 789 #if (NGX_HAVE_INET6)
567 int rc;
568 u_char *p, *host, *port, *last, *uri; 790 u_char *p, *host, *port, *last, *uri;
569 size_t len; 791 size_t len;
570 ngx_int_t n; 792 ngx_int_t n;
571 struct sockaddr_in6 *sin6; 793 struct sockaddr_in6 *sin6;
572 794
634 if (len == 0) { 856 if (len == 0) {
635 u->err = "no host"; 857 u->err = "no host";
636 return NGX_ERROR; 858 return NGX_ERROR;
637 } 859 }
638 860
639 u->host.len = len++; 861 u->host.len = len;
640 u->host.data = host; 862 u->host.data = host;
641 863
642 p = ngx_alloc(len, pool->log); 864 if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
643 if (p == NULL) {
644 return NGX_ERROR;
645 }
646
647 (void) ngx_cpystrn(p, host, len);
648
649 #if (NGX_WIN32)
650
651 rc = WSAStringToAddress((char *) p, AF_INET6, NULL,
652 (SOCKADDR *) sin6, &u->socklen);
653 rc = !rc;
654
655 if (u->port) {
656 sin6->sin6_port = htons(u->port);
657 }
658
659 #else
660
661 rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
662
663 #endif
664
665 ngx_free(p);
666
667 if (rc == 0) {
668 u->err = "invalid IPv6 address"; 865 u->err = "invalid IPv6 address";
669 return NGX_ERROR; 866 return NGX_ERROR;
670 } 867 }
671 868
672 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 869 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
705 in_addr_t in_addr; 902 in_addr_t in_addr;
706 ngx_uint_t i; 903 ngx_uint_t i;
707 struct hostent *h; 904 struct hostent *h;
708 struct sockaddr_in *sin; 905 struct sockaddr_in *sin;
709 906
710 host = ngx_alloc(u->host.len + 1, pool->log);
711 if (host == NULL) {
712 return NGX_ERROR;
713 }
714
715 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
716
717 /* AF_INET only */ 907 /* AF_INET only */
718 908
719 port = htons(u->port); 909 port = htons(u->port);
720 910
721 in_addr = inet_addr((char *) host); 911 in_addr = ngx_inet_addr(u->host.data, u->host.len);
722 912
723 if (in_addr == INADDR_NONE) { 913 if (in_addr == INADDR_NONE) {
914 host = ngx_alloc(u->host.len + 1, pool->log);
915 if (host == NULL) {
916 return NGX_ERROR;
917 }
918
919 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
920
724 h = gethostbyname((char *) host); 921 h = gethostbyname((char *) host);
725 922
726 ngx_free(host); 923 ngx_free(host);
727 924
728 if (h == NULL || h->h_addr_list[0] == NULL) { 925 if (h == NULL || h->h_addr_list[0] == NULL) {
737 i = 1; 934 i = 1;
738 } 935 }
739 936
740 /* MP: ngx_shared_palloc() */ 937 /* MP: ngx_shared_palloc() */
741 938
742 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t)); 939 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
743 if (u->addrs == NULL) { 940 if (u->addrs == NULL) {
744 return NGX_ERROR; 941 return NGX_ERROR;
745 } 942 }
746 943
747 u->naddrs = i; 944 u->naddrs = i;
773 u->addrs[i].name.data = p; 970 u->addrs[i].name.data = p;
774 } 971 }
775 972
776 } else { 973 } else {
777 974
778 ngx_free(host);
779
780 /* MP: ngx_shared_palloc() */ 975 /* MP: ngx_shared_palloc() */
781 976
782 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); 977 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
783 if (u->addrs == NULL) { 978 if (u->addrs == NULL) {
784 return NGX_ERROR; 979 return NGX_ERROR;
785 } 980 }
786 981
787 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); 982 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));