blob: 91c7ef0811df0b9a7a165a724127ae88af27ae93 [file] [log] [blame]
Igor Sysoev42feecb2002-12-15 06:25:09 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev42feecb2002-12-15 06:25:09 +00007#include <ngx_config.h>
Igor Sysoev1c104622003-06-03 15:42:58 +00008#include <ngx_core.h>
Igor Sysoev42feecb2002-12-15 06:25:09 +00009
10
Igor Sysoev154013c2008-08-22 13:36:56 +000011static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
12static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
Igor Sysoeva35eacc2009-02-21 07:02:02 +000013static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
Igor Sysoev154013c2008-08-22 13:36:56 +000014
15
Igor Sysoev36b634c2007-11-23 16:59:24 +000016in_addr_t
17ngx_inet_addr(u_char *text, size_t len)
18{
19 u_char *p, c;
20 in_addr_t addr;
21 ngx_uint_t octet, n;
22
23 addr = 0;
24 octet = 0;
25 n = 0;
26
27 for (p = text; p < text + len; p++) {
28
29 c = *p;
30
31 if (c >= '0' && c <= '9') {
32 octet = octet * 10 + (c - '0');
33 continue;
34 }
35
36 if (c == '.' && octet < 256) {
37 addr = (addr << 8) + octet;
38 octet = 0;
39 n++;
40 continue;
41 }
42
43 return INADDR_NONE;
44 }
45
46 if (n != 3) {
47 return INADDR_NONE;
48 }
49
50 if (octet < 256) {
51 addr = (addr << 8) + octet;
52 return htonl(addr);
53 }
54
55 return INADDR_NONE;
56}
57
58
Igor Sysoev5a76cbb2009-11-02 12:50:00 +000059#if (NGX_HAVE_INET6)
60
61ngx_int_t
62ngx_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
Igor Sysoev899b44e2005-05-12 14:58:06 +0000179size_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000180ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000181{
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000182 u_char *p;
183 struct sockaddr_in *sin;
184#if (NGX_HAVE_INET6)
185 size_t n;
186 struct sockaddr_in6 *sin6;
187#endif
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000188#if (NGX_HAVE_UNIX_DOMAIN)
189 struct sockaddr_un *saun;
190#endif
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000191
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000192 switch (sa->sa_family) {
193
194 case AF_INET:
Igor Sysoev6a750192008-08-21 18:47:23 +0000195
196 sin = (struct sockaddr_in *) sa;
197 p = (u_char *) &sin->sin_addr;
198
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000199 if (port) {
200 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
201 p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
202 } else {
203 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
204 p[0], p[1], p[2], p[3]);
205 }
Igor Sysoev9c610952004-03-16 13:35:20 +0000206
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000207 return (p - text);
208
209#if (NGX_HAVE_INET6)
210
211 case AF_INET6:
212
213 sin6 = (struct sockaddr_in6 *) sa;
214
215 n = 0;
216
217 if (port) {
218 text[n++] = '[';
219 }
220
Igor Sysoev67765e82009-11-02 14:32:46 +0000221 n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000222
223 if (port) {
224 n = ngx_sprintf(&text[1 + n], "]:%d",
225 ntohs(sin6->sin6_port)) - text;
226 }
227
228 return n;
229#endif
230
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000231#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
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000242 default:
243 return 0;
244 }
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000245}
246
Igor Sysoev02729772008-01-04 11:54:55 +0000247
Igor Sysoev899b44e2005-05-12 14:58:06 +0000248size_t
249ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
Igor Sysoev42feecb2002-12-15 06:25:09 +0000250{
Igor Sysoev6a750192008-08-21 18:47:23 +0000251 u_char *p;
Igor Sysoev9c610952004-03-16 13:35:20 +0000252
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000253 switch (family) {
Igor Sysoev6a750192008-08-21 18:47:23 +0000254
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000255 case AF_INET:
256
257 p = addr;
Igor Sysoev6a750192008-08-21 18:47:23 +0000258
259 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
260 p[0], p[1], p[2], p[3])
261 - text;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000262
263#if (NGX_HAVE_INET6)
264
265 case AF_INET6:
266 return ngx_inet6_ntop(addr, text, len);
267
268#endif
269
270 default:
271 return 0;
272 }
273}
274
275
276#if (NGX_HAVE_INET6)
277
Igor Sysoevfd078fd2009-11-03 12:44:55 +0000278size_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000279ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
280{
281 u_char *dst;
282 size_t max, n;
283 ngx_uint_t i, zero, last;
284
285 if (len < NGX_INET6_ADDRSTRLEN) {
286 return 0;
Igor Sysoev9c610952004-03-16 13:35:20 +0000287 }
288
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000289 zero = (ngx_uint_t) -1;
290 last = (ngx_uint_t) -1;
291 max = 1;
292 n = 0;
293
294 for (i = 0; i < 16; i += 2) {
295
296 if (p[i] || p[i + 1]) {
297
298 if (max < n) {
299 zero = last;
300 max = n;
301 }
302
303 n = 0;
304 continue;
305 }
306
307 if (n++ == 0) {
308 last = i;
309 }
310 }
311
312 if (max < n) {
313 zero = last;
314 max = n;
315 }
316
317 dst = text;
318 n = 16;
319
320 if (zero == 0) {
321
322 if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
323 || (max == 6)
324 || (max == 7 && p[14] != 0 && p[15] != 1))
325 {
326 n = 12;
327 }
328
329 *dst++ = ':';
330 }
331
332 for (i = 0; i < n; i += 2) {
333
334 if (i == zero) {
335 *dst++ = ':';
336 i += (max - 1) * 2;
337 continue;
338 }
339
340 dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
341
342 if (i < 14) {
343 *dst++ = ':';
344 }
345 }
346
347 if (n == 12) {
348 dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
349 }
350
351 return dst - text;
Igor Sysoev02729772008-01-04 11:54:55 +0000352}
353
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000354#endif
355
Igor Sysoev02729772008-01-04 11:54:55 +0000356
Igor Sysoev899b44e2005-05-12 14:58:06 +0000357ngx_int_t
Igor Sysoev36860102009-02-24 14:01:40 +0000358ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
Igor Sysoev822834e2004-05-25 15:28:46 +0000359{
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000360 u_char *addr, *mask, *last;
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
Igor Sysoev822834e2004-05-25 15:28:46 +0000367
Igor Sysoev9c388c02008-08-26 14:19:37 +0000368 addr = text->data;
369 last = addr + text->len;
Igor Sysoev822834e2004-05-25 15:28:46 +0000370
Igor Sysoev9c388c02008-08-26 14:19:37 +0000371 mask = ngx_strlchr(addr, last, '/');
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000372 len = (mask ? mask : last) - addr;
Igor Sysoev822834e2004-05-25 15:28:46 +0000373
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000374 cidr->u.in.addr = ngx_inet_addr(addr, len);
Igor Sysoev822834e2004-05-25 15:28:46 +0000375
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000376 if (cidr->u.in.addr != INADDR_NONE) {
Igor Sysoev36860102009-02-24 14:01:40 +0000377 cidr->family = AF_INET;
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000378
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;
Igor Sysoev9c388c02008-08-26 14:19:37 +0000396 }
397
398 mask++;
399
400 shift = ngx_atoi(mask, last - mask);
401 if (shift == NGX_ERROR) {
Igor Sysoev822834e2004-05-25 15:28:46 +0000402 return NGX_ERROR;
403 }
404
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000405 switch (cidr->family) {
Igor Sysoev36860102009-02-24 14:01:40 +0000406
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000407#if (NGX_HAVE_INET6)
408 case AF_INET6:
409 addr = cidr->u.in6.addr.s6_addr;
410 mask = cidr->u.in6.mask.s6_addr;
411 rc = NGX_OK;
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000412
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000413 for (i = 0; i < 16; i++) {
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000414
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000415 s = (shift > 8) ? 8 : shift;
416 shift -= s;
Igor Sysoev9c388c02008-08-26 14:19:37 +0000417
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000418 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)) {
Igor Sysoev9c388c02008-08-26 14:19:37 +0000440 return NGX_OK;
441 }
442
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000443 cidr->u.in.addr &= cidr->u.in.mask;
444
Igor Sysoev9c388c02008-08-26 14:19:37 +0000445 return NGX_DONE;
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000446 }
Igor Sysoev822834e2004-05-25 15:28:46 +0000447}
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000448
449
Igor Sysoev8b816d82009-11-02 16:11:06 +0000450ngx_int_t
451ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000452{
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000453 in_addr_t inaddr;
454 ngx_uint_t family;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000455 struct sockaddr_in *sin;
456#if (NGX_HAVE_INET6)
457 struct in6_addr inaddr6;
458 struct sockaddr_in6 *sin6;
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000459
460 /*
461 * prevent MSVC8 waring:
462 * potentially uninitialized local variable 'inaddr6' used
463 */
464 ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000465#endif
466
Igor Sysoev8b816d82009-11-02 16:11:06 +0000467 inaddr = ngx_inet_addr(text, len);
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000468
469 if (inaddr != INADDR_NONE) {
470 family = AF_INET;
471 len = sizeof(struct sockaddr_in);
472
473#if (NGX_HAVE_INET6)
Igor Sysoev8b816d82009-11-02 16:11:06 +0000474 } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000475 family = AF_INET6;
476 len = sizeof(struct sockaddr_in6);
477
478#endif
479 } else {
Igor Sysoev8b816d82009-11-02 16:11:06 +0000480 return NGX_DECLINED;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000481 }
482
Igor Sysoev8b816d82009-11-02 16:11:06 +0000483 addr->sockaddr = ngx_pcalloc(pool, len);
484 if (addr->sockaddr == NULL) {
485 return NGX_ERROR;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000486 }
487
Igor Sysoev8b816d82009-11-02 16:11:06 +0000488 addr->sockaddr->sa_family = (u_char) family;
489 addr->socklen = len;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000490
491 switch (family) {
492
493#if (NGX_HAVE_INET6)
494 case AF_INET6:
Igor Sysoev8b816d82009-11-02 16:11:06 +0000495 sin6 = (struct sockaddr_in6 *) addr->sockaddr;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000496 ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
497 break;
498#endif
499
500 default: /* AF_INET */
Igor Sysoev8b816d82009-11-02 16:11:06 +0000501 sin = (struct sockaddr_in *) addr->sockaddr;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000502 sin->sin_addr.s_addr = inaddr;
503 break;
504 }
505
Igor Sysoev8b816d82009-11-02 16:11:06 +0000506 return NGX_OK;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000507}
508
509
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000510ngx_int_t
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000511ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000512{
Igor Sysoev154013c2008-08-22 13:36:56 +0000513 u_char *p;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000514
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000515 p = u->url.data;
516
Igor Sysoev722231f2007-02-14 18:51:19 +0000517 if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
Igor Sysoev154013c2008-08-22 13:36:56 +0000518 return ngx_parse_unix_domain_url(pool, u);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000519 }
520
521 if ((p[0] == ':' || p[0] == '/') && !u->listen) {
522 u->err = "invalid host";
523 return NGX_ERROR;
524 }
525
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000526 if (p[0] == '[') {
527 return ngx_parse_inet6_url(pool, u);
528 }
529
Igor Sysoev154013c2008-08-22 13:36:56 +0000530 return ngx_parse_inet_url(pool, u);
531}
532
533
534static ngx_int_t
535ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
536{
537#if (NGX_HAVE_UNIX_DOMAIN)
Igor Sysoevc9491d12008-08-26 14:24:14 +0000538 u_char *path, *uri, *last;
Igor Sysoev154013c2008-08-22 13:36:56 +0000539 size_t len;
Igor Sysoev154013c2008-08-22 13:36:56 +0000540 struct sockaddr_un *saun;
541
542 len = u->url.len;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000543 path = u->url.data;
Igor Sysoev154013c2008-08-22 13:36:56 +0000544
Igor Sysoevc9491d12008-08-26 14:24:14 +0000545 path += 5;
Igor Sysoev154013c2008-08-22 13:36:56 +0000546 len -= 5;
547
Igor Sysoev154013c2008-08-22 13:36:56 +0000548 if (u->uri_part) {
Igor Sysoev154013c2008-08-22 13:36:56 +0000549
Igor Sysoevc9491d12008-08-26 14:24:14 +0000550 last = path + len;
551 uri = ngx_strlchr(path, last, ':');
Igor Sysoev154013c2008-08-22 13:36:56 +0000552
Igor Sysoevc9491d12008-08-26 14:24:14 +0000553 if (uri) {
554 len = uri - path;
555 uri++;
556 u->uri.len = last - uri;
557 u->uri.data = uri;
Igor Sysoev154013c2008-08-22 13:36:56 +0000558 }
559 }
560
561 if (len == 0) {
562 u->err = "no path in the unix domain socket";
563 return NGX_ERROR;
564 }
565
Igor Sysoevc9491d12008-08-26 14:24:14 +0000566 u->host.len = len++;
567 u->host.data = path;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000568
569 if (len > sizeof(saun->sun_path)) {
Igor Sysoev154013c2008-08-22 13:36:56 +0000570 u->err = "too long path in the unix domain socket";
571 return NGX_ERROR;
572 }
573
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000574 u->socklen = sizeof(struct sockaddr_un);
575 saun = (struct sockaddr_un *) &u->sockaddr;
576 saun->sun_family = AF_UNIX;
577 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
578
Igor Sysoev0c189c52009-11-02 15:14:17 +0000579 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
Igor Sysoev154013c2008-08-22 13:36:56 +0000580 if (u->addrs == NULL) {
581 return NGX_ERROR;
582 }
583
584 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
585 if (saun == NULL) {
586 return NGX_ERROR;
587 }
588
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000589 u->family = AF_UNIX;
Igor Sysoev154013c2008-08-22 13:36:56 +0000590 u->naddrs = 1;
591
592 saun->sun_family = AF_UNIX;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000593 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
Igor Sysoev154013c2008-08-22 13:36:56 +0000594
595 u->addrs[0].sockaddr = (struct sockaddr *) saun;
596 u->addrs[0].socklen = sizeof(struct sockaddr_un);
Igor Sysoevc9491d12008-08-26 14:24:14 +0000597 u->addrs[0].name.len = len + 4;
Igor Sysoev154013c2008-08-22 13:36:56 +0000598 u->addrs[0].name.data = u->url.data;
599
Igor Sysoev154013c2008-08-22 13:36:56 +0000600 return NGX_OK;
601
602#else
603
604 u->err = "the unix domain sockets are not supported on this platform";
605
606 return NGX_ERROR;
607
608#endif
609}
610
611
612static ngx_int_t
613ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
614{
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000615 u_char *p, *host, *port, *last, *uri, *args;
616 size_t len;
617 ngx_int_t n;
618 struct hostent *h;
619 struct sockaddr_in *sin;
620
621 u->socklen = sizeof(struct sockaddr_in);
622 sin = (struct sockaddr_in *) &u->sockaddr;
623 sin->sin_family = AF_INET;
Igor Sysoev154013c2008-08-22 13:36:56 +0000624
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000625 u->family = AF_INET;
626
Igor Sysoevc9491d12008-08-26 14:24:14 +0000627 host = u->url.data;
Igor Sysoev154013c2008-08-22 13:36:56 +0000628
Igor Sysoevc9491d12008-08-26 14:24:14 +0000629 last = host + u->url.len;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000630
Igor Sysoevc9491d12008-08-26 14:24:14 +0000631 port = ngx_strlchr(host, last, ':');
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000632
Igor Sysoevc239da52008-10-24 15:12:11 +0000633 uri = ngx_strlchr(host, last, '/');
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000634
Igor Sysoev164abfb2008-10-24 19:34:24 +0000635 args = ngx_strlchr(host, last, '?');
636
637 if (args) {
638 if (uri == NULL) {
639 uri = args;
640
641 } else if (args < uri) {
642 uri = args;
643 }
644 }
645
Igor Sysoevc9491d12008-08-26 14:24:14 +0000646 if (uri) {
647 if (u->listen || !u->uri_part) {
648 u->err = "invalid host";
649 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000650 }
651
Igor Sysoevc9491d12008-08-26 14:24:14 +0000652 u->uri.len = last - uri;
653 u->uri.data = uri;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000654
Igor Sysoevc9491d12008-08-26 14:24:14 +0000655 last = uri;
Igor Sysoevc239da52008-10-24 15:12:11 +0000656
657 if (uri < port) {
658 port = NULL;
Igor Sysoevead80912008-11-11 16:04:05 +0000659 }
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000660 }
661
Igor Sysoevc9491d12008-08-26 14:24:14 +0000662 if (port) {
663 port++;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000664
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000665 len = last - port;
666
667 if (len == 0) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000668 u->err = "invalid port";
669 return NGX_ERROR;
670 }
671
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000672 n = ngx_atoi(port, len);
673
674 if (n < 1 || n > 65536) {
675 u->err = "invalid port";
676 return NGX_ERROR;
677 }
678
679 u->port = (in_port_t) n;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000680 sin->sin_port = htons((in_port_t) n);
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000681
682 u->port_text.len = len;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000683 u->port_text.data = port;
684
685 last = port - 1;
Igor Sysoev00e03772007-11-28 19:55:31 +0000686
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000687 } else {
Igor Sysoevc9491d12008-08-26 14:24:14 +0000688 if (uri == NULL) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000689
Igor Sysoevc9491d12008-08-26 14:24:14 +0000690 if (u->listen) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000691
Igor Sysoevc9491d12008-08-26 14:24:14 +0000692 /* test value as port only */
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000693
Igor Sysoevc9491d12008-08-26 14:24:14 +0000694 n = ngx_atoi(host, last - host);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000695
Igor Sysoevc9491d12008-08-26 14:24:14 +0000696 if (n != NGX_ERROR) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000697
Igor Sysoevc9491d12008-08-26 14:24:14 +0000698 if (n < 1 || n > 65536) {
699 u->err = "invalid port";
700 return NGX_ERROR;
701 }
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000702
Igor Sysoevc9491d12008-08-26 14:24:14 +0000703 u->port = (in_port_t) n;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000704 sin->sin_port = htons((in_port_t) n);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000705
Igor Sysoevc9491d12008-08-26 14:24:14 +0000706 u->port_text.len = last - host;
707 u->port_text.data = host;
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000708
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000709 u->wildcard = 1;
710
Igor Sysoevc9491d12008-08-26 14:24:14 +0000711 return NGX_OK;
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000712 }
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000713 }
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000714 }
715
Igor Sysoevc9491d12008-08-26 14:24:14 +0000716 u->no_port = 1;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000717 }
718
Igor Sysoevc9491d12008-08-26 14:24:14 +0000719 len = last - host;
720
721 if (len == 0) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000722 u->err = "no host";
723 return NGX_ERROR;
724 }
725
Igor Sysoevc9491d12008-08-26 14:24:14 +0000726 if (len == 1 && *host == '*') {
727 len = 0;
728 }
729
730 u->host.len = len;
731 u->host.data = host;
732
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000733 if (u->no_resolve) {
734 return NGX_OK;
735 }
736
Igor Sysoev0f25ed32009-11-02 13:51:10 +0000737 if (len) {
738 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
Igor Sysoevc9491d12008-08-26 14:24:14 +0000739
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000740 if (sin->sin_addr.s_addr == INADDR_NONE) {
Igor Sysoev0f25ed32009-11-02 13:51:10 +0000741 p = ngx_alloc(++len, pool->log);
742 if (p == NULL) {
743 return NGX_ERROR;
744 }
745
746 (void) ngx_cpystrn(p, host, len);
747
Igor Sysoevc9491d12008-08-26 14:24:14 +0000748 h = gethostbyname((const char *) p);
749
Igor Sysoev0f25ed32009-11-02 13:51:10 +0000750 ngx_free(p);
751
Igor Sysoevc9491d12008-08-26 14:24:14 +0000752 if (h == NULL || h->h_addr_list[0] == NULL) {
Igor Sysoevc9491d12008-08-26 14:24:14 +0000753 u->err = "host not found";
754 return NGX_ERROR;
755 }
756
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000757 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
758 }
759
760 if (sin->sin_addr.s_addr == INADDR_ANY) {
761 u->wildcard = 1;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000762 }
763
Igor Sysoevc9491d12008-08-26 14:24:14 +0000764 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000765 sin->sin_addr.s_addr = INADDR_ANY;
766 u->wildcard = 1;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000767 }
768
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000769 if (u->no_port) {
770 u->port = u->default_port;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000771 sin->sin_port = htons(u->default_port);
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000772 }
773
Igor Sysoevc9491d12008-08-26 14:24:14 +0000774 if (u->listen) {
775 return NGX_OK;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000776 }
777
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000778 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000779 return NGX_ERROR;
780 }
781
782 return NGX_OK;
783}
784
785
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000786static ngx_int_t
787ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
788{
789#if (NGX_HAVE_INET6)
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000790 u_char *p, *host, *port, *last, *uri;
791 size_t len;
792 ngx_int_t n;
793 struct sockaddr_in6 *sin6;
794
795 u->socklen = sizeof(struct sockaddr_in6);
796 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
797 sin6->sin6_family = AF_INET6;
798
799 host = u->url.data + 1;
800
801 last = u->url.data + u->url.len;
802
803 p = ngx_strlchr(host, last, ']');
804
805 if (p == NULL) {
806 u->err = "invalid host";
807 return NGX_ERROR;
808 }
809
810 if (last - p) {
811
812 port = p + 1;
813
814 uri = ngx_strlchr(port, last, '/');
815
816 if (uri) {
817 if (u->listen || !u->uri_part) {
818 u->err = "invalid host";
819 return NGX_ERROR;
820 }
821
822 u->uri.len = last - uri;
823 u->uri.data = uri;
824 }
825
826 if (*port == ':') {
827 port++;
828
829 len = last - port;
830
831 if (len == 0) {
832 u->err = "invalid port";
833 return NGX_ERROR;
834 }
835
836 n = ngx_atoi(port, len);
837
838 if (n < 1 || n > 65536) {
839 u->err = "invalid port";
840 return NGX_ERROR;
841 }
842
843 u->port = (in_port_t) n;
844 sin6->sin6_port = htons((in_port_t) n);
845
846 u->port_text.len = len;
847 u->port_text.data = port;
848
849 } else {
850 u->no_port = 1;
851 }
852 }
853
854 len = p - host;
855
856 if (len == 0) {
857 u->err = "no host";
858 return NGX_ERROR;
859 }
860
Igor Sysoev47c88462009-11-02 12:58:30 +0000861 u->host.len = len;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000862 u->host.data = host;
863
Igor Sysoev67765e82009-11-02 14:32:46 +0000864 if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000865 u->err = "invalid IPv6 address";
866 return NGX_ERROR;
867 }
868
869 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
870 u->wildcard = 1;
871 }
872
873 u->family = AF_INET6;
874
875 if (u->no_resolve) {
876 return NGX_OK;
877 }
878
879 if (u->no_port) {
880 u->port = u->default_port;
881 sin6->sin6_port = htons(u->default_port);
882 }
883
884 return NGX_OK;
885
886#else
887
888 u->err = "the INET6 sockets are not supported on this platform";
889
890 return NGX_ERROR;
891
892#endif
893}
894
895
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000896ngx_int_t
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000897ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000898{
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000899 u_char *p, *host;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000900 size_t len;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000901 in_port_t port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000902 in_addr_t in_addr;
903 ngx_uint_t i;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000904 struct hostent *h;
905 struct sockaddr_in *sin;
906
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000907 /* AF_INET only */
908
Igor Sysoev2bc44ea2009-02-21 14:34:32 +0000909 port = htons(u->port);
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000910
Igor Sysoev0f25ed32009-11-02 13:51:10 +0000911 in_addr = ngx_inet_addr(u->host.data, u->host.len);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000912
913 if (in_addr == INADDR_NONE) {
Igor Sysoev0f25ed32009-11-02 13:51:10 +0000914 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
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000921 h = gethostbyname((char *) host);
922
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000923 ngx_free(host);
924
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000925 if (h == NULL || h->h_addr_list[0] == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000926 u->err = "host not found";
927 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000928 }
929
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000930 if (u->one_addr == 0) {
931 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
932
933 } else {
934 i = 1;
935 }
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000936
937 /* MP: ngx_shared_palloc() */
938
Igor Sysoev0c189c52009-11-02 15:14:17 +0000939 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000940 if (u->addrs == NULL) {
941 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000942 }
943
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000944 u->naddrs = i;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000945
946 for (i = 0; h->h_addr_list[i] != NULL; i++) {
947
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000948 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000949 if (sin == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000950 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000951 }
952
953 sin->sin_family = AF_INET;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000954 sin->sin_port = port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000955 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
956
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000957 u->addrs[i].sockaddr = (struct sockaddr *) sin;
958 u->addrs[i].socklen = sizeof(struct sockaddr_in);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000959
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000960 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000961
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +0000962 p = ngx_pnalloc(pool, len);
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000963 if (p == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000964 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000965 }
966
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000967 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000968
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000969 u->addrs[i].name.len = len;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000970 u->addrs[i].name.data = p;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000971 }
972
973 } else {
974
975 /* MP: ngx_shared_palloc() */
976
Igor Sysoev0c189c52009-11-02 15:14:17 +0000977 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000978 if (u->addrs == NULL) {
979 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000980 }
981
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000982 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000983 if (sin == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000984 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000985 }
986
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000987 u->naddrs = 1;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000988
989 sin->sin_family = AF_INET;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000990 sin->sin_port = port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000991 sin->sin_addr.s_addr = in_addr;
992
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000993 u->addrs[0].sockaddr = (struct sockaddr *) sin;
994 u->addrs[0].socklen = sizeof(struct sockaddr_in);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000995
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000996 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000997 if (p == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000998 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000999 }
1000
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001001 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
1002 &u->host, ntohs(port)) - p;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00001003 u->addrs[0].name.data = p;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001004 }
1005
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001006 return NGX_OK;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001007}