blob: 765bda53d990557b85ddc7ff74a31e79a9f7ed4c [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
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoevd90282d2004-09-28 08:34:51 +00005 */
6
7
Igor Sysoev42feecb2002-12-15 06:25:09 +00008#include <ngx_config.h>
Igor Sysoev1c104622003-06-03 15:42:58 +00009#include <ngx_core.h>
Igor Sysoev42feecb2002-12-15 06:25:09 +000010
11
Igor Sysoev154013c2008-08-22 13:36:56 +000012static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
13static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
Igor Sysoeva35eacc2009-02-21 07:02:02 +000014static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
Igor Sysoev154013c2008-08-22 13:36:56 +000015
16
Igor Sysoev36b634c2007-11-23 16:59:24 +000017in_addr_t
18ngx_inet_addr(u_char *text, size_t len)
19{
20 u_char *p, c;
21 in_addr_t addr;
22 ngx_uint_t octet, n;
23
24 addr = 0;
25 octet = 0;
26 n = 0;
27
28 for (p = text; p < text + len; p++) {
Igor Sysoev36b634c2007-11-23 16:59:24 +000029 c = *p;
30
31 if (c >= '0' && c <= '9') {
32 octet = octet * 10 + (c - '0');
Valentin Bartenev0074c972015-04-28 18:55:03 +030033
34 if (octet > 255) {
35 return INADDR_NONE;
36 }
37
Igor Sysoev36b634c2007-11-23 16:59:24 +000038 continue;
39 }
40
Ruslan Ermilov616c3492015-03-17 00:26:22 +030041 if (c == '.') {
Igor Sysoev36b634c2007-11-23 16:59:24 +000042 addr = (addr << 8) + octet;
43 octet = 0;
44 n++;
45 continue;
46 }
47
48 return INADDR_NONE;
49 }
50
Ruslan Ermilov616c3492015-03-17 00:26:22 +030051 if (n == 3) {
Igor Sysoev36b634c2007-11-23 16:59:24 +000052 addr = (addr << 8) + octet;
53 return htonl(addr);
54 }
55
56 return INADDR_NONE;
57}
58
59
Igor Sysoev5a76cbb2009-11-02 12:50:00 +000060#if (NGX_HAVE_INET6)
61
62ngx_int_t
63ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
64{
65 u_char c, *zero, *digit, *s, *d;
66 size_t len4;
67 ngx_uint_t n, nibbles, word;
68
69 if (len == 0) {
70 return NGX_ERROR;
71 }
72
73 zero = NULL;
74 digit = NULL;
75 len4 = 0;
76 nibbles = 0;
77 word = 0;
78 n = 8;
79
80 if (p[0] == ':') {
81 p++;
82 len--;
83 }
84
85 for (/* void */; len; len--) {
86 c = *p++;
87
88 if (c == ':') {
89 if (nibbles) {
90 digit = p;
91 len4 = len;
92 *addr++ = (u_char) (word >> 8);
93 *addr++ = (u_char) (word & 0xff);
94
95 if (--n) {
96 nibbles = 0;
97 word = 0;
98 continue;
99 }
100
101 } else {
102 if (zero == NULL) {
103 digit = p;
104 len4 = len;
105 zero = addr;
106 continue;
107 }
108 }
109
110 return NGX_ERROR;
111 }
112
113 if (c == '.' && nibbles) {
Igor Sysoev9813a192011-04-15 13:50:27 +0000114 if (n < 2 || digit == NULL) {
Igor Sysoev5a76cbb2009-11-02 12:50:00 +0000115 return NGX_ERROR;
116 }
117
118 word = ngx_inet_addr(digit, len4 - 1);
119 if (word == INADDR_NONE) {
120 return NGX_ERROR;
121 }
122
123 word = ntohl(word);
124 *addr++ = (u_char) ((word >> 24) & 0xff);
125 *addr++ = (u_char) ((word >> 16) & 0xff);
126 n--;
127 break;
128 }
129
130 if (++nibbles > 4) {
131 return NGX_ERROR;
132 }
133
134 if (c >= '0' && c <= '9') {
135 word = word * 16 + (c - '0');
136 continue;
137 }
138
139 c |= 0x20;
140
141 if (c >= 'a' && c <= 'f') {
142 word = word * 16 + (c - 'a') + 10;
143 continue;
144 }
145
146 return NGX_ERROR;
147 }
148
149 if (nibbles == 0 && zero == NULL) {
150 return NGX_ERROR;
151 }
152
153 *addr++ = (u_char) (word >> 8);
154 *addr++ = (u_char) (word & 0xff);
155
156 if (--n) {
157 if (zero) {
158 n *= 2;
159 s = addr - 1;
160 d = s + n;
161 while (s >= zero) {
162 *d-- = *s--;
163 }
164 ngx_memzero(zero, n);
165 return NGX_OK;
166 }
167
168 } else {
169 if (zero == NULL) {
170 return NGX_OK;
171 }
172 }
173
174 return NGX_ERROR;
175}
176
177#endif
178
179
Igor Sysoev899b44e2005-05-12 14:58:06 +0000180size_t
Vladimir Homutovaf189462013-07-11 16:07:25 +0400181ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len,
182 ngx_uint_t port)
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000183{
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000184 u_char *p;
185 struct sockaddr_in *sin;
186#if (NGX_HAVE_INET6)
187 size_t n;
188 struct sockaddr_in6 *sin6;
189#endif
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000190#if (NGX_HAVE_UNIX_DOMAIN)
191 struct sockaddr_un *saun;
192#endif
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000193
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000194 switch (sa->sa_family) {
195
196 case AF_INET:
Igor Sysoev6a750192008-08-21 18:47:23 +0000197
198 sin = (struct sockaddr_in *) sa;
199 p = (u_char *) &sin->sin_addr;
200
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000201 if (port) {
202 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
203 p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
204 } else {
205 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
206 p[0], p[1], p[2], p[3]);
207 }
Igor Sysoev9c610952004-03-16 13:35:20 +0000208
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000209 return (p - text);
210
211#if (NGX_HAVE_INET6)
212
213 case AF_INET6:
214
215 sin6 = (struct sockaddr_in6 *) sa;
216
217 n = 0;
218
219 if (port) {
220 text[n++] = '[';
221 }
222
Igor Sysoev67765e82009-11-02 14:32:46 +0000223 n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000224
225 if (port) {
226 n = ngx_sprintf(&text[1 + n], "]:%d",
227 ntohs(sin6->sin6_port)) - text;
228 }
229
230 return n;
231#endif
232
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000233#if (NGX_HAVE_UNIX_DOMAIN)
234
235 case AF_UNIX:
236 saun = (struct sockaddr_un *) sa;
237
Vladimir Homutovaf189462013-07-11 16:07:25 +0400238 /* on Linux sockaddr might not include sun_path at all */
239
Maxim Dounin4d1b08b2013-08-05 11:40:33 +0400240 if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
Vladimir Homutovaf189462013-07-11 16:07:25 +0400241 p = ngx_snprintf(text, len, "unix:%Z");
242
243 } else {
244 p = ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path);
245 }
246
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000247 /* we do not include trailing zero in address length */
248
Vladimir Homutovaf189462013-07-11 16:07:25 +0400249 return (p - text - 1);
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000250
251#endif
252
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000253 default:
254 return 0;
255 }
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000256}
257
Igor Sysoev02729772008-01-04 11:54:55 +0000258
Igor Sysoev899b44e2005-05-12 14:58:06 +0000259size_t
260ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
Igor Sysoev42feecb2002-12-15 06:25:09 +0000261{
Igor Sysoev6a750192008-08-21 18:47:23 +0000262 u_char *p;
Igor Sysoev9c610952004-03-16 13:35:20 +0000263
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000264 switch (family) {
Igor Sysoev6a750192008-08-21 18:47:23 +0000265
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000266 case AF_INET:
267
268 p = addr;
Igor Sysoev6a750192008-08-21 18:47:23 +0000269
270 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
271 p[0], p[1], p[2], p[3])
272 - text;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000273
274#if (NGX_HAVE_INET6)
275
276 case AF_INET6:
277 return ngx_inet6_ntop(addr, text, len);
278
279#endif
280
281 default:
282 return 0;
283 }
284}
285
286
287#if (NGX_HAVE_INET6)
288
Igor Sysoevfd078fd2009-11-03 12:44:55 +0000289size_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000290ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
291{
292 u_char *dst;
293 size_t max, n;
294 ngx_uint_t i, zero, last;
295
296 if (len < NGX_INET6_ADDRSTRLEN) {
297 return 0;
Igor Sysoev9c610952004-03-16 13:35:20 +0000298 }
299
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000300 zero = (ngx_uint_t) -1;
301 last = (ngx_uint_t) -1;
302 max = 1;
303 n = 0;
304
305 for (i = 0; i < 16; i += 2) {
306
307 if (p[i] || p[i + 1]) {
308
309 if (max < n) {
310 zero = last;
311 max = n;
312 }
313
314 n = 0;
315 continue;
316 }
317
318 if (n++ == 0) {
319 last = i;
320 }
321 }
322
323 if (max < n) {
324 zero = last;
325 max = n;
326 }
327
328 dst = text;
329 n = 16;
330
331 if (zero == 0) {
332
333 if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
334 || (max == 6)
335 || (max == 7 && p[14] != 0 && p[15] != 1))
336 {
337 n = 12;
338 }
339
340 *dst++ = ':';
341 }
342
343 for (i = 0; i < n; i += 2) {
344
345 if (i == zero) {
346 *dst++ = ':';
347 i += (max - 1) * 2;
348 continue;
349 }
350
351 dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
352
353 if (i < 14) {
354 *dst++ = ':';
355 }
356 }
357
358 if (n == 12) {
359 dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
360 }
361
362 return dst - text;
Igor Sysoev02729772008-01-04 11:54:55 +0000363}
364
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000365#endif
366
Igor Sysoev02729772008-01-04 11:54:55 +0000367
Igor Sysoev899b44e2005-05-12 14:58:06 +0000368ngx_int_t
Igor Sysoev36860102009-02-24 14:01:40 +0000369ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
Igor Sysoev822834e2004-05-25 15:28:46 +0000370{
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000371 u_char *addr, *mask, *last;
372 size_t len;
373 ngx_int_t shift;
374#if (NGX_HAVE_INET6)
375 ngx_int_t rc;
376 ngx_uint_t s, i;
377#endif
Igor Sysoev822834e2004-05-25 15:28:46 +0000378
Igor Sysoev9c388c02008-08-26 14:19:37 +0000379 addr = text->data;
380 last = addr + text->len;
Igor Sysoev822834e2004-05-25 15:28:46 +0000381
Igor Sysoev9c388c02008-08-26 14:19:37 +0000382 mask = ngx_strlchr(addr, last, '/');
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000383 len = (mask ? mask : last) - addr;
Igor Sysoev822834e2004-05-25 15:28:46 +0000384
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000385 cidr->u.in.addr = ngx_inet_addr(addr, len);
Igor Sysoev822834e2004-05-25 15:28:46 +0000386
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000387 if (cidr->u.in.addr != INADDR_NONE) {
Igor Sysoev36860102009-02-24 14:01:40 +0000388 cidr->family = AF_INET;
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000389
390 if (mask == NULL) {
391 cidr->u.in.mask = 0xffffffff;
392 return NGX_OK;
393 }
394
395#if (NGX_HAVE_INET6)
396 } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
397 cidr->family = AF_INET6;
398
399 if (mask == NULL) {
400 ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
401 return NGX_OK;
402 }
403
404#endif
405 } else {
406 return NGX_ERROR;
Igor Sysoev9c388c02008-08-26 14:19:37 +0000407 }
408
409 mask++;
410
411 shift = ngx_atoi(mask, last - mask);
412 if (shift == NGX_ERROR) {
Igor Sysoev822834e2004-05-25 15:28:46 +0000413 return NGX_ERROR;
414 }
415
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000416 switch (cidr->family) {
Igor Sysoev36860102009-02-24 14:01:40 +0000417
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000418#if (NGX_HAVE_INET6)
419 case AF_INET6:
Ruslan Ermilovbffbbeb2012-04-03 08:22:00 +0000420 if (shift > 128) {
421 return NGX_ERROR;
422 }
423
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000424 addr = cidr->u.in6.addr.s6_addr;
425 mask = cidr->u.in6.mask.s6_addr;
426 rc = NGX_OK;
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000427
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000428 for (i = 0; i < 16; i++) {
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000429
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000430 s = (shift > 8) ? 8 : shift;
431 shift -= s;
Igor Sysoev9c388c02008-08-26 14:19:37 +0000432
Ruslan Ermilova5bb6162012-04-11 17:18:15 +0000433 mask[i] = (u_char) (0xffu << (8 - s));
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000434
435 if (addr[i] != (addr[i] & mask[i])) {
436 rc = NGX_DONE;
437 addr[i] &= mask[i];
438 }
439 }
440
441 return rc;
442#endif
443
444 default: /* AF_INET */
Ruslan Ermilovbffbbeb2012-04-03 08:22:00 +0000445 if (shift > 32) {
446 return NGX_ERROR;
447 }
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000448
449 if (shift) {
Ruslan Ermilova5bb6162012-04-11 17:18:15 +0000450 cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000451
452 } else {
453 /* x86 compilers use a shl instruction that shifts by modulo 32 */
454 cidr->u.in.mask = 0;
455 }
456
457 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
Igor Sysoev9c388c02008-08-26 14:19:37 +0000458 return NGX_OK;
459 }
460
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000461 cidr->u.in.addr &= cidr->u.in.mask;
462
Igor Sysoev9c388c02008-08-26 14:19:37 +0000463 return NGX_DONE;
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000464 }
Igor Sysoev822834e2004-05-25 15:28:46 +0000465}
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000466
467
Igor Sysoev8b816d82009-11-02 16:11:06 +0000468ngx_int_t
469ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000470{
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000471 in_addr_t inaddr;
472 ngx_uint_t family;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000473 struct sockaddr_in *sin;
474#if (NGX_HAVE_INET6)
475 struct in6_addr inaddr6;
476 struct sockaddr_in6 *sin6;
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000477
478 /*
Ruslan Ermilov47a04aa2012-04-03 07:37:31 +0000479 * prevent MSVC8 warning:
Igor Sysoev4ac5ca82009-11-03 13:42:25 +0000480 * potentially uninitialized local variable 'inaddr6' used
481 */
Ruslan Ermilov7c4068d2012-12-22 20:03:38 +0000482 ngx_memzero(&inaddr6, sizeof(struct in6_addr));
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000483#endif
484
Igor Sysoev8b816d82009-11-02 16:11:06 +0000485 inaddr = ngx_inet_addr(text, len);
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000486
487 if (inaddr != INADDR_NONE) {
488 family = AF_INET;
489 len = sizeof(struct sockaddr_in);
490
491#if (NGX_HAVE_INET6)
Igor Sysoev8b816d82009-11-02 16:11:06 +0000492 } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000493 family = AF_INET6;
494 len = sizeof(struct sockaddr_in6);
495
496#endif
497 } else {
Igor Sysoev8b816d82009-11-02 16:11:06 +0000498 return NGX_DECLINED;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000499 }
500
Igor Sysoev8b816d82009-11-02 16:11:06 +0000501 addr->sockaddr = ngx_pcalloc(pool, len);
502 if (addr->sockaddr == NULL) {
503 return NGX_ERROR;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000504 }
505
Igor Sysoev8b816d82009-11-02 16:11:06 +0000506 addr->sockaddr->sa_family = (u_char) family;
507 addr->socklen = len;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000508
509 switch (family) {
510
511#if (NGX_HAVE_INET6)
512 case AF_INET6:
Igor Sysoev8b816d82009-11-02 16:11:06 +0000513 sin6 = (struct sockaddr_in6 *) addr->sockaddr;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000514 ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
515 break;
516#endif
517
518 default: /* AF_INET */
Igor Sysoev8b816d82009-11-02 16:11:06 +0000519 sin = (struct sockaddr_in *) addr->sockaddr;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000520 sin->sin_addr.s_addr = inaddr;
521 break;
522 }
523
Igor Sysoev8b816d82009-11-02 16:11:06 +0000524 return NGX_OK;
Igor Sysoev1d52beb2009-11-02 15:20:42 +0000525}
526
527
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000528ngx_int_t
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000529ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000530{
Igor Sysoev154013c2008-08-22 13:36:56 +0000531 u_char *p;
Piotr Sikora0518b162016-02-26 17:30:27 -0800532 size_t len;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000533
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000534 p = u->url.data;
Piotr Sikora0518b162016-02-26 17:30:27 -0800535 len = u->url.len;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000536
Piotr Sikora0518b162016-02-26 17:30:27 -0800537 if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
Igor Sysoev154013c2008-08-22 13:36:56 +0000538 return ngx_parse_unix_domain_url(pool, u);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000539 }
540
Piotr Sikora0518b162016-02-26 17:30:27 -0800541 if (len && p[0] == '[') {
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000542 return ngx_parse_inet6_url(pool, u);
543 }
544
Igor Sysoev154013c2008-08-22 13:36:56 +0000545 return ngx_parse_inet_url(pool, u);
546}
547
548
549static ngx_int_t
550ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
551{
552#if (NGX_HAVE_UNIX_DOMAIN)
Igor Sysoevc9491d12008-08-26 14:24:14 +0000553 u_char *path, *uri, *last;
Igor Sysoev154013c2008-08-22 13:36:56 +0000554 size_t len;
Igor Sysoev154013c2008-08-22 13:36:56 +0000555 struct sockaddr_un *saun;
556
557 len = u->url.len;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000558 path = u->url.data;
Igor Sysoev154013c2008-08-22 13:36:56 +0000559
Igor Sysoevc9491d12008-08-26 14:24:14 +0000560 path += 5;
Igor Sysoev154013c2008-08-22 13:36:56 +0000561 len -= 5;
562
Igor Sysoev154013c2008-08-22 13:36:56 +0000563 if (u->uri_part) {
Igor Sysoev154013c2008-08-22 13:36:56 +0000564
Igor Sysoevc9491d12008-08-26 14:24:14 +0000565 last = path + len;
566 uri = ngx_strlchr(path, last, ':');
Igor Sysoev154013c2008-08-22 13:36:56 +0000567
Igor Sysoevc9491d12008-08-26 14:24:14 +0000568 if (uri) {
569 len = uri - path;
570 uri++;
571 u->uri.len = last - uri;
572 u->uri.data = uri;
Igor Sysoev154013c2008-08-22 13:36:56 +0000573 }
574 }
575
576 if (len == 0) {
577 u->err = "no path in the unix domain socket";
578 return NGX_ERROR;
579 }
580
Igor Sysoevc9491d12008-08-26 14:24:14 +0000581 u->host.len = len++;
582 u->host.data = path;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000583
584 if (len > sizeof(saun->sun_path)) {
Igor Sysoev154013c2008-08-22 13:36:56 +0000585 u->err = "too long path in the unix domain socket";
586 return NGX_ERROR;
587 }
588
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000589 u->socklen = sizeof(struct sockaddr_un);
590 saun = (struct sockaddr_un *) &u->sockaddr;
591 saun->sun_family = AF_UNIX;
592 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
593
Igor Sysoev0c189c52009-11-02 15:14:17 +0000594 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
Igor Sysoev154013c2008-08-22 13:36:56 +0000595 if (u->addrs == NULL) {
596 return NGX_ERROR;
597 }
598
599 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
600 if (saun == NULL) {
601 return NGX_ERROR;
602 }
603
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000604 u->family = AF_UNIX;
Igor Sysoev154013c2008-08-22 13:36:56 +0000605 u->naddrs = 1;
606
607 saun->sun_family = AF_UNIX;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000608 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
Igor Sysoev154013c2008-08-22 13:36:56 +0000609
610 u->addrs[0].sockaddr = (struct sockaddr *) saun;
611 u->addrs[0].socklen = sizeof(struct sockaddr_un);
Igor Sysoevc9491d12008-08-26 14:24:14 +0000612 u->addrs[0].name.len = len + 4;
Igor Sysoev154013c2008-08-22 13:36:56 +0000613 u->addrs[0].name.data = u->url.data;
614
Igor Sysoev154013c2008-08-22 13:36:56 +0000615 return NGX_OK;
616
617#else
618
619 u->err = "the unix domain sockets are not supported on this platform";
620
621 return NGX_ERROR;
622
623#endif
624}
625
626
627static ngx_int_t
628ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
629{
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +0000630 u_char *p, *host, *port, *last, *uri, *args;
631 size_t len;
632 ngx_int_t n;
633 struct sockaddr_in *sin;
634#if (NGX_HAVE_INET6)
635 struct sockaddr_in6 *sin6;
636#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000637
638 u->socklen = sizeof(struct sockaddr_in);
639 sin = (struct sockaddr_in *) &u->sockaddr;
640 sin->sin_family = AF_INET;
Igor Sysoev154013c2008-08-22 13:36:56 +0000641
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000642 u->family = AF_INET;
643
Igor Sysoevc9491d12008-08-26 14:24:14 +0000644 host = u->url.data;
Igor Sysoev154013c2008-08-22 13:36:56 +0000645
Igor Sysoevc9491d12008-08-26 14:24:14 +0000646 last = host + u->url.len;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000647
Igor Sysoevc9491d12008-08-26 14:24:14 +0000648 port = ngx_strlchr(host, last, ':');
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000649
Igor Sysoevc239da52008-10-24 15:12:11 +0000650 uri = ngx_strlchr(host, last, '/');
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000651
Igor Sysoev164abfb2008-10-24 19:34:24 +0000652 args = ngx_strlchr(host, last, '?');
653
654 if (args) {
Ruslan Ermilov887f5142012-06-01 11:35:09 +0000655 if (uri == NULL || args < uri) {
Igor Sysoev164abfb2008-10-24 19:34:24 +0000656 uri = args;
657 }
658 }
659
Igor Sysoevc9491d12008-08-26 14:24:14 +0000660 if (uri) {
661 if (u->listen || !u->uri_part) {
662 u->err = "invalid host";
663 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000664 }
665
Igor Sysoevc9491d12008-08-26 14:24:14 +0000666 u->uri.len = last - uri;
667 u->uri.data = uri;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000668
Igor Sysoevc9491d12008-08-26 14:24:14 +0000669 last = uri;
Igor Sysoevc239da52008-10-24 15:12:11 +0000670
671 if (uri < port) {
672 port = NULL;
Igor Sysoevead80912008-11-11 16:04:05 +0000673 }
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000674 }
675
Igor Sysoevc9491d12008-08-26 14:24:14 +0000676 if (port) {
677 port++;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000678
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000679 len = last - port;
680
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000681 n = ngx_atoi(port, len);
682
Ruslan Ermilovf12d6ce2011-10-25 13:48:43 +0000683 if (n < 1 || n > 65535) {
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000684 u->err = "invalid port";
685 return NGX_ERROR;
686 }
687
688 u->port = (in_port_t) n;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000689 sin->sin_port = htons((in_port_t) n);
Igor Sysoevd3bf7c12008-08-26 16:11:30 +0000690
691 u->port_text.len = len;
Igor Sysoevc9491d12008-08-26 14:24:14 +0000692 u->port_text.data = port;
693
694 last = port - 1;
Igor Sysoev00e03772007-11-28 19:55:31 +0000695
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000696 } else {
Igor Sysoevc9491d12008-08-26 14:24:14 +0000697 if (uri == NULL) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000698
Igor Sysoevc9491d12008-08-26 14:24:14 +0000699 if (u->listen) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000700
Igor Sysoevc9491d12008-08-26 14:24:14 +0000701 /* test value as port only */
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000702
Igor Sysoevc9491d12008-08-26 14:24:14 +0000703 n = ngx_atoi(host, last - host);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000704
Igor Sysoevc9491d12008-08-26 14:24:14 +0000705 if (n != NGX_ERROR) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000706
Ruslan Ermilovf12d6ce2011-10-25 13:48:43 +0000707 if (n < 1 || n > 65535) {
Igor Sysoevc9491d12008-08-26 14:24:14 +0000708 u->err = "invalid port";
709 return NGX_ERROR;
710 }
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000711
Igor Sysoevc9491d12008-08-26 14:24:14 +0000712 u->port = (in_port_t) n;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000713 sin->sin_port = htons((in_port_t) n);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000714
Igor Sysoevc9491d12008-08-26 14:24:14 +0000715 u->port_text.len = last - host;
716 u->port_text.data = host;
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000717
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000718 u->wildcard = 1;
719
Igor Sysoevc9491d12008-08-26 14:24:14 +0000720 return NGX_OK;
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000721 }
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000722 }
Igor Sysoev20bf47b2006-10-24 13:06:55 +0000723 }
724
Igor Sysoevc9491d12008-08-26 14:24:14 +0000725 u->no_port = 1;
Ruslan Ermilova2a22912013-01-10 12:58:55 +0000726 u->port = u->default_port;
727 sin->sin_port = htons(u->default_port);
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000728 }
729
Igor Sysoevc9491d12008-08-26 14:24:14 +0000730 len = last - host;
731
732 if (len == 0) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000733 u->err = "no host";
734 return NGX_ERROR;
735 }
736
Igor Sysoevc9491d12008-08-26 14:24:14 +0000737 u->host.len = len;
738 u->host.data = host;
739
Ruslan Ermilovbbf70432012-12-17 09:31:53 +0000740 if (u->listen && len == 1 && *host == '*') {
741 sin->sin_addr.s_addr = INADDR_ANY;
742 u->wildcard = 1;
743 return NGX_OK;
744 }
745
Ruslan Ermilovbbf70432012-12-17 09:31:53 +0000746 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
Igor Sysoevc9491d12008-08-26 14:24:14 +0000747
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +0000748 if (sin->sin_addr.s_addr != INADDR_NONE) {
749
750 if (sin->sin_addr.s_addr == INADDR_ANY) {
751 u->wildcard = 1;
752 }
753
754 u->naddrs = 1;
755
756 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
757 if (u->addrs == NULL) {
758 return NGX_ERROR;
759 }
760
761 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
762 if (sin == NULL) {
763 return NGX_ERROR;
764 }
765
766 ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in));
767
768 u->addrs[0].sockaddr = (struct sockaddr *) sin;
769 u->addrs[0].socklen = sizeof(struct sockaddr_in);
770
771 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
Ruslan Ermilovbbf70432012-12-17 09:31:53 +0000772 if (p == NULL) {
773 return NGX_ERROR;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000774 }
775
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +0000776 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
777 &u->host, u->port) - p;
778 u->addrs[0].name.data = p;
Ruslan Ermilovbbf70432012-12-17 09:31:53 +0000779
Igor Sysoevc9491d12008-08-26 14:24:14 +0000780 return NGX_OK;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000781 }
782
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +0000783 if (u->no_resolve) {
784 return NGX_OK;
785 }
786
787 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
788 return NGX_ERROR;
789 }
790
791 u->family = u->addrs[0].sockaddr->sa_family;
792 u->socklen = u->addrs[0].socklen;
793 ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
794
795 switch (u->family) {
796
797#if (NGX_HAVE_INET6)
798 case AF_INET6:
799 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
800
801 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
802 u->wildcard = 1;
803 }
804
805 break;
806#endif
807
808 default: /* AF_INET */
809 sin = (struct sockaddr_in *) &u->sockaddr;
810
811 if (sin->sin_addr.s_addr == INADDR_ANY) {
812 u->wildcard = 1;
813 }
814
815 break;
816 }
817
818 return NGX_OK;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000819}
820
821
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000822static ngx_int_t
823ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
824{
825#if (NGX_HAVE_INET6)
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000826 u_char *p, *host, *port, *last, *uri;
827 size_t len;
828 ngx_int_t n;
829 struct sockaddr_in6 *sin6;
830
831 u->socklen = sizeof(struct sockaddr_in6);
832 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
833 sin6->sin6_family = AF_INET6;
834
835 host = u->url.data + 1;
836
837 last = u->url.data + u->url.len;
838
839 p = ngx_strlchr(host, last, ']');
840
841 if (p == NULL) {
842 u->err = "invalid host";
843 return NGX_ERROR;
844 }
845
846 if (last - p) {
847
848 port = p + 1;
849
850 uri = ngx_strlchr(port, last, '/');
851
852 if (uri) {
853 if (u->listen || !u->uri_part) {
854 u->err = "invalid host";
855 return NGX_ERROR;
856 }
857
858 u->uri.len = last - uri;
859 u->uri.data = uri;
Maxim Dounin596226f2012-06-04 14:07:34 +0000860
861 last = uri;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000862 }
863
864 if (*port == ':') {
865 port++;
866
867 len = last - port;
868
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000869 n = ngx_atoi(port, len);
870
Ruslan Ermilovf12d6ce2011-10-25 13:48:43 +0000871 if (n < 1 || n > 65535) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000872 u->err = "invalid port";
873 return NGX_ERROR;
874 }
875
876 u->port = (in_port_t) n;
877 sin6->sin6_port = htons((in_port_t) n);
878
879 u->port_text.len = len;
880 u->port_text.data = port;
881
882 } else {
883 u->no_port = 1;
Ruslan Ermilova2a22912013-01-10 12:58:55 +0000884 u->port = u->default_port;
885 sin6->sin6_port = htons(u->default_port);
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000886 }
887 }
888
889 len = p - host;
890
891 if (len == 0) {
892 u->err = "no host";
893 return NGX_ERROR;
894 }
895
Maxim Dounin596226f2012-06-04 14:07:34 +0000896 u->host.len = len + 2;
897 u->host.data = host - 1;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000898
Igor Sysoev67765e82009-11-02 14:32:46 +0000899 if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000900 u->err = "invalid IPv6 address";
901 return NGX_ERROR;
902 }
903
904 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
905 u->wildcard = 1;
906 }
907
Maxim Dounin596226f2012-06-04 14:07:34 +0000908 u->family = AF_INET6;
909 u->naddrs = 1;
910
911 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
912 if (u->addrs == NULL) {
913 return NGX_ERROR;
914 }
915
916 sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
917 if (sin6 == NULL) {
918 return NGX_ERROR;
919 }
920
921 ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6));
922
923 u->addrs[0].sockaddr = (struct sockaddr *) sin6;
924 u->addrs[0].socklen = sizeof(struct sockaddr_in6);
925
926 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
927 if (p == NULL) {
928 return NGX_ERROR;
929 }
930
931 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
932 &u->host, u->port) - p;
933 u->addrs[0].name.data = p;
934
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000935 return NGX_OK;
936
937#else
938
939 u->err = "the INET6 sockets are not supported on this platform";
940
941 return NGX_ERROR;
942
943#endif
944}
945
946
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +0000947#if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
948
949ngx_int_t
950ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
951{
952 u_char *p, *host;
953 size_t len;
954 in_port_t port;
955 ngx_uint_t i;
956 struct addrinfo hints, *res, *rp;
957 struct sockaddr_in *sin;
958 struct sockaddr_in6 *sin6;
959
960 port = htons(u->port);
961
962 host = ngx_alloc(u->host.len + 1, pool->log);
963 if (host == NULL) {
964 return NGX_ERROR;
965 }
966
967 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
968
969 ngx_memzero(&hints, sizeof(struct addrinfo));
970 hints.ai_family = AF_UNSPEC;
971 hints.ai_socktype = SOCK_STREAM;
Ruslan Ermilov3693daa2013-08-05 13:44:56 +0400972#ifdef AI_ADDRCONFIG
Ruslan Ermilov7c6971c2013-08-05 10:55:59 +0400973 hints.ai_flags = AI_ADDRCONFIG;
Ruslan Ermilov3693daa2013-08-05 13:44:56 +0400974#endif
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +0000975
976 if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
977 u->err = "host not found";
978 ngx_free(host);
979 return NGX_ERROR;
980 }
981
982 ngx_free(host);
983
984 for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) {
985
986 switch (rp->ai_family) {
987
988 case AF_INET:
989 case AF_INET6:
990 break;
991
992 default:
993 continue;
994 }
995
996 i++;
997 }
998
999 if (i == 0) {
1000 u->err = "host not found";
1001 goto failed;
1002 }
1003
1004 /* MP: ngx_shared_palloc() */
1005
1006 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
1007 if (u->addrs == NULL) {
1008 goto failed;
1009 }
1010
1011 u->naddrs = i;
1012
1013 i = 0;
1014
1015 /* AF_INET addresses first */
1016
1017 for (rp = res; rp != NULL; rp = rp->ai_next) {
1018
1019 if (rp->ai_family != AF_INET) {
1020 continue;
1021 }
1022
1023 sin = ngx_pcalloc(pool, rp->ai_addrlen);
1024 if (sin == NULL) {
1025 goto failed;
1026 }
1027
1028 ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
1029
1030 sin->sin_port = port;
1031
1032 u->addrs[i].sockaddr = (struct sockaddr *) sin;
1033 u->addrs[i].socklen = rp->ai_addrlen;
1034
1035 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
1036
1037 p = ngx_pnalloc(pool, len);
1038 if (p == NULL) {
1039 goto failed;
1040 }
1041
Vladimir Homutovaf189462013-07-11 16:07:25 +04001042 len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1);
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +00001043
1044 u->addrs[i].name.len = len;
1045 u->addrs[i].name.data = p;
1046
1047 i++;
1048 }
1049
1050 for (rp = res; rp != NULL; rp = rp->ai_next) {
1051
1052 if (rp->ai_family != AF_INET6) {
1053 continue;
1054 }
1055
1056 sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
1057 if (sin6 == NULL) {
1058 goto failed;
1059 }
1060
1061 ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
1062
1063 sin6->sin6_port = port;
1064
1065 u->addrs[i].sockaddr = (struct sockaddr *) sin6;
1066 u->addrs[i].socklen = rp->ai_addrlen;
1067
1068 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
1069
1070 p = ngx_pnalloc(pool, len);
1071 if (p == NULL) {
1072 goto failed;
1073 }
1074
Vladimir Homutovaf189462013-07-11 16:07:25 +04001075 len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p,
1076 len, 1);
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +00001077
1078 u->addrs[i].name.len = len;
1079 u->addrs[i].name.data = p;
1080
1081 i++;
1082 }
1083
1084 freeaddrinfo(res);
1085 return NGX_OK;
1086
1087failed:
1088
1089 freeaddrinfo(res);
1090 return NGX_ERROR;
1091}
1092
1093#else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
1094
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001095ngx_int_t
Igor Sysoev7ed63ee2007-10-08 08:55:12 +00001096ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001097{
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00001098 u_char *p, *host;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001099 size_t len;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001100 in_port_t port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001101 in_addr_t in_addr;
1102 ngx_uint_t i;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001103 struct hostent *h;
1104 struct sockaddr_in *sin;
1105
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001106 /* AF_INET only */
1107
Igor Sysoev2bc44ea2009-02-21 14:34:32 +00001108 port = htons(u->port);
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001109
Igor Sysoev0f25ed32009-11-02 13:51:10 +00001110 in_addr = ngx_inet_addr(u->host.data, u->host.len);
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001111
1112 if (in_addr == INADDR_NONE) {
Igor Sysoev0f25ed32009-11-02 13:51:10 +00001113 host = ngx_alloc(u->host.len + 1, pool->log);
1114 if (host == NULL) {
1115 return NGX_ERROR;
1116 }
1117
1118 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
1119
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001120 h = gethostbyname((char *) host);
1121
Igor Sysoev7ed63ee2007-10-08 08:55:12 +00001122 ngx_free(host);
1123
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001124 if (h == NULL || h->h_addr_list[0] == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001125 u->err = "host not found";
1126 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001127 }
1128
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +00001129 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001130
1131 /* MP: ngx_shared_palloc() */
1132
Igor Sysoev0c189c52009-11-02 15:14:17 +00001133 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001134 if (u->addrs == NULL) {
1135 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001136 }
1137
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001138 u->naddrs = i;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001139
Igor Sysoevd53c8362011-02-17 15:01:16 +00001140 for (i = 0; i < u->naddrs; i++) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001141
Igor Sysoev7ed63ee2007-10-08 08:55:12 +00001142 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001143 if (sin == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001144 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001145 }
1146
1147 sin->sin_family = AF_INET;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001148 sin->sin_port = port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001149 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
1150
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001151 u->addrs[i].sockaddr = (struct sockaddr *) sin;
1152 u->addrs[i].socklen = sizeof(struct sockaddr_in);
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001153
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001154 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001155
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001156 p = ngx_pnalloc(pool, len);
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00001157 if (p == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001158 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001159 }
1160
Vladimir Homutovaf189462013-07-11 16:07:25 +04001161 len = ngx_sock_ntop((struct sockaddr *) sin,
1162 sizeof(struct sockaddr_in), p, len, 1);
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001163
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001164 u->addrs[i].name.len = len;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00001165 u->addrs[i].name.data = p;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001166 }
1167
1168 } else {
1169
1170 /* MP: ngx_shared_palloc() */
1171
Igor Sysoev0c189c52009-11-02 15:14:17 +00001172 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001173 if (u->addrs == NULL) {
1174 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001175 }
1176
Igor Sysoev7ed63ee2007-10-08 08:55:12 +00001177 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001178 if (sin == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001179 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001180 }
1181
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001182 u->naddrs = 1;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001183
1184 sin->sin_family = AF_INET;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001185 sin->sin_port = port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001186 sin->sin_addr.s_addr = in_addr;
1187
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001188 u->addrs[0].sockaddr = (struct sockaddr *) sin;
1189 u->addrs[0].socklen = sizeof(struct sockaddr_in);
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001190
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001191 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00001192 if (p == NULL) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001193 return NGX_ERROR;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001194 }
1195
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001196 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
1197 &u->host, ntohs(port)) - p;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00001198 u->addrs[0].name.data = p;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001199 }
1200
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001201 return NGX_OK;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00001202}
Ruslan Ermilovb8a90c62012-12-17 12:08:53 +00001203
1204#endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
Ruslan Ermilovefd0e0e2013-12-06 14:30:27 +04001205
1206
1207ngx_int_t
1208ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
1209 struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
1210{
1211 struct sockaddr_in *sin1, *sin2;
1212#if (NGX_HAVE_INET6)
1213 struct sockaddr_in6 *sin61, *sin62;
1214#endif
1215#if (NGX_HAVE_UNIX_DOMAIN)
1216 struct sockaddr_un *saun1, *saun2;
1217#endif
1218
1219 if (sa1->sa_family != sa2->sa_family) {
1220 return NGX_DECLINED;
1221 }
1222
1223 switch (sa1->sa_family) {
1224
1225#if (NGX_HAVE_INET6)
1226 case AF_INET6:
1227
1228 sin61 = (struct sockaddr_in6 *) sa1;
1229 sin62 = (struct sockaddr_in6 *) sa2;
1230
1231 if (cmp_port && sin61->sin6_port != sin62->sin6_port) {
1232 return NGX_DECLINED;
1233 }
1234
1235 if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
1236 return NGX_DECLINED;
1237 }
1238
1239 break;
1240#endif
1241
1242#if (NGX_HAVE_UNIX_DOMAIN)
1243 case AF_UNIX:
1244
Ruslan Ermilov2161d8a2016-03-30 11:52:16 +03001245 /* TODO length */
Ruslan Ermilovefd0e0e2013-12-06 14:30:27 +04001246
Ruslan Ermilov2161d8a2016-03-30 11:52:16 +03001247 saun1 = (struct sockaddr_un *) sa1;
1248 saun2 = (struct sockaddr_un *) sa2;
Ruslan Ermilovefd0e0e2013-12-06 14:30:27 +04001249
Ruslan Ermilov2161d8a2016-03-30 11:52:16 +03001250 if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
1251 sizeof(saun1->sun_path))
1252 != 0)
1253 {
1254 return NGX_DECLINED;
1255 }
Ruslan Ermilovefd0e0e2013-12-06 14:30:27 +04001256
Ruslan Ermilov2161d8a2016-03-30 11:52:16 +03001257 break;
Ruslan Ermilovefd0e0e2013-12-06 14:30:27 +04001258#endif
1259
1260 default: /* AF_INET */
1261
1262 sin1 = (struct sockaddr_in *) sa1;
1263 sin2 = (struct sockaddr_in *) sa2;
1264
1265 if (cmp_port && sin1->sin_port != sin2->sin_port) {
1266 return NGX_DECLINED;
1267 }
1268
1269 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1270 return NGX_DECLINED;
1271 }
1272
1273 break;
1274 }
1275
1276 return NGX_OK;
1277}