Mercurial > hg > nginx-ranges
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)); |