comparison src/core/ngx_inet.c @ 540:c04fa65fe604 NGINX_0_8_22

nginx 0.8.22 *) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind" directives. *) Feature: the "access" and the "deny" directives support IPv6. *) Feature: the "set_real_ip_from" directive supports IPv6 addresses in request headers. *) Feature: the "unix:" parameter of the "set_real_ip_from" directive. *) Bugfix: nginx did not delete unix domain socket after configuration testing. *) Bugfix: nginx deleted unix domain socket while online upgrade. *) Bugfix: the "!-x" operator did not work. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process, if limit_rate was used in HTTPS server. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process while $limit_rate logging. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process, if there was no "listen" directive in "server" block; the bug had appeared in 0.8.21.
author Igor Sysoev <http://sysoev.ru>
date Tue, 03 Nov 2009 00:00:00 +0300
parents 1dcf6adad484
children 25255878df91
comparison
equal deleted inserted replaced
539:c88014f74832 540:c04fa65fe604
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
55 return htonl(addr); 52 return htonl(addr);
56 } 53 }
57 54
58 return INADDR_NONE; 55 return INADDR_NONE;
59 } 56 }
57
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
60 177
61 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 {
99 216
100 if (port) { 217 if (port) {
101 text[n++] = '['; 218 text[n++] = '[';
102 } 219 }
103 220
104 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);
105 222
106 if (port) { 223 if (port) {
107 n = ngx_sprintf(&text[1 + n], "]:%d", 224 n = ngx_sprintf(&text[1 + n], "]:%d",
108 ntohs(sin6->sin6_port)) - text; 225 ntohs(sin6->sin6_port)) - text;
109 } 226 }
156 } 273 }
157 274
158 275
159 #if (NGX_HAVE_INET6) 276 #if (NGX_HAVE_INET6)
160 277
161 static size_t 278 size_t
162 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)
163 { 280 {
164 u_char *dst; 281 u_char *dst;
165 size_t max, n; 282 size_t max, n;
166 ngx_uint_t i, zero, last; 283 ngx_uint_t i, zero, last;
235 } 352 }
236 353
237 #endif 354 #endif
238 355
239 356
240 /* AF_INET only */
241
242 ngx_int_t 357 ngx_int_t
243 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr) 358 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
244 { 359 {
245 u_char *addr, *mask, *last; 360 u_char *addr, *mask, *last;
246 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
247 367
248 addr = text->data; 368 addr = text->data;
249 last = addr + text->len; 369 last = addr + text->len;
250 370
251 mask = ngx_strlchr(addr, last, '/'); 371 mask = ngx_strlchr(addr, last, '/');
252 372 len = (mask ? mask : last) - addr;
253 cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr); 373
254 374 cidr->u.in.addr = ngx_inet_addr(addr, len);
255 if (cidr->u.in.addr == INADDR_NONE) { 375
256 return NGX_ERROR; 376 if (cidr->u.in.addr != INADDR_NONE) {
257 }
258
259 if (mask == NULL) {
260 cidr->family = AF_INET; 377 cidr->family = AF_INET;
261 cidr->u.in.mask = 0xffffffff; 378
262 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;
263 } 396 }
264 397
265 mask++; 398 mask++;
266 399
267 shift = ngx_atoi(mask, last - mask); 400 shift = ngx_atoi(mask, last - mask);
268 if (shift == NGX_ERROR) { 401 if (shift == NGX_ERROR) {
269 return NGX_ERROR; 402 return NGX_ERROR;
270 } 403 }
271 404
272 cidr->family = AF_INET; 405 switch (cidr->family) {
273 406
274 if (shift == 0) { 407 #if (NGX_HAVE_INET6)
275 408 case AF_INET6:
276 /* the x86 compilers use the shl instruction that shifts by modulo 32 */ 409 addr = cidr->u.in6.addr.s6_addr;
277 410 mask = cidr->u.in6.mask.s6_addr;
278 cidr->u.in.mask = 0; 411 rc = NGX_OK;
279 412
280 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)) {
281 return NGX_OK; 440 return NGX_OK;
282 } 441 }
283 442
443 cidr->u.in.addr &= cidr->u.in.mask;
444
284 return NGX_DONE; 445 return NGX_DONE;
285 } 446 }
286 447 }
287 cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift)))); 448
288 449
289 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) { 450 ngx_int_t
290 return NGX_OK; 451 ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
291 } 452 {
292 453 in_addr_t inaddr;
293 cidr->u.in.addr &= cidr->u.in.mask; 454 ngx_uint_t family;
294 455 struct sockaddr_in *sin;
295 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;
296 } 507 }
297 508
298 509
299 ngx_int_t 510 ngx_int_t
300 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) 511 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
363 u->socklen = sizeof(struct sockaddr_un); 574 u->socklen = sizeof(struct sockaddr_un);
364 saun = (struct sockaddr_un *) &u->sockaddr; 575 saun = (struct sockaddr_un *) &u->sockaddr;
365 saun->sun_family = AF_UNIX; 576 saun->sun_family = AF_UNIX;
366 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); 577 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
367 578
368 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); 579 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
369 if (u->addrs == NULL) { 580 if (u->addrs == NULL) {
370 return NGX_ERROR; 581 return NGX_ERROR;
371 } 582 }
372 583
373 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un)); 584 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
521 732
522 if (u->no_resolve) { 733 if (u->no_resolve) {
523 return NGX_OK; 734 return NGX_OK;
524 } 735 }
525 736
526 if (len++) { 737 if (len) {
527 738 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
528 p = ngx_alloc(len, pool->log);
529 if (p == NULL) {
530 return NGX_ERROR;
531 }
532
533 (void) ngx_cpystrn(p, host, len);
534
535 sin->sin_addr.s_addr = inet_addr((const char *) p);
536 739
537 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
538 h = gethostbyname((const char *) p); 748 h = gethostbyname((const char *) p);
749
750 ngx_free(p);
539 751
540 if (h == NULL || h->h_addr_list[0] == NULL) { 752 if (h == NULL || h->h_addr_list[0] == NULL) {
541 ngx_free(p); 753 ngx_free(p);
542 u->err = "host not found"; 754 u->err = "host not found";
543 return NGX_ERROR; 755 return NGX_ERROR;
548 760
549 if (sin->sin_addr.s_addr == INADDR_ANY) { 761 if (sin->sin_addr.s_addr == INADDR_ANY) {
550 u->wildcard = 1; 762 u->wildcard = 1;
551 } 763 }
552 764
553 ngx_free(p);
554
555 } else { 765 } else {
556 sin->sin_addr.s_addr = INADDR_ANY; 766 sin->sin_addr.s_addr = INADDR_ANY;
557 u->wildcard = 1; 767 u->wildcard = 1;
558 } 768 }
559 769
576 786
577 static ngx_int_t 787 static ngx_int_t
578 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) 788 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
579 { 789 {
580 #if (NGX_HAVE_INET6) 790 #if (NGX_HAVE_INET6)
581 int rc;
582 u_char *p, *host, *port, *last, *uri; 791 u_char *p, *host, *port, *last, *uri;
583 size_t len; 792 size_t len;
584 ngx_int_t n; 793 ngx_int_t n;
585 struct sockaddr_in6 *sin6; 794 struct sockaddr_in6 *sin6;
586 795
648 if (len == 0) { 857 if (len == 0) {
649 u->err = "no host"; 858 u->err = "no host";
650 return NGX_ERROR; 859 return NGX_ERROR;
651 } 860 }
652 861
653 u->host.len = len++; 862 u->host.len = len;
654 u->host.data = host; 863 u->host.data = host;
655 864
656 p = ngx_alloc(len, pool->log); 865 if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
657 if (p == NULL) {
658 return NGX_ERROR;
659 }
660
661 (void) ngx_cpystrn(p, host, len);
662
663 #if (NGX_WIN32)
664
665 rc = WSAStringToAddress((char *) p, AF_INET6, NULL,
666 (SOCKADDR *) sin6, &u->socklen);
667 rc = !rc;
668
669 if (u->port) {
670 sin6->sin6_port = htons(u->port);
671 }
672
673 #else
674
675 rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
676
677 #endif
678
679 ngx_free(p);
680
681 if (rc == 0) {
682 u->err = "invalid IPv6 address"; 866 u->err = "invalid IPv6 address";
683 return NGX_ERROR; 867 return NGX_ERROR;
684 } 868 }
685 869
686 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 870 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
719 in_addr_t in_addr; 903 in_addr_t in_addr;
720 ngx_uint_t i; 904 ngx_uint_t i;
721 struct hostent *h; 905 struct hostent *h;
722 struct sockaddr_in *sin; 906 struct sockaddr_in *sin;
723 907
724 host = ngx_alloc(u->host.len + 1, pool->log);
725 if (host == NULL) {
726 return NGX_ERROR;
727 }
728
729 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
730
731 /* AF_INET only */ 908 /* AF_INET only */
732 909
733 port = htons(u->port); 910 port = htons(u->port);
734 911
735 in_addr = inet_addr((char *) host); 912 in_addr = ngx_inet_addr(u->host.data, u->host.len);
736 913
737 if (in_addr == INADDR_NONE) { 914 if (in_addr == INADDR_NONE) {
915 host = ngx_alloc(u->host.len + 1, pool->log);
916 if (host == NULL) {
917 return NGX_ERROR;
918 }
919
920 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
921
738 h = gethostbyname((char *) host); 922 h = gethostbyname((char *) host);
739 923
740 ngx_free(host); 924 ngx_free(host);
741 925
742 if (h == NULL || h->h_addr_list[0] == NULL) { 926 if (h == NULL || h->h_addr_list[0] == NULL) {
751 i = 1; 935 i = 1;
752 } 936 }
753 937
754 /* MP: ngx_shared_palloc() */ 938 /* MP: ngx_shared_palloc() */
755 939
756 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t)); 940 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
757 if (u->addrs == NULL) { 941 if (u->addrs == NULL) {
758 return NGX_ERROR; 942 return NGX_ERROR;
759 } 943 }
760 944
761 u->naddrs = i; 945 u->naddrs = i;
787 u->addrs[i].name.data = p; 971 u->addrs[i].name.data = p;
788 } 972 }
789 973
790 } else { 974 } else {
791 975
792 ngx_free(host);
793
794 /* MP: ngx_shared_palloc() */ 976 /* MP: ngx_shared_palloc() */
795 977
796 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); 978 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
797 if (u->addrs == NULL) { 979 if (u->addrs == NULL) {
798 return NGX_ERROR; 980 return NGX_ERROR;
799 } 981 }
800 982
801 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); 983 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));