Mercurial > hg > nginx
comparison src/core/ngx_inet.c @ 2512:2e91aecb9e57
a prelimiary IPv6 support, HTTP listen
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 21 Feb 2009 07:02:02 +0000 |
parents | 148c2e840c2b |
children | 095f28fc0c4a |
comparison
equal
deleted
inserted
replaced
2511:f91c5c964e61 | 2512:2e91aecb9e57 |
---|---|
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 | |
11 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); | 14 static ngx_int_t ngx_parse_unix_domain_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); | 15 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); |
13 | 16 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); |
14 | 17 |
15 /* AF_INET only */ | |
16 | 18 |
17 in_addr_t | 19 in_addr_t |
18 ngx_inet_addr(u_char *text, size_t len) | 20 ngx_inet_addr(u_char *text, size_t len) |
19 { | 21 { |
20 u_char *p, c; | 22 u_char *p, c; |
55 | 57 |
56 return INADDR_NONE; | 58 return INADDR_NONE; |
57 } | 59 } |
58 | 60 |
59 | 61 |
60 /* AF_INET only */ | |
61 | |
62 size_t | 62 size_t |
63 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len) | 63 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port) |
64 { | 64 { |
65 u_char *p; | 65 u_char *p; |
66 struct sockaddr_in *sin; | 66 struct sockaddr_in *sin; |
67 | 67 #if (NGX_HAVE_INET6) |
68 if (sa->sa_family == AF_INET) { | 68 size_t n; |
69 struct sockaddr_in6 *sin6; | |
70 #endif | |
71 | |
72 switch (sa->sa_family) { | |
73 | |
74 case AF_INET: | |
69 | 75 |
70 sin = (struct sockaddr_in *) sa; | 76 sin = (struct sockaddr_in *) sa; |
71 p = (u_char *) &sin->sin_addr; | 77 p = (u_char *) &sin->sin_addr; |
78 | |
79 if (port) { | |
80 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d", | |
81 p[0], p[1], p[2], p[3], ntohs(sin->sin_port)); | |
82 } else { | |
83 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud", | |
84 p[0], p[1], p[2], p[3]); | |
85 } | |
86 | |
87 return (p - text); | |
88 | |
89 #if (NGX_HAVE_INET6) | |
90 | |
91 case AF_INET6: | |
92 | |
93 sin6 = (struct sockaddr_in6 *) sa; | |
94 | |
95 n = 0; | |
96 | |
97 if (port) { | |
98 text[n++] = '['; | |
99 } | |
100 | |
101 n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len); | |
102 | |
103 if (port) { | |
104 n = ngx_sprintf(&text[1 + n], "]:%d", | |
105 ntohs(sin6->sin6_port)) - text; | |
106 } | |
107 | |
108 return n; | |
109 #endif | |
110 | |
111 default: | |
112 return 0; | |
113 } | |
114 } | |
115 | |
116 | |
117 size_t | |
118 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len) | |
119 { | |
120 u_char *p; | |
121 | |
122 switch (family) { | |
123 | |
124 case AF_INET: | |
125 | |
126 p = addr; | |
72 | 127 |
73 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud", | 128 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud", |
74 p[0], p[1], p[2], p[3]) | 129 p[0], p[1], p[2], p[3]) |
75 - text; | 130 - text; |
76 } | 131 |
77 | 132 #if (NGX_HAVE_INET6) |
78 return 0; | 133 |
79 } | 134 case AF_INET6: |
80 | 135 return ngx_inet6_ntop(addr, text, len); |
81 | 136 |
82 size_t | 137 #endif |
83 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len) | 138 |
84 { | 139 default: |
85 u_char *p; | 140 return 0; |
86 | 141 } |
87 if (family == AF_INET) { | 142 } |
88 | 143 |
89 p = (u_char *) addr; | 144 |
90 | 145 #if (NGX_HAVE_INET6) |
91 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud", | 146 |
92 p[0], p[1], p[2], p[3]) | 147 static size_t |
93 - text; | 148 ngx_inet6_ntop(u_char *p, u_char *text, size_t len) |
94 } | 149 { |
95 | 150 u_char *dst; |
96 return 0; | 151 size_t max, n; |
97 } | 152 ngx_uint_t i, zero, last; |
153 | |
154 if (len < NGX_INET6_ADDRSTRLEN) { | |
155 return 0; | |
156 } | |
157 | |
158 zero = (ngx_uint_t) -1; | |
159 last = (ngx_uint_t) -1; | |
160 max = 1; | |
161 n = 0; | |
162 | |
163 for (i = 0; i < 16; i += 2) { | |
164 | |
165 if (p[i] || p[i + 1]) { | |
166 | |
167 if (max < n) { | |
168 zero = last; | |
169 max = n; | |
170 } | |
171 | |
172 n = 0; | |
173 continue; | |
174 } | |
175 | |
176 if (n++ == 0) { | |
177 last = i; | |
178 } | |
179 } | |
180 | |
181 if (max < n) { | |
182 zero = last; | |
183 max = n; | |
184 } | |
185 | |
186 dst = text; | |
187 n = 16; | |
188 | |
189 if (zero == 0) { | |
190 | |
191 if ((max == 5 && p[10] == 0xff && p[11] == 0xff) | |
192 || (max == 6) | |
193 || (max == 7 && p[14] != 0 && p[15] != 1)) | |
194 { | |
195 n = 12; | |
196 } | |
197 | |
198 *dst++ = ':'; | |
199 } | |
200 | |
201 for (i = 0; i < n; i += 2) { | |
202 | |
203 if (i == zero) { | |
204 *dst++ = ':'; | |
205 i += (max - 1) * 2; | |
206 continue; | |
207 } | |
208 | |
209 dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]); | |
210 | |
211 if (i < 14) { | |
212 *dst++ = ':'; | |
213 } | |
214 } | |
215 | |
216 if (n == 12) { | |
217 dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]); | |
218 } | |
219 | |
220 return dst - text; | |
221 } | |
222 | |
223 #endif | |
98 | 224 |
99 | 225 |
100 /* AF_INET only */ | 226 /* AF_INET only */ |
101 | 227 |
102 ngx_int_t | 228 ngx_int_t |
167 } | 293 } |
168 | 294 |
169 if ((p[0] == ':' || p[0] == '/') && !u->listen) { | 295 if ((p[0] == ':' || p[0] == '/') && !u->listen) { |
170 u->err = "invalid host"; | 296 u->err = "invalid host"; |
171 return NGX_ERROR; | 297 return NGX_ERROR; |
298 } | |
299 | |
300 if (p[0] == '[') { | |
301 return ngx_parse_inet6_url(pool, u); | |
172 } | 302 } |
173 | 303 |
174 return ngx_parse_inet_url(pool, u); | 304 return ngx_parse_inet_url(pool, u); |
175 } | 305 } |
176 | 306 |
207 return NGX_ERROR; | 337 return NGX_ERROR; |
208 } | 338 } |
209 | 339 |
210 u->host.len = len++; | 340 u->host.len = len++; |
211 u->host.data = path; | 341 u->host.data = path; |
212 u->family = AF_UNIX; | |
213 | 342 |
214 if (len > sizeof(saun->sun_path)) { | 343 if (len > sizeof(saun->sun_path)) { |
215 u->err = "too long path in the unix domain socket"; | 344 u->err = "too long path in the unix domain socket"; |
216 return NGX_ERROR; | 345 return NGX_ERROR; |
217 } | 346 } |
218 | 347 |
348 u->socklen = sizeof(struct sockaddr_un); | |
349 saun = (struct sockaddr_un *) &u->sockaddr; | |
350 saun->sun_family = AF_UNIX; | |
351 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); | |
352 | |
219 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); | 353 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); |
220 if (u->addrs == NULL) { | 354 if (u->addrs == NULL) { |
221 return NGX_ERROR; | 355 return NGX_ERROR; |
222 } | 356 } |
223 | 357 |
224 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un)); | 358 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un)); |
225 if (saun == NULL) { | 359 if (saun == NULL) { |
226 return NGX_ERROR; | 360 return NGX_ERROR; |
227 } | 361 } |
228 | 362 |
363 u->family = AF_UNIX; | |
229 u->naddrs = 1; | 364 u->naddrs = 1; |
230 | 365 |
231 saun->sun_family = AF_UNIX; | 366 saun->sun_family = AF_UNIX; |
232 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); | 367 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); |
233 | 368 |
249 | 384 |
250 | 385 |
251 static ngx_int_t | 386 static ngx_int_t |
252 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) | 387 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) |
253 { | 388 { |
254 u_char *p, *host, *port, *last, *uri, *args; | 389 u_char *p, *host, *port, *last, *uri, *args; |
255 size_t len; | 390 size_t len; |
256 ngx_int_t n; | 391 ngx_int_t n; |
257 struct hostent *h; | 392 struct hostent *h; |
393 struct sockaddr_in *sin; | |
394 | |
395 u->socklen = sizeof(struct sockaddr_in); | |
396 sin = (struct sockaddr_in *) &u->sockaddr; | |
397 sin->sin_family = AF_INET; | |
258 | 398 |
259 u->family = AF_INET; | 399 u->family = AF_INET; |
260 | 400 |
261 host = u->url.data; | 401 host = u->url.data; |
262 | 402 |
309 u->err = "invalid port"; | 449 u->err = "invalid port"; |
310 return NGX_ERROR; | 450 return NGX_ERROR; |
311 } | 451 } |
312 | 452 |
313 u->port = (in_port_t) n; | 453 u->port = (in_port_t) n; |
454 sin->sin_port = htons((in_port_t) n); | |
314 | 455 |
315 u->port_text.len = len; | 456 u->port_text.len = len; |
316 u->port_text.data = port; | 457 u->port_text.data = port; |
317 | 458 |
318 last = port - 1; | 459 last = port - 1; |
332 u->err = "invalid port"; | 473 u->err = "invalid port"; |
333 return NGX_ERROR; | 474 return NGX_ERROR; |
334 } | 475 } |
335 | 476 |
336 u->port = (in_port_t) n; | 477 u->port = (in_port_t) n; |
478 sin->sin_port = htons((in_port_t) n); | |
337 | 479 |
338 u->port_text.len = last - host; | 480 u->port_text.len = last - host; |
339 u->port_text.data = host; | 481 u->port_text.data = host; |
482 | |
483 u->wildcard = 1; | |
340 | 484 |
341 return NGX_OK; | 485 return NGX_OK; |
342 } | 486 } |
343 } | 487 } |
344 } | 488 } |
372 } | 516 } |
373 | 517 |
374 (void) ngx_cpystrn(p, host, len); | 518 (void) ngx_cpystrn(p, host, len); |
375 | 519 |
376 u->addr.in_addr = inet_addr((const char *) p); | 520 u->addr.in_addr = inet_addr((const char *) p); |
377 | 521 sin->sin_addr.s_addr = inet_addr((const char *) p); |
378 if (u->addr.in_addr == INADDR_NONE) { | 522 |
523 if (sin->sin_addr.s_addr == INADDR_NONE) { | |
379 h = gethostbyname((const char *) p); | 524 h = gethostbyname((const char *) p); |
380 | 525 |
381 if (h == NULL || h->h_addr_list[0] == NULL) { | 526 if (h == NULL || h->h_addr_list[0] == NULL) { |
382 ngx_free(p); | 527 ngx_free(p); |
383 u->err = "host not found"; | 528 u->err = "host not found"; |
384 return NGX_ERROR; | 529 return NGX_ERROR; |
385 } | 530 } |
386 | 531 |
387 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]); | 532 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]); |
533 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]); | |
534 } | |
535 | |
536 if (sin->sin_addr.s_addr == INADDR_ANY) { | |
537 u->wildcard = 1; | |
388 } | 538 } |
389 | 539 |
390 ngx_free(p); | 540 ngx_free(p); |
391 | 541 |
392 } else { | 542 } else { |
393 u->addr.in_addr = INADDR_ANY; | 543 u->addr.in_addr = INADDR_ANY; |
544 sin->sin_addr.s_addr = INADDR_ANY; | |
545 u->wildcard = 1; | |
394 } | 546 } |
395 | 547 |
396 if (u->no_port) { | 548 if (u->no_port) { |
397 u->port = u->default_port; | 549 u->port = u->default_port; |
550 sin->sin_port = htons(u->default_port); | |
398 } | 551 } |
399 | 552 |
400 if (u->listen) { | 553 if (u->listen) { |
401 return NGX_OK; | 554 return NGX_OK; |
402 } | 555 } |
407 | 560 |
408 return NGX_OK; | 561 return NGX_OK; |
409 } | 562 } |
410 | 563 |
411 | 564 |
565 static ngx_int_t | |
566 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) | |
567 { | |
568 #if (NGX_HAVE_INET6) | |
569 int rc; | |
570 u_char *p, *host, *port, *last, *uri; | |
571 size_t len; | |
572 ngx_int_t n; | |
573 struct sockaddr_in6 *sin6; | |
574 | |
575 u->socklen = sizeof(struct sockaddr_in6); | |
576 sin6 = (struct sockaddr_in6 *) &u->sockaddr; | |
577 sin6->sin6_family = AF_INET6; | |
578 | |
579 host = u->url.data + 1; | |
580 | |
581 last = u->url.data + u->url.len; | |
582 | |
583 p = ngx_strlchr(host, last, ']'); | |
584 | |
585 if (p == NULL) { | |
586 u->err = "invalid host"; | |
587 return NGX_ERROR; | |
588 } | |
589 | |
590 if (last - p) { | |
591 | |
592 port = p + 1; | |
593 | |
594 uri = ngx_strlchr(port, last, '/'); | |
595 | |
596 if (uri) { | |
597 if (u->listen || !u->uri_part) { | |
598 u->err = "invalid host"; | |
599 return NGX_ERROR; | |
600 } | |
601 | |
602 u->uri.len = last - uri; | |
603 u->uri.data = uri; | |
604 } | |
605 | |
606 if (*port == ':') { | |
607 port++; | |
608 | |
609 len = last - port; | |
610 | |
611 if (len == 0) { | |
612 u->err = "invalid port"; | |
613 return NGX_ERROR; | |
614 } | |
615 | |
616 n = ngx_atoi(port, len); | |
617 | |
618 if (n < 1 || n > 65536) { | |
619 u->err = "invalid port"; | |
620 return NGX_ERROR; | |
621 } | |
622 | |
623 u->port = (in_port_t) n; | |
624 sin6->sin6_port = htons((in_port_t) n); | |
625 | |
626 u->port_text.len = len; | |
627 u->port_text.data = port; | |
628 | |
629 } else { | |
630 u->no_port = 1; | |
631 } | |
632 } | |
633 | |
634 len = p - host; | |
635 | |
636 if (len == 0) { | |
637 u->err = "no host"; | |
638 return NGX_ERROR; | |
639 } | |
640 | |
641 u->host.len = len++; | |
642 u->host.data = host; | |
643 | |
644 p = ngx_alloc(len, pool->log); | |
645 if (p == NULL) { | |
646 return NGX_ERROR; | |
647 } | |
648 | |
649 (void) ngx_cpystrn(p, host, len); | |
650 | |
651 rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr); | |
652 | |
653 ngx_free(p); | |
654 | |
655 if (rc == 0) { | |
656 u->err = "invalid IPv6 address"; | |
657 return NGX_ERROR; | |
658 } | |
659 | |
660 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | |
661 u->wildcard = 1; | |
662 } | |
663 | |
664 u->family = AF_INET6; | |
665 | |
666 if (u->no_resolve) { | |
667 return NGX_OK; | |
668 } | |
669 | |
670 if (u->no_port) { | |
671 u->port = u->default_port; | |
672 sin6->sin6_port = htons(u->default_port); | |
673 } | |
674 | |
675 return NGX_OK; | |
676 | |
677 #else | |
678 | |
679 u->err = "the INET6 sockets are not supported on this platform"; | |
680 | |
681 return NGX_ERROR; | |
682 | |
683 #endif | |
684 } | |
685 | |
686 | |
412 ngx_int_t | 687 ngx_int_t |
413 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) | 688 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) |
414 { | 689 { |
415 u_char *p, *host; | 690 u_char *p, *host; |
416 size_t len; | 691 size_t len; |
692 in_port_t port; | |
417 in_addr_t in_addr; | 693 in_addr_t in_addr; |
418 ngx_uint_t i; | 694 ngx_uint_t i; |
419 struct hostent *h; | 695 struct hostent *h; |
420 struct sockaddr_in *sin; | 696 struct sockaddr_in *sin; |
421 | 697 |
426 | 702 |
427 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1); | 703 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1); |
428 | 704 |
429 /* AF_INET only */ | 705 /* AF_INET only */ |
430 | 706 |
707 sin = (struct sockaddr_in *) &u->sockaddr; | |
708 port = sin->sin_port; | |
709 | |
431 in_addr = inet_addr((char *) host); | 710 in_addr = inet_addr((char *) host); |
432 | 711 |
433 if (in_addr == INADDR_NONE) { | 712 if (in_addr == INADDR_NONE) { |
434 h = gethostbyname((char *) host); | 713 h = gethostbyname((char *) host); |
435 | 714 |
462 if (sin == NULL) { | 741 if (sin == NULL) { |
463 return NGX_ERROR; | 742 return NGX_ERROR; |
464 } | 743 } |
465 | 744 |
466 sin->sin_family = AF_INET; | 745 sin->sin_family = AF_INET; |
467 sin->sin_port = htons(u->port); | 746 sin->sin_port = port; |
468 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); | 747 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); |
469 | 748 |
470 u->addrs[i].sockaddr = (struct sockaddr *) sin; | 749 u->addrs[i].sockaddr = (struct sockaddr *) sin; |
471 u->addrs[i].socklen = sizeof(struct sockaddr_in); | 750 u->addrs[i].socklen = sizeof(struct sockaddr_in); |
472 | 751 |
473 len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1; | 752 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; |
474 | 753 |
475 p = ngx_pnalloc(pool, len); | 754 p = ngx_pnalloc(pool, len); |
476 if (p == NULL) { | 755 if (p == NULL) { |
477 return NGX_ERROR; | 756 return NGX_ERROR; |
478 } | 757 } |
479 | 758 |
480 len = ngx_sock_ntop((struct sockaddr *) sin, p, len); | 759 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1); |
481 | 760 |
482 u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p; | 761 u->addrs[i].name.len = len; |
483 u->addrs[i].name.data = p; | 762 u->addrs[i].name.data = p; |
484 } | 763 } |
485 | 764 |
486 } else { | 765 } else { |
487 | 766 |
500 } | 779 } |
501 | 780 |
502 u->naddrs = 1; | 781 u->naddrs = 1; |
503 | 782 |
504 sin->sin_family = AF_INET; | 783 sin->sin_family = AF_INET; |
505 sin->sin_port = htons(u->port); | 784 sin->sin_port = port; |
506 sin->sin_addr.s_addr = in_addr; | 785 sin->sin_addr.s_addr = in_addr; |
507 | 786 |
508 u->addrs[0].sockaddr = (struct sockaddr *) sin; | 787 u->addrs[0].sockaddr = (struct sockaddr *) sin; |
509 u->addrs[0].socklen = sizeof(struct sockaddr_in); | 788 u->addrs[0].socklen = sizeof(struct sockaddr_in); |
510 | 789 |
511 p = ngx_pnalloc(pool, u->host.len + sizeof(":65536") - 1); | 790 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); |
512 if (p == NULL) { | 791 if (p == NULL) { |
513 return NGX_ERROR; | 792 return NGX_ERROR; |
514 } | 793 } |
515 | 794 |
516 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p; | 795 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", |
796 &u->host, ntohs(port)) - p; | |
517 u->addrs[0].name.data = p; | 797 u->addrs[0].name.data = p; |
518 } | 798 } |
519 | 799 |
520 return NGX_OK; | 800 return NGX_OK; |
521 } | 801 } |