0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
660
|
4 * Copyright (C) Nginx, Inc.
|
0
|
5 */
|
|
6
|
|
7
|
|
8 #include <ngx_config.h>
|
|
9 #include <ngx_core.h>
|
|
10
|
|
11
|
400
|
12 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
|
|
13 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
|
448
|
14 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
|
362
|
15
|
348
|
16
|
|
17 in_addr_t
|
|
18 ngx_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++) {
|
|
29
|
|
30 c = *p;
|
|
31
|
|
32 if (c >= '0' && c <= '9') {
|
|
33 octet = octet * 10 + (c - '0');
|
|
34 continue;
|
|
35 }
|
|
36
|
|
37 if (c == '.' && octet < 256) {
|
|
38 addr = (addr << 8) + octet;
|
|
39 octet = 0;
|
|
40 n++;
|
|
41 continue;
|
|
42 }
|
|
43
|
|
44 return INADDR_NONE;
|
|
45 }
|
|
46
|
670
|
47 if (n == 3 && octet < 256) {
|
348
|
48 addr = (addr << 8) + octet;
|
|
49 return htonl(addr);
|
|
50 }
|
|
51
|
|
52 return INADDR_NONE;
|
|
53 }
|
|
54
|
|
55
|
540
|
56 #if (NGX_HAVE_INET6)
|
|
57
|
|
58 ngx_int_t
|
|
59 ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
|
|
60 {
|
|
61 u_char c, *zero, *digit, *s, *d;
|
|
62 size_t len4;
|
|
63 ngx_uint_t n, nibbles, word;
|
|
64
|
|
65 if (len == 0) {
|
|
66 return NGX_ERROR;
|
|
67 }
|
|
68
|
|
69 zero = NULL;
|
|
70 digit = NULL;
|
|
71 len4 = 0;
|
|
72 nibbles = 0;
|
|
73 word = 0;
|
|
74 n = 8;
|
|
75
|
|
76 if (p[0] == ':') {
|
|
77 p++;
|
|
78 len--;
|
|
79 }
|
|
80
|
|
81 for (/* void */; len; len--) {
|
|
82 c = *p++;
|
|
83
|
|
84 if (c == ':') {
|
|
85 if (nibbles) {
|
|
86 digit = p;
|
|
87 len4 = len;
|
|
88 *addr++ = (u_char) (word >> 8);
|
|
89 *addr++ = (u_char) (word & 0xff);
|
|
90
|
|
91 if (--n) {
|
|
92 nibbles = 0;
|
|
93 word = 0;
|
|
94 continue;
|
|
95 }
|
|
96
|
|
97 } else {
|
|
98 if (zero == NULL) {
|
|
99 digit = p;
|
|
100 len4 = len;
|
|
101 zero = addr;
|
|
102 continue;
|
|
103 }
|
|
104 }
|
|
105
|
|
106 return NGX_ERROR;
|
|
107 }
|
|
108
|
|
109 if (c == '.' && nibbles) {
|
622
|
110 if (n < 2 || digit == NULL) {
|
540
|
111 return NGX_ERROR;
|
|
112 }
|
|
113
|
|
114 word = ngx_inet_addr(digit, len4 - 1);
|
|
115 if (word == INADDR_NONE) {
|
|
116 return NGX_ERROR;
|
|
117 }
|
|
118
|
|
119 word = ntohl(word);
|
|
120 *addr++ = (u_char) ((word >> 24) & 0xff);
|
|
121 *addr++ = (u_char) ((word >> 16) & 0xff);
|
|
122 n--;
|
|
123 break;
|
|
124 }
|
|
125
|
|
126 if (++nibbles > 4) {
|
|
127 return NGX_ERROR;
|
|
128 }
|
|
129
|
|
130 if (c >= '0' && c <= '9') {
|
|
131 word = word * 16 + (c - '0');
|
|
132 continue;
|
|
133 }
|
|
134
|
|
135 c |= 0x20;
|
|
136
|
|
137 if (c >= 'a' && c <= 'f') {
|
|
138 word = word * 16 + (c - 'a') + 10;
|
|
139 continue;
|
|
140 }
|
|
141
|
|
142 return NGX_ERROR;
|
|
143 }
|
|
144
|
|
145 if (nibbles == 0 && zero == NULL) {
|
|
146 return NGX_ERROR;
|
|
147 }
|
|
148
|
|
149 *addr++ = (u_char) (word >> 8);
|
|
150 *addr++ = (u_char) (word & 0xff);
|
|
151
|
|
152 if (--n) {
|
|
153 if (zero) {
|
|
154 n *= 2;
|
|
155 s = addr - 1;
|
|
156 d = s + n;
|
|
157 while (s >= zero) {
|
|
158 *d-- = *s--;
|
|
159 }
|
|
160 ngx_memzero(zero, n);
|
|
161 return NGX_OK;
|
|
162 }
|
|
163
|
|
164 } else {
|
|
165 if (zero == NULL) {
|
|
166 return NGX_OK;
|
|
167 }
|
|
168 }
|
|
169
|
|
170 return NGX_ERROR;
|
|
171 }
|
|
172
|
|
173 #endif
|
|
174
|
|
175
|
58
|
176 size_t
|
448
|
177 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
|
0
|
178 {
|
448
|
179 u_char *p;
|
|
180 struct sockaddr_in *sin;
|
|
181 #if (NGX_HAVE_INET6)
|
|
182 size_t n;
|
|
183 struct sockaddr_in6 *sin6;
|
|
184 #endif
|
538
|
185 #if (NGX_HAVE_UNIX_DOMAIN)
|
|
186 struct sockaddr_un *saun;
|
|
187 #endif
|
0
|
188
|
448
|
189 switch (sa->sa_family) {
|
|
190
|
|
191 case AF_INET:
|
0
|
192
|
400
|
193 sin = (struct sockaddr_in *) sa;
|
|
194 p = (u_char *) &sin->sin_addr;
|
0
|
195
|
448
|
196 if (port) {
|
|
197 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
|
|
198 p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
|
|
199 } else {
|
|
200 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
|
|
201 p[0], p[1], p[2], p[3]);
|
|
202 }
|
|
203
|
|
204 return (p - text);
|
|
205
|
|
206 #if (NGX_HAVE_INET6)
|
|
207
|
|
208 case AF_INET6:
|
|
209
|
|
210 sin6 = (struct sockaddr_in6 *) sa;
|
|
211
|
|
212 n = 0;
|
|
213
|
|
214 if (port) {
|
|
215 text[n++] = '[';
|
|
216 }
|
|
217
|
540
|
218 n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
|
448
|
219
|
|
220 if (port) {
|
|
221 n = ngx_sprintf(&text[1 + n], "]:%d",
|
|
222 ntohs(sin6->sin6_port)) - text;
|
|
223 }
|
|
224
|
|
225 return n;
|
|
226 #endif
|
|
227
|
538
|
228 #if (NGX_HAVE_UNIX_DOMAIN)
|
|
229
|
|
230 case AF_UNIX:
|
|
231 saun = (struct sockaddr_un *) sa;
|
|
232
|
|
233 /* we do not include trailing zero in address length */
|
|
234
|
|
235 return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
|
|
236
|
|
237 #endif
|
|
238
|
448
|
239 default:
|
|
240 return 0;
|
0
|
241 }
|
|
242 }
|
|
243
|
362
|
244
|
58
|
245 size_t
|
|
246 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
|
0
|
247 {
|
400
|
248 u_char *p;
|
0
|
249
|
448
|
250 switch (family) {
|
0
|
251
|
448
|
252 case AF_INET:
|
|
253
|
|
254 p = addr;
|
0
|
255
|
400
|
256 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
|
|
257 p[0], p[1], p[2], p[3])
|
|
258 - text;
|
448
|
259
|
|
260 #if (NGX_HAVE_INET6)
|
|
261
|
|
262 case AF_INET6:
|
|
263 return ngx_inet6_ntop(addr, text, len);
|
|
264
|
|
265 #endif
|
|
266
|
|
267 default:
|
|
268 return 0;
|
|
269 }
|
|
270 }
|
|
271
|
|
272
|
|
273 #if (NGX_HAVE_INET6)
|
|
274
|
540
|
275 size_t
|
448
|
276 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
|
|
277 {
|
|
278 u_char *dst;
|
|
279 size_t max, n;
|
|
280 ngx_uint_t i, zero, last;
|
|
281
|
|
282 if (len < NGX_INET6_ADDRSTRLEN) {
|
|
283 return 0;
|
0
|
284 }
|
|
285
|
448
|
286 zero = (ngx_uint_t) -1;
|
|
287 last = (ngx_uint_t) -1;
|
|
288 max = 1;
|
|
289 n = 0;
|
|
290
|
|
291 for (i = 0; i < 16; i += 2) {
|
|
292
|
|
293 if (p[i] || p[i + 1]) {
|
|
294
|
|
295 if (max < n) {
|
|
296 zero = last;
|
|
297 max = n;
|
|
298 }
|
|
299
|
|
300 n = 0;
|
|
301 continue;
|
|
302 }
|
|
303
|
|
304 if (n++ == 0) {
|
|
305 last = i;
|
|
306 }
|
|
307 }
|
|
308
|
|
309 if (max < n) {
|
|
310 zero = last;
|
|
311 max = n;
|
|
312 }
|
|
313
|
|
314 dst = text;
|
|
315 n = 16;
|
|
316
|
|
317 if (zero == 0) {
|
|
318
|
|
319 if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
|
|
320 || (max == 6)
|
|
321 || (max == 7 && p[14] != 0 && p[15] != 1))
|
|
322 {
|
|
323 n = 12;
|
|
324 }
|
|
325
|
|
326 *dst++ = ':';
|
|
327 }
|
|
328
|
|
329 for (i = 0; i < n; i += 2) {
|
|
330
|
|
331 if (i == zero) {
|
|
332 *dst++ = ':';
|
|
333 i += (max - 1) * 2;
|
|
334 continue;
|
|
335 }
|
|
336
|
|
337 dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
|
|
338
|
|
339 if (i < 14) {
|
|
340 *dst++ = ':';
|
|
341 }
|
|
342 }
|
|
343
|
|
344 if (n == 12) {
|
|
345 dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
|
|
346 }
|
|
347
|
|
348 return dst - text;
|
362
|
349 }
|
|
350
|
448
|
351 #endif
|
|
352
|
362
|
353
|
58
|
354 ngx_int_t
|
454
|
355 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
|
0
|
356 {
|
540
|
357 u_char *addr, *mask, *last;
|
|
358 size_t len;
|
|
359 ngx_int_t shift;
|
|
360 #if (NGX_HAVE_INET6)
|
|
361 ngx_int_t rc;
|
|
362 ngx_uint_t s, i;
|
|
363 #endif
|
0
|
364
|
400
|
365 addr = text->data;
|
|
366 last = addr + text->len;
|
0
|
367
|
400
|
368 mask = ngx_strlchr(addr, last, '/');
|
540
|
369 len = (mask ? mask : last) - addr;
|
0
|
370
|
540
|
371 cidr->u.in.addr = ngx_inet_addr(addr, len);
|
|
372
|
|
373 if (cidr->u.in.addr != INADDR_NONE) {
|
|
374 cidr->family = AF_INET;
|
|
375
|
|
376 if (mask == NULL) {
|
|
377 cidr->u.in.mask = 0xffffffff;
|
|
378 return NGX_OK;
|
|
379 }
|
400
|
380
|
540
|
381 #if (NGX_HAVE_INET6)
|
|
382 } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
|
|
383 cidr->family = AF_INET6;
|
|
384
|
|
385 if (mask == NULL) {
|
|
386 ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
|
|
387 return NGX_OK;
|
|
388 }
|
|
389
|
|
390 #endif
|
|
391 } else {
|
0
|
392 return NGX_ERROR;
|
|
393 }
|
|
394
|
400
|
395 mask++;
|
|
396
|
|
397 shift = ngx_atoi(mask, last - mask);
|
|
398 if (shift == NGX_ERROR) {
|
0
|
399 return NGX_ERROR;
|
|
400 }
|
|
401
|
540
|
402 switch (cidr->family) {
|
454
|
403
|
540
|
404 #if (NGX_HAVE_INET6)
|
|
405 case AF_INET6:
|
670
|
406 if (shift > 128) {
|
|
407 return NGX_ERROR;
|
|
408 }
|
|
409
|
540
|
410 addr = cidr->u.in6.addr.s6_addr;
|
|
411 mask = cidr->u.in6.mask.s6_addr;
|
|
412 rc = NGX_OK;
|
|
413
|
|
414 for (i = 0; i < 16; i++) {
|
|
415
|
|
416 s = (shift > 8) ? 8 : shift;
|
|
417 shift -= s;
|
|
418
|
670
|
419 mask[i] = (u_char) (0xffu << (8 - s));
|
0
|
420
|
540
|
421 if (addr[i] != (addr[i] & mask[i])) {
|
|
422 rc = NGX_DONE;
|
|
423 addr[i] &= mask[i];
|
|
424 }
|
|
425 }
|
|
426
|
|
427 return rc;
|
|
428 #endif
|
0
|
429
|
540
|
430 default: /* AF_INET */
|
670
|
431 if (shift > 32) {
|
|
432 return NGX_ERROR;
|
|
433 }
|
540
|
434
|
|
435 if (shift) {
|
670
|
436 cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
|
400
|
437
|
540
|
438 } else {
|
|
439 /* x86 compilers use a shl instruction that shifts by modulo 32 */
|
|
440 cidr->u.in.mask = 0;
|
|
441 }
|
|
442
|
|
443 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
|
400
|
444 return NGX_OK;
|
|
445 }
|
|
446
|
540
|
447 cidr->u.in.addr &= cidr->u.in.mask;
|
|
448
|
400
|
449 return NGX_DONE;
|
0
|
450 }
|
540
|
451 }
|
|
452
|
|
453
|
|
454 ngx_int_t
|
|
455 ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
|
|
456 {
|
|
457 in_addr_t inaddr;
|
|
458 ngx_uint_t family;
|
|
459 struct sockaddr_in *sin;
|
|
460 #if (NGX_HAVE_INET6)
|
|
461 struct in6_addr inaddr6;
|
|
462 struct sockaddr_in6 *sin6;
|
|
463
|
|
464 /*
|
670
|
465 * prevent MSVC8 warning:
|
540
|
466 * potentially uninitialized local variable 'inaddr6' used
|
|
467 */
|
|
468 ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
|
|
469 #endif
|
|
470
|
|
471 inaddr = ngx_inet_addr(text, len);
|
|
472
|
|
473 if (inaddr != INADDR_NONE) {
|
|
474 family = AF_INET;
|
|
475 len = sizeof(struct sockaddr_in);
|
|
476
|
|
477 #if (NGX_HAVE_INET6)
|
|
478 } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
|
|
479 family = AF_INET6;
|
|
480 len = sizeof(struct sockaddr_in6);
|
|
481
|
|
482 #endif
|
|
483 } else {
|
|
484 return NGX_DECLINED;
|
|
485 }
|
0
|
486
|
540
|
487 addr->sockaddr = ngx_pcalloc(pool, len);
|
|
488 if (addr->sockaddr == NULL) {
|
|
489 return NGX_ERROR;
|
326
|
490 }
|
|
491
|
540
|
492 addr->sockaddr->sa_family = (u_char) family;
|
|
493 addr->socklen = len;
|
|
494
|
|
495 switch (family) {
|
326
|
496
|
540
|
497 #if (NGX_HAVE_INET6)
|
|
498 case AF_INET6:
|
|
499 sin6 = (struct sockaddr_in6 *) addr->sockaddr;
|
|
500 ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
|
|
501 break;
|
|
502 #endif
|
|
503
|
|
504 default: /* AF_INET */
|
|
505 sin = (struct sockaddr_in *) addr->sockaddr;
|
|
506 sin->sin_addr.s_addr = inaddr;
|
|
507 break;
|
|
508 }
|
|
509
|
|
510 return NGX_OK;
|
0
|
511 }
|
|
512
|
|
513
|
200
|
514 ngx_int_t
|
340
|
515 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
|
200
|
516 {
|
400
|
517 u_char *p;
|
200
|
518
|
|
519 p = u->url.data;
|
|
520
|
286
|
521 if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
|
400
|
522 return ngx_parse_unix_domain_url(pool, u);
|
200
|
523 }
|
|
524
|
|
525 if ((p[0] == ':' || p[0] == '/') && !u->listen) {
|
|
526 u->err = "invalid host";
|
|
527 return NGX_ERROR;
|
|
528 }
|
|
529
|
448
|
530 if (p[0] == '[') {
|
|
531 return ngx_parse_inet6_url(pool, u);
|
|
532 }
|
|
533
|
400
|
534 return ngx_parse_inet_url(pool, u);
|
|
535 }
|
266
|
536
|
200
|
537
|
400
|
538 static ngx_int_t
|
|
539 ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
|
|
540 {
|
|
541 #if (NGX_HAVE_UNIX_DOMAIN)
|
|
542 u_char *path, *uri, *last;
|
|
543 size_t len;
|
|
544 struct sockaddr_un *saun;
|
200
|
545
|
400
|
546 len = u->url.len;
|
|
547 path = u->url.data;
|
200
|
548
|
400
|
549 path += 5;
|
|
550 len -= 5;
|
|
551
|
|
552 if (u->uri_part) {
|
200
|
553
|
400
|
554 last = path + len;
|
|
555 uri = ngx_strlchr(path, last, ':');
|
200
|
556
|
400
|
557 if (uri) {
|
|
558 len = uri - path;
|
|
559 uri++;
|
|
560 u->uri.len = last - uri;
|
|
561 u->uri.data = uri;
|
200
|
562 }
|
|
563 }
|
|
564
|
400
|
565 if (len == 0) {
|
|
566 u->err = "no path in the unix domain socket";
|
|
567 return NGX_ERROR;
|
|
568 }
|
|
569
|
|
570 u->host.len = len++;
|
|
571 u->host.data = path;
|
|
572
|
|
573 if (len > sizeof(saun->sun_path)) {
|
|
574 u->err = "too long path in the unix domain socket";
|
|
575 return NGX_ERROR;
|
|
576 }
|
200
|
577
|
448
|
578 u->socklen = sizeof(struct sockaddr_un);
|
|
579 saun = (struct sockaddr_un *) &u->sockaddr;
|
|
580 saun->sun_family = AF_UNIX;
|
|
581 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
|
|
582
|
540
|
583 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
|
400
|
584 if (u->addrs == NULL) {
|
|
585 return NGX_ERROR;
|
|
586 }
|
|
587
|
|
588 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
|
|
589 if (saun == NULL) {
|
|
590 return NGX_ERROR;
|
|
591 }
|
|
592
|
448
|
593 u->family = AF_UNIX;
|
400
|
594 u->naddrs = 1;
|
|
595
|
|
596 saun->sun_family = AF_UNIX;
|
|
597 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
|
|
598
|
|
599 u->addrs[0].sockaddr = (struct sockaddr *) saun;
|
|
600 u->addrs[0].socklen = sizeof(struct sockaddr_un);
|
|
601 u->addrs[0].name.len = len + 4;
|
|
602 u->addrs[0].name.data = u->url.data;
|
200
|
603
|
400
|
604 return NGX_OK;
|
|
605
|
|
606 #else
|
|
607
|
|
608 u->err = "the unix domain sockets are not supported on this platform";
|
|
609
|
|
610 return NGX_ERROR;
|
|
611
|
|
612 #endif
|
|
613 }
|
|
614
|
|
615
|
|
616 static ngx_int_t
|
|
617 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
|
|
618 {
|
448
|
619 u_char *p, *host, *port, *last, *uri, *args;
|
|
620 size_t len;
|
|
621 ngx_int_t n;
|
|
622 struct hostent *h;
|
|
623 struct sockaddr_in *sin;
|
|
624
|
|
625 u->socklen = sizeof(struct sockaddr_in);
|
|
626 sin = (struct sockaddr_in *) &u->sockaddr;
|
|
627 sin->sin_family = AF_INET;
|
400
|
628
|
|
629 u->family = AF_INET;
|
|
630
|
|
631 host = u->url.data;
|
|
632
|
|
633 last = host + u->url.len;
|
|
634
|
|
635 port = ngx_strlchr(host, last, ':');
|
|
636
|
416
|
637 uri = ngx_strlchr(host, last, '/');
|
|
638
|
|
639 args = ngx_strlchr(host, last, '?');
|
|
640
|
|
641 if (args) {
|
|
642 if (uri == NULL) {
|
|
643 uri = args;
|
|
644
|
|
645 } else if (args < uri) {
|
|
646 uri = args;
|
|
647 }
|
|
648 }
|
400
|
649
|
|
650 if (uri) {
|
|
651 if (u->listen || !u->uri_part) {
|
|
652 u->err = "invalid host";
|
|
653 return NGX_ERROR;
|
200
|
654 }
|
|
655
|
400
|
656 u->uri.len = last - uri;
|
|
657 u->uri.data = uri;
|
|
658
|
|
659 last = uri;
|
416
|
660
|
|
661 if (uri < port) {
|
|
662 port = NULL;
|
418
|
663 }
|
400
|
664 }
|
200
|
665
|
400
|
666 if (port) {
|
|
667 port++;
|
|
668
|
|
669 len = last - port;
|
|
670
|
|
671 if (len == 0) {
|
200
|
672 u->err = "invalid port";
|
|
673 return NGX_ERROR;
|
|
674 }
|
|
675
|
400
|
676 n = ngx_atoi(port, len);
|
200
|
677
|
646
|
678 if (n < 1 || n > 65535) {
|
400
|
679 u->err = "invalid port";
|
|
680 return NGX_ERROR;
|
252
|
681 }
|
|
682
|
400
|
683 u->port = (in_port_t) n;
|
448
|
684 sin->sin_port = htons((in_port_t) n);
|
252
|
685
|
400
|
686 u->port_text.len = len;
|
|
687 u->port_text.data = port;
|
|
688
|
|
689 last = port - 1;
|
252
|
690
|
400
|
691 } else {
|
|
692 if (uri == NULL) {
|
252
|
693
|
400
|
694 if (u->listen) {
|
252
|
695
|
400
|
696 /* test value as port only */
|
|
697
|
|
698 n = ngx_atoi(host, last - host);
|
252
|
699
|
400
|
700 if (n != NGX_ERROR) {
|
|
701
|
646
|
702 if (n < 1 || n > 65535) {
|
400
|
703 u->err = "invalid port";
|
|
704 return NGX_ERROR;
|
|
705 }
|
252
|
706
|
400
|
707 u->port = (in_port_t) n;
|
448
|
708 sin->sin_port = htons((in_port_t) n);
|
400
|
709
|
|
710 u->port_text.len = last - host;
|
|
711 u->port_text.data = host;
|
|
712
|
448
|
713 u->wildcard = 1;
|
|
714
|
400
|
715 return NGX_OK;
|
252
|
716 }
|
|
717 }
|
|
718 }
|
|
719
|
400
|
720 u->no_port = 1;
|
200
|
721 }
|
|
722
|
400
|
723 len = last - host;
|
|
724
|
|
725 if (len == 0) {
|
200
|
726 u->err = "no host";
|
|
727 return NGX_ERROR;
|
|
728 }
|
|
729
|
400
|
730 if (len == 1 && *host == '*') {
|
|
731 len = 0;
|
|
732 }
|
|
733
|
|
734 u->host.len = len;
|
|
735 u->host.data = host;
|
|
736
|
260
|
737 if (u->no_resolve) {
|
|
738 return NGX_OK;
|
200
|
739 }
|
|
740
|
540
|
741 if (len) {
|
|
742 sin->sin_addr.s_addr = ngx_inet_addr(host, len);
|
400
|
743
|
448
|
744 if (sin->sin_addr.s_addr == INADDR_NONE) {
|
540
|
745 p = ngx_alloc(++len, pool->log);
|
|
746 if (p == NULL) {
|
|
747 return NGX_ERROR;
|
|
748 }
|
|
749
|
|
750 (void) ngx_cpystrn(p, host, len);
|
|
751
|
400
|
752 h = gethostbyname((const char *) p);
|
|
753
|
540
|
754 ngx_free(p);
|
|
755
|
400
|
756 if (h == NULL || h->h_addr_list[0] == NULL) {
|
|
757 u->err = "host not found";
|
|
758 return NGX_ERROR;
|
|
759 }
|
|
760
|
448
|
761 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
|
|
762 }
|
|
763
|
|
764 if (sin->sin_addr.s_addr == INADDR_ANY) {
|
|
765 u->wildcard = 1;
|
400
|
766 }
|
|
767
|
|
768 } else {
|
448
|
769 sin->sin_addr.s_addr = INADDR_ANY;
|
|
770 u->wildcard = 1;
|
400
|
771 }
|
|
772
|
266
|
773 if (u->no_port) {
|
|
774 u->port = u->default_port;
|
448
|
775 sin->sin_port = htons(u->default_port);
|
266
|
776 }
|
|
777
|
400
|
778 if (u->listen) {
|
|
779 return NGX_OK;
|
266
|
780 }
|
|
781
|
340
|
782 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
|
200
|
783 return NGX_ERROR;
|
|
784 }
|
|
785
|
|
786 return NGX_OK;
|
|
787 }
|
|
788
|
|
789
|
448
|
790 static ngx_int_t
|
|
791 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
|
|
792 {
|
|
793 #if (NGX_HAVE_INET6)
|
|
794 u_char *p, *host, *port, *last, *uri;
|
|
795 size_t len;
|
|
796 ngx_int_t n;
|
|
797 struct sockaddr_in6 *sin6;
|
|
798
|
|
799 u->socklen = sizeof(struct sockaddr_in6);
|
|
800 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
|
|
801 sin6->sin6_family = AF_INET6;
|
|
802
|
|
803 host = u->url.data + 1;
|
|
804
|
|
805 last = u->url.data + u->url.len;
|
|
806
|
|
807 p = ngx_strlchr(host, last, ']');
|
|
808
|
|
809 if (p == NULL) {
|
|
810 u->err = "invalid host";
|
|
811 return NGX_ERROR;
|
|
812 }
|
|
813
|
|
814 if (last - p) {
|
|
815
|
|
816 port = p + 1;
|
|
817
|
|
818 uri = ngx_strlchr(port, last, '/');
|
|
819
|
|
820 if (uri) {
|
|
821 if (u->listen || !u->uri_part) {
|
|
822 u->err = "invalid host";
|
|
823 return NGX_ERROR;
|
|
824 }
|
|
825
|
|
826 u->uri.len = last - uri;
|
|
827 u->uri.data = uri;
|
|
828 }
|
|
829
|
|
830 if (*port == ':') {
|
|
831 port++;
|
|
832
|
|
833 len = last - port;
|
|
834
|
|
835 if (len == 0) {
|
|
836 u->err = "invalid port";
|
|
837 return NGX_ERROR;
|
|
838 }
|
|
839
|
|
840 n = ngx_atoi(port, len);
|
|
841
|
646
|
842 if (n < 1 || n > 65535) {
|
448
|
843 u->err = "invalid port";
|
|
844 return NGX_ERROR;
|
|
845 }
|
|
846
|
|
847 u->port = (in_port_t) n;
|
|
848 sin6->sin6_port = htons((in_port_t) n);
|
|
849
|
|
850 u->port_text.len = len;
|
|
851 u->port_text.data = port;
|
|
852
|
|
853 } else {
|
|
854 u->no_port = 1;
|
|
855 }
|
|
856 }
|
|
857
|
|
858 len = p - host;
|
|
859
|
|
860 if (len == 0) {
|
|
861 u->err = "no host";
|
|
862 return NGX_ERROR;
|
|
863 }
|
|
864
|
540
|
865 u->host.len = len;
|
448
|
866 u->host.data = host;
|
|
867
|
540
|
868 if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
|
448
|
869 u->err = "invalid IPv6 address";
|
|
870 return NGX_ERROR;
|
|
871 }
|
|
872
|
|
873 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
|
874 u->wildcard = 1;
|
|
875 }
|
|
876
|
|
877 u->family = AF_INET6;
|
|
878
|
|
879 if (u->no_resolve) {
|
|
880 return NGX_OK;
|
|
881 }
|
|
882
|
|
883 if (u->no_port) {
|
|
884 u->port = u->default_port;
|
|
885 sin6->sin6_port = htons(u->default_port);
|
|
886 }
|
|
887
|
|
888 return NGX_OK;
|
|
889
|
|
890 #else
|
|
891
|
|
892 u->err = "the INET6 sockets are not supported on this platform";
|
|
893
|
|
894 return NGX_ERROR;
|
|
895
|
|
896 #endif
|
|
897 }
|
|
898
|
|
899
|
260
|
900 ngx_int_t
|
340
|
901 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
|
200
|
902 {
|
266
|
903 u_char *p, *host;
|
200
|
904 size_t len;
|
448
|
905 in_port_t port;
|
200
|
906 in_addr_t in_addr;
|
|
907 ngx_uint_t i;
|
|
908 struct hostent *h;
|
|
909 struct sockaddr_in *sin;
|
|
910
|
|
911 /* AF_INET only */
|
|
912
|
450
|
913 port = htons(u->port);
|
448
|
914
|
540
|
915 in_addr = ngx_inet_addr(u->host.data, u->host.len);
|
200
|
916
|
|
917 if (in_addr == INADDR_NONE) {
|
540
|
918 host = ngx_alloc(u->host.len + 1, pool->log);
|
|
919 if (host == NULL) {
|
|
920 return NGX_ERROR;
|
|
921 }
|
|
922
|
|
923 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
|
|
924
|
200
|
925 h = gethostbyname((char *) host);
|
|
926
|
340
|
927 ngx_free(host);
|
|
928
|
200
|
929 if (h == NULL || h->h_addr_list[0] == NULL) {
|
260
|
930 u->err = "host not found";
|
|
931 return NGX_ERROR;
|
200
|
932 }
|
|
933
|
260
|
934 if (u->one_addr == 0) {
|
|
935 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
|
|
936
|
|
937 } else {
|
|
938 i = 1;
|
|
939 }
|
200
|
940
|
|
941 /* MP: ngx_shared_palloc() */
|
|
942
|
540
|
943 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
|
260
|
944 if (u->addrs == NULL) {
|
|
945 return NGX_ERROR;
|
200
|
946 }
|
|
947
|
260
|
948 u->naddrs = i;
|
200
|
949
|
614
|
950 for (i = 0; i < u->naddrs; i++) {
|
200
|
951
|
340
|
952 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
|
200
|
953 if (sin == NULL) {
|
260
|
954 return NGX_ERROR;
|
200
|
955 }
|
|
956
|
|
957 sin->sin_family = AF_INET;
|
448
|
958 sin->sin_port = port;
|
200
|
959 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
|
|
960
|
260
|
961 u->addrs[i].sockaddr = (struct sockaddr *) sin;
|
|
962 u->addrs[i].socklen = sizeof(struct sockaddr_in);
|
200
|
963
|
448
|
964 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
|
200
|
965
|
382
|
966 p = ngx_pnalloc(pool, len);
|
266
|
967 if (p == NULL) {
|
260
|
968 return NGX_ERROR;
|
200
|
969 }
|
|
970
|
448
|
971 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
|
200
|
972
|
448
|
973 u->addrs[i].name.len = len;
|
266
|
974 u->addrs[i].name.data = p;
|
200
|
975 }
|
|
976
|
|
977 } else {
|
|
978
|
|
979 /* MP: ngx_shared_palloc() */
|
|
980
|
540
|
981 u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
|
260
|
982 if (u->addrs == NULL) {
|
|
983 return NGX_ERROR;
|
200
|
984 }
|
|
985
|
340
|
986 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
|
200
|
987 if (sin == NULL) {
|
260
|
988 return NGX_ERROR;
|
200
|
989 }
|
|
990
|
260
|
991 u->naddrs = 1;
|
200
|
992
|
|
993 sin->sin_family = AF_INET;
|
448
|
994 sin->sin_port = port;
|
200
|
995 sin->sin_addr.s_addr = in_addr;
|
|
996
|
260
|
997 u->addrs[0].sockaddr = (struct sockaddr *) sin;
|
|
998 u->addrs[0].socklen = sizeof(struct sockaddr_in);
|
200
|
999
|
448
|
1000 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
|
266
|
1001 if (p == NULL) {
|
260
|
1002 return NGX_ERROR;
|
200
|
1003 }
|
|
1004
|
448
|
1005 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
|
|
1006 &u->host, ntohs(port)) - p;
|
266
|
1007 u->addrs[0].name.data = p;
|
200
|
1008 }
|
|
1009
|
260
|
1010 return NGX_OK;
|
200
|
1011 }
|