comparison src/core/ngx_inet.c @ 448:76a79816b771 NGINX_0_7_36

nginx 0.7.36 *) Feature: a preliminary IPv6 support; the "listen" directive of the HTTP module supports IPv6. *) Bugfix: the $ancient_browser variable did not work for browsers preset by a "modern_browser" directives.
author Igor Sysoev <http://sysoev.ru>
date Sat, 21 Feb 2009 00:00:00 +0300
parents ff86d646f9df
children 20962db0117c
comparison
equal deleted inserted replaced
447:40964c811e59 448:76a79816b771
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 }