1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 static size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len);
12
13
14 /* AF_INET only */
15
16 in_addr_t
17 ngx_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 >= '' && c <= '9') {
32 octet = octet * 10 + (c - '');
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
59 /*
60 * ngx_sock_ntop() and ngx_inet_ntop() may be implemented as
61 * "ngx_sprintf(text, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3])", however,
62 * they had been implemented long before the ngx_sprintf() had appeared
63 * and they are faster by 1.5-2.5 times, so it is worth to keep them.
64 *
65 * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times
66 * than using FreeBSD libc's snprintf().
67 */
68
69 /* AF_INET only */
70
71 size_t
72 ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len)
73 {
74 u_char *p;
75 size_t n;
76 ngx_uint_t i;
77 struct sockaddr_in *sin;
78
79 if (len == 0) {
80 return 0;
81 }
82
83 if (family != AF_INET) {
84 return 0;
85 }
86
87 sin = (struct sockaddr_in *) sa;
88 p = (u_char *) &sin->sin_addr;
89
90 if (len > INET_ADDRSTRLEN) {
91 len = INET_ADDRSTRLEN;
92 }
93
94 n = ngx_sprint_uchar(text, p[0], len);
95
96 i = 1;
97
98 do {
99 if (len == n) {
100 text[n - 1] = '\0';
101 return n;
102 }
103
104 text[n++] = '.';
105
106 if (len == n) {
107 text[n - 1] = '\0';
108 return n;
109 }
110
111 n += ngx_sprint_uchar(&text[n], p[i++], len - n);
112
113 } while (i < 4);
114
115 if (len == n) {
116 text[n] = '\0';
117 return n;
118 }
119
120 text[n] = '\0';
121
122 return n;
123 }
124
125
126 size_t
127 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
128 {
129 u_char *p;
130 size_t n;
131 ngx_uint_t i;
132
133 if (len == 0) {
134 return 0;
135 }
136
137 if (family != AF_INET) {
138 return 0;
139 }
140
141 p = (u_char *) addr;
142
143 if (len > INET_ADDRSTRLEN) {
144 len = INET_ADDRSTRLEN;
145 }
146
147 n = ngx_sprint_uchar(text, p[0], len);
148
149 i = 1;
150
151 do {
152 if (len == n) {
153 text[n - 1] = '\0';
154 return n;
155 }
156
157 text[n++] = '.';
158
159 if (len == n) {
160 text[n - 1] = '\0';
161 return n;
162 }
163
164 n += ngx_sprint_uchar(&text[n], p[i++], len - n);
165
166 } while (i < 4);
167
168 if (len == n) {
169 text[n] = '\0';
170 return n;
171 }
172
173 text[n] = '\0';
174
175 return n;
176 }
177
178
179 static size_t
180 ngx_sprint_uchar(u_char *text, u_char c, size_t len)
181 {
182 size_t n;
183 ngx_uint_t c1, c2;
184
185 n = 0;
186
187 if (len == n) {
188 return n;
189 }
190
191 c1 = c / 100;
192
193 if (c1) {
194 *text++ = (u_char) (c1 + '');
195 n++;
196
197 if (len == n) {
198 return n;
199 }
200 }
201
202 c2 = (c % 100) / 10;
203
204 if (c1 || c2) {
205 *text++ = (u_char) (c2 + '');
206 n++;
207
208 if (len == n) {
209 return n;
210 }
211 }
212
213 c2 = c % 10;
214
215 *text = (u_char) (c2 + '');
216 n++;
217
218 return n;
219 }
220
221
222 /* AF_INET only */
223
224 ngx_int_t
225 ngx_ptocidr(ngx_str_t *text, void *cidr)
226 {
227 ngx_int_t m;
228 ngx_uint_t i;
229 ngx_inet_cidr_t *in_cidr;
230
231 in_cidr = cidr;
232
233 for (i = 0; i < text->len; i++) {
234 if (text->data[i] == '/') {
235 break;
236 }
237 }
238
239 if (i == text->len) {
240 return NGX_ERROR;
241 }
242
243 text->data[i] = '\0';
244 in_cidr->addr = inet_addr((char *) text->data);
245 text->data[i] = '/';
246 if (in_cidr->addr == INADDR_NONE) {
247 return NGX_ERROR;
248 }
249
250 m = ngx_atoi(&text->data[i + 1], text->len - (i + 1));
251 if (m == NGX_ERROR) {
252 return NGX_ERROR;
253 }
254
255 if (m == 0) {
256
257 /* the x86 compilers use the shl instruction that shifts by modulo 32 */
258
259 in_cidr->mask = 0;
260 return NGX_OK;
261 }
262
263 in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - m))));
264
265 if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
266 return NGX_OK;
267 }
268
269 in_cidr->addr &= in_cidr->mask;
270
271 return NGX_DONE;
272 }
273
274
275 ngx_int_t
276 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
277 {
278 u_char *p, *host, *port_start;
279 size_t len, port_len;
280 ngx_int_t port;
281 ngx_uint_t i;
282 struct hostent *h;
283 #if (NGX_HAVE_UNIX_DOMAIN)
284 struct sockaddr_un *saun;
285 #endif
286
287 len = u->url.len;
288 p = u->url.data;
289
290 if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
291
292 #if (NGX_HAVE_UNIX_DOMAIN)
293
294 p += 5;
295 len -= 5;
296
297 u->uri.len = len;
298 u->uri.data = p;
299
300 if (u->uri_part) {
301 for (i = 0; i < len; i++) {
302
303 if (p[i] == ':') {
304 len = i;
305
306 u->uri.len -= len + 1;
307 u->uri.data += len + 1;
308
309 break;
310 }
311 }
312 }
313
314 if (len == 0) {
315 u->err = "no path in the unix domain socket";
316 return NGX_ERROR;
317 }
318
319 if (len + 1 > sizeof(saun->sun_path)) {
320 u->err = "too long path in the unix domain socket";
321 return NGX_ERROR;
322 }
323
324 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
325 if (u->addrs == NULL) {
326 return NGX_ERROR;
327 }
328
329 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
330 if (saun == NULL) {
331 return NGX_ERROR;
332 }
333
334 u->naddrs = 1;
335
336 saun->sun_family = AF_UNIX;
337 (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1);
338
339 u->addrs[0].sockaddr = (struct sockaddr *) saun;
340 u->addrs[0].socklen = sizeof(struct sockaddr_un);
341 u->addrs[0].name.len = len + 5;
342 u->addrs[0].name.data = u->url.data;
343
344 u->host.len = len;
345 u->host.data = p;
346
347 u->unix_socket = 1;
348
349 return NGX_OK;
350
351 #else
352 u->err = "the unix domain sockets are not supported on this platform";
353
354 return NGX_ERROR;
355
356 #endif
357 }
358
359 if ((p[0] == ':' || p[0] == '/') && !u->listen) {
360 u->err = "invalid host";
361 return NGX_ERROR;
362 }
363
364 u->host.data = p;
365
366 port_start = NULL;
367 port_len = 0;
368
369 for (i = 0; i < len; i++) {
370
371 if (p[i] == ':') {
372 port_start = &p[i + 1];
373 u->host.len = i;
374
375 if (!u->uri_part) {
376 port_len = len - (i + 1);
377 break;
378 }
379 }
380
381 if (p[i] == '/') {
382 u->uri.len = len - i;
383 u->uri.data = &p[i];
384
385 if (u->host.len == 0) {
386 u->host.len = i;
387 }
388
389 if (port_start == NULL) {
390 u->no_port = 1;
391 goto no_port;
392 }
393
394 port_len = &p[i] - port_start;
395
396 if (port_len == 0) {
397 u->err = "invalid port";
398 return NGX_ERROR;
399 }
400
401 break;
402 }
403 }
404
405 if (port_start) {
406
407 if (port_len == 0) {
408 port_len = &p[i] - port_start;
409
410 if (port_len == 0) {
411 u->err = "invalid port";
412 return NGX_ERROR;
413 }
414 }
415
416 port = ngx_atoi(port_start, port_len);
417
418 if (port == NGX_ERROR || port < 1 || port > 65536) {
419 u->err = "invalid port";
420 return NGX_ERROR;
421 }
422
423 u->port_text.len = port_len;
424 u->port_text.data = port_start;
425
426 } else {
427 port = ngx_atoi(p, len);
428
429 if (port == NGX_ERROR) {
430 u->host.len = len;
431 u->no_port = 1;
432
433 goto no_port;
434 }
435
436 u->wildcard = 1;
437 }
438
439 u->port = (in_port_t) port;
440
441 no_port:
442
443 if (u->listen) {
444
445 if (u->port == 0) {
446 if (u->default_port == 0) {
447 u->err = "no port";
448 return NGX_ERROR;
449 }
450
451 u->port = u->default_port;
452 }
453
454 if (u->host.len == 1 && u->host.data[0] == '*') {
455 u->host.len = 0;
456 }
457
458 /* AF_INET only */
459
460 if (u->host.len) {
461
462 host = ngx_alloc(u->host.len + 1, pool->log);
463 if (host == NULL) {
464 return NGX_ERROR;
465 }
466
467 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
468
469 u->addr.in_addr = inet_addr((const char *) host);
470
471 if (u->addr.in_addr == INADDR_NONE) {
472 h = gethostbyname((const char *) host);
473
474 if (h == NULL || h->h_addr_list[0] == NULL) {
475 ngx_free(host);
476 u->err = "host not found";
477 return NGX_ERROR;
478 }
479
480 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
481 }
482
483 ngx_free(host);
484
485 } else {
486 u->addr.in_addr = INADDR_ANY;
487 }
488
489 return NGX_OK;
490 }
491
492 if (u->host.len == 0) {
493 u->err = "no host";
494 return NGX_ERROR;
495 }
496
497 if (u->no_resolve) {
498 return NGX_OK;
499 }
500
501 if (u->no_port) {
502 u->port = u->default_port;
503 }
504
505 if (u->port == 0) {
506 u->err = "no port";
507 return NGX_ERROR;
508 }
509
510 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
511 return NGX_ERROR;
512 }
513
514 return NGX_OK;
515 }
516
517
518 ngx_int_t
519 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
520 {
521 u_char *p, *host;
522 size_t len;
523 in_addr_t in_addr;
524 ngx_uint_t i;
525 struct hostent *h;
526 struct sockaddr_in *sin;
527
528 host = ngx_alloc(u->host.len + 1, pool->log);
529 if (host == NULL) {
530 return NGX_ERROR;
531 }
532
533 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
534
535 /* AF_INET only */
536
537 in_addr = inet_addr((char *) host);
538
539 if (in_addr == INADDR_NONE) {
540 h = gethostbyname((char *) host);
541
542 ngx_free(host);
543
544 if (h == NULL || h->h_addr_list[0] == NULL) {
545 u->err = "host not found";
546 return NGX_ERROR;
547 }
548
549 if (u->one_addr == 0) {
550 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
551
552 } else {
553 i = 1;
554 }
555
556 /* MP: ngx_shared_palloc() */
557
558 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
559 if (u->addrs == NULL) {
560 return NGX_ERROR;
561 }
562
563 u->naddrs = i;
564
565 for (i = 0; h->h_addr_list[i] != NULL; i++) {
566
567 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
568 if (sin == NULL) {
569 return NGX_ERROR;
570 }
571
572 sin->sin_family = AF_INET;
573 sin->sin_port = htons(u->port);
574 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
575
576 u->addrs[i].sockaddr = (struct sockaddr *) sin;
577 u->addrs[i].socklen = sizeof(struct sockaddr_in);
578
579 len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
580
581 p = ngx_palloc(pool, len);
582 if (p == NULL) {
583 return NGX_ERROR;
584 }
585
586 len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, p, len);
587
588 u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p;
589 u->addrs[i].name.data = p;
590 }
591
592 } else {
593
594 ngx_free(host);
595
596 /* MP: ngx_shared_palloc() */
597
598 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
599 if (u->addrs == NULL) {
600 return NGX_ERROR;
601 }
602
603 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
604 if (sin == NULL) {
605 return NGX_ERROR;
606 }
607
608 u->naddrs = 1;
609
610 sin->sin_family = AF_INET;
611 sin->sin_port = htons(u->port);
612 sin->sin_addr.s_addr = in_addr;
613
614 u->addrs[0].sockaddr = (struct sockaddr *) sin;
615 u->addrs[0].socklen = sizeof(struct sockaddr_in);
616
617 p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
618 if (p == NULL) {
619 return NGX_ERROR;
620 }
621
622 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p;
623 u->addrs[0].name.data = p;
624 }
625
626 return NGX_OK;
627 }
628
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.