3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
14 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
15 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
16 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
20 ngx_inet_addr(u_char *text, size_t len)
30 for (p = text; p < text + len; p++) {
34 if (c >= '0' && c <= '9') {
35 octet = octet * 10 + (c - '0');
39 if (c == '.' && octet < 256) {
40 addr = (addr << 8) + octet;
54 addr = (addr << 8) + octet;
63 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
66 struct sockaddr_in *sin;
69 struct sockaddr_in6 *sin6;
72 switch (sa->sa_family) {
76 sin = (struct sockaddr_in *) sa;
77 p = (u_char *) &sin->sin_addr;
80 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
81 p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
83 p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
84 p[0], p[1], p[2], p[3]);
93 sin6 = (struct sockaddr_in6 *) sa;
101 n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len);
104 n = ngx_sprintf(&text[1 + n], "]:%d",
105 ntohs(sin6->sin6_port)) - text;
118 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
128 return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
129 p[0], p[1], p[2], p[3])
135 return ngx_inet6_ntop(addr, text, len);
148 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
152 ngx_uint_t i, zero, last;
154 if (len < NGX_INET6_ADDRSTRLEN) {
158 zero = (ngx_uint_t) -1;
159 last = (ngx_uint_t) -1;
163 for (i = 0; i < 16; i += 2) {
165 if (p[i] || p[i + 1]) {
191 if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
193 || (max == 7 && p[14] != 0 && p[15] != 1))
201 for (i = 0; i < n; i += 2) {
209 dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
217 dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
229 ngx_ptocidr(ngx_str_t *text, void *cidr)
231 u_char *addr, *mask, *last;
233 ngx_inet_cidr_t *in_cidr;
237 last = addr + text->len;
239 mask = ngx_strlchr(addr, last, '/');
241 in_cidr->addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
243 if (in_cidr->addr == INADDR_NONE) {
248 in_cidr->mask = 0xffffffff;
254 shift = ngx_atoi(mask, last - mask);
255 if (shift == NGX_ERROR) {
261 /* the x86 compilers use the shl instruction that shifts by modulo 32 */
265 if (in_cidr->addr == 0) {
272 in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
274 if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
278 in_cidr->addr &= in_cidr->mask;
285 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
291 if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
292 return ngx_parse_unix_domain_url(pool, u);
295 if ((p[0] == ':' || p[0] == '/') && !u->listen) {
296 u->err = "invalid host";
301 return ngx_parse_inet6_url(pool, u);
304 return ngx_parse_inet_url(pool, u);
309 ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
311 #if (NGX_HAVE_UNIX_DOMAIN)
312 u_char *path, *uri, *last;
314 struct sockaddr_un *saun;
325 uri = ngx_strlchr(path, last, ':');
330 u->uri.len = last - uri;
336 u->err = "no path in the unix domain socket";
343 if (len > sizeof(saun->sun_path)) {
344 u->err = "too long path in the unix domain socket";
348 u->socklen = sizeof(struct sockaddr_un);
349 saun = (struct sockaddr_un *) &u->sockaddr;
350 saun->sun_family = AF_UNIX;
351 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
353 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
354 if (u->addrs == NULL) {
358 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
366 saun->sun_family = AF_UNIX;
367 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
369 u->addrs[0].sockaddr = (struct sockaddr *) saun;
370 u->addrs[0].socklen = sizeof(struct sockaddr_un);
371 u->addrs[0].name.len = len + 4;
372 u->addrs[0].name.data = u->url.data;
378 u->err = "the unix domain sockets are not supported on this platform";
387 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
389 u_char *p, *host, *port, *last, *uri, *args;
393 struct sockaddr_in *sin;
395 u->socklen = sizeof(struct sockaddr_in);
396 sin = (struct sockaddr_in *) &u->sockaddr;
397 sin->sin_family = AF_INET;
403 last = host + u->url.len;
405 port = ngx_strlchr(host, last, ':');
407 uri = ngx_strlchr(host, last, '/');
409 args = ngx_strlchr(host, last, '?');
415 } else if (args < uri) {
421 if (u->listen || !u->uri_part) {
422 u->err = "invalid host";
426 u->uri.len = last - uri;
442 u->err = "invalid port";
446 n = ngx_atoi(port, len);
448 if (n < 1 || n > 65536) {
449 u->err = "invalid port";
453 u->port = (in_port_t) n;
454 sin->sin_port = htons((in_port_t) n);
456 u->port_text.len = len;
457 u->port_text.data = port;
466 /* test value as port only */
468 n = ngx_atoi(host, last - host);
470 if (n != NGX_ERROR) {
472 if (n < 1 || n > 65536) {
473 u->err = "invalid port";
477 u->port = (in_port_t) n;
478 sin->sin_port = htons((in_port_t) n);
480 u->port_text.len = last - host;
481 u->port_text.data = host;
500 if (len == 1 && *host == '*') {
513 p = ngx_alloc(len, pool->log);
518 (void) ngx_cpystrn(p, host, len);
520 u->addr.in_addr = inet_addr((const char *) p);
521 sin->sin_addr.s_addr = inet_addr((const char *) p);
523 if (sin->sin_addr.s_addr == INADDR_NONE) {
524 h = gethostbyname((const char *) p);
526 if (h == NULL || h->h_addr_list[0] == NULL) {
528 u->err = "host not found";
532 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
533 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
536 if (sin->sin_addr.s_addr == INADDR_ANY) {
543 u->addr.in_addr = INADDR_ANY;
544 sin->sin_addr.s_addr = INADDR_ANY;
549 u->port = u->default_port;
550 sin->sin_port = htons(u->default_port);
557 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
566 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
570 u_char *p, *host, *port, *last, *uri;
573 struct sockaddr_in6 *sin6;
575 u->socklen = sizeof(struct sockaddr_in6);
576 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
577 sin6->sin6_family = AF_INET6;
579 host = u->url.data + 1;
581 last = u->url.data + u->url.len;
583 p = ngx_strlchr(host, last, ']');
586 u->err = "invalid host";
594 uri = ngx_strlchr(port, last, '/');
597 if (u->listen || !u->uri_part) {
598 u->err = "invalid host";
602 u->uri.len = last - uri;
612 u->err = "invalid port";
616 n = ngx_atoi(port, len);
618 if (n < 1 || n > 65536) {
619 u->err = "invalid port";
623 u->port = (in_port_t) n;
624 sin6->sin6_port = htons((in_port_t) n);
626 u->port_text.len = len;
627 u->port_text.data = port;
644 p = ngx_alloc(len, pool->log);
649 (void) ngx_cpystrn(p, host, len);
651 rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
656 u->err = "invalid IPv6 address";
660 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
664 u->family = AF_INET6;
671 u->port = u->default_port;
672 sin6->sin6_port = htons(u->default_port);
679 u->err = "the INET6 sockets are not supported on this platform";
688 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
696 struct sockaddr_in *sin;
698 host = ngx_alloc(u->host.len + 1, pool->log);
703 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
707 port = htons(u->port);
709 in_addr = inet_addr((char *) host);
711 if (in_addr == INADDR_NONE) {
712 h = gethostbyname((char *) host);
716 if (h == NULL || h->h_addr_list[0] == NULL) {
717 u->err = "host not found";
721 if (u->one_addr == 0) {
722 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
728 /* MP: ngx_shared_palloc() */
730 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
731 if (u->addrs == NULL) {
737 for (i = 0; h->h_addr_list[i] != NULL; i++) {
739 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
744 sin->sin_family = AF_INET;
745 sin->sin_port = port;
746 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
748 u->addrs[i].sockaddr = (struct sockaddr *) sin;
749 u->addrs[i].socklen = sizeof(struct sockaddr_in);
751 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
753 p = ngx_pnalloc(pool, len);
758 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
760 u->addrs[i].name.len = len;
761 u->addrs[i].name.data = p;
768 /* MP: ngx_shared_palloc() */
770 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
771 if (u->addrs == NULL) {
775 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
782 sin->sin_family = AF_INET;
783 sin->sin_port = port;
784 sin->sin_addr.s_addr = in_addr;
786 u->addrs[0].sockaddr = (struct sockaddr *) sin;
787 u->addrs[0].socklen = sizeof(struct sockaddr_in);
789 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
794 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
795 &u->host, ntohs(port)) - p;
796 u->addrs[0].name.data = p;