Mercurial > hg > nginx-mail
comparison src/core/ngx_inet.c @ 583: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
582:c88014f74832 | 583: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)); |