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, ngx_cidr_t *cidr)
231 u_char *addr, *mask, *last;
235 last = addr + text->len;
237 mask = ngx_strlchr(addr, last, '/');
239 cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
241 if (cidr->u.in.addr == INADDR_NONE) {
246 cidr->family = AF_INET;
247 cidr->u.in.mask = 0xffffffff;
253 shift = ngx_atoi(mask, last - mask);
254 if (shift == NGX_ERROR) {
258 cidr->family = AF_INET;
262 /* the x86 compilers use the shl instruction that shifts by modulo 32 */
266 if (cidr->u.in.addr == 0) {
273 cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
275 if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
279 cidr->u.in.addr &= cidr->u.in.mask;
286 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
292 if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
293 return ngx_parse_unix_domain_url(pool, u);
296 if ((p[0] == ':' || p[0] == '/') && !u->listen) {
297 u->err = "invalid host";
302 return ngx_parse_inet6_url(pool, u);
305 return ngx_parse_inet_url(pool, u);
310 ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
312 #if (NGX_HAVE_UNIX_DOMAIN)
313 u_char *path, *uri, *last;
315 struct sockaddr_un *saun;
326 uri = ngx_strlchr(path, last, ':');
331 u->uri.len = last - uri;
337 u->err = "no path in the unix domain socket";
344 if (len > sizeof(saun->sun_path)) {
345 u->err = "too long path in the unix domain socket";
349 u->socklen = sizeof(struct sockaddr_un);
350 saun = (struct sockaddr_un *) &u->sockaddr;
351 saun->sun_family = AF_UNIX;
352 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
354 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
355 if (u->addrs == NULL) {
359 saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
367 saun->sun_family = AF_UNIX;
368 (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
370 u->addrs[0].sockaddr = (struct sockaddr *) saun;
371 u->addrs[0].socklen = sizeof(struct sockaddr_un);
372 u->addrs[0].name.len = len + 4;
373 u->addrs[0].name.data = u->url.data;
379 u->err = "the unix domain sockets are not supported on this platform";
388 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
390 u_char *p, *host, *port, *last, *uri, *args;
394 struct sockaddr_in *sin;
396 u->socklen = sizeof(struct sockaddr_in);
397 sin = (struct sockaddr_in *) &u->sockaddr;
398 sin->sin_family = AF_INET;
404 last = host + u->url.len;
406 port = ngx_strlchr(host, last, ':');
408 uri = ngx_strlchr(host, last, '/');
410 args = ngx_strlchr(host, last, '?');
416 } else if (args < uri) {
422 if (u->listen || !u->uri_part) {
423 u->err = "invalid host";
427 u->uri.len = last - uri;
443 u->err = "invalid port";
447 n = ngx_atoi(port, len);
449 if (n < 1 || n > 65536) {
450 u->err = "invalid port";
454 u->port = (in_port_t) n;
455 sin->sin_port = htons((in_port_t) n);
457 u->port_text.len = len;
458 u->port_text.data = port;
467 /* test value as port only */
469 n = ngx_atoi(host, last - host);
471 if (n != NGX_ERROR) {
473 if (n < 1 || n > 65536) {
474 u->err = "invalid port";
478 u->port = (in_port_t) n;
479 sin->sin_port = htons((in_port_t) n);
481 u->port_text.len = last - host;
482 u->port_text.data = host;
501 if (len == 1 && *host == '*') {
514 p = ngx_alloc(len, pool->log);
519 (void) ngx_cpystrn(p, host, len);
521 u->addr.in_addr = inet_addr((const char *) p);
522 sin->sin_addr.s_addr = inet_addr((const char *) p);
524 if (sin->sin_addr.s_addr == INADDR_NONE) {
525 h = gethostbyname((const char *) p);
527 if (h == NULL || h->h_addr_list[0] == NULL) {
529 u->err = "host not found";
533 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
534 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
537 if (sin->sin_addr.s_addr == INADDR_ANY) {
544 u->addr.in_addr = INADDR_ANY;
545 sin->sin_addr.s_addr = INADDR_ANY;
550 u->port = u->default_port;
551 sin->sin_port = htons(u->default_port);
558 if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
567 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
571 u_char *p, *host, *port, *last, *uri;
574 struct sockaddr_in6 *sin6;
576 u->socklen = sizeof(struct sockaddr_in6);
577 sin6 = (struct sockaddr_in6 *) &u->sockaddr;
578 sin6->sin6_family = AF_INET6;
580 host = u->url.data + 1;
582 last = u->url.data + u->url.len;
584 p = ngx_strlchr(host, last, ']');
587 u->err = "invalid host";
595 uri = ngx_strlchr(port, last, '/');
598 if (u->listen || !u->uri_part) {
599 u->err = "invalid host";
603 u->uri.len = last - uri;
613 u->err = "invalid port";
617 n = ngx_atoi(port, len);
619 if (n < 1 || n > 65536) {
620 u->err = "invalid port";
624 u->port = (in_port_t) n;
625 sin6->sin6_port = htons((in_port_t) n);
627 u->port_text.len = len;
628 u->port_text.data = port;
645 p = ngx_alloc(len, pool->log);
650 (void) ngx_cpystrn(p, host, len);
652 rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
657 u->err = "invalid IPv6 address";
661 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
665 u->family = AF_INET6;
672 u->port = u->default_port;
673 sin6->sin6_port = htons(u->default_port);
680 u->err = "the INET6 sockets are not supported on this platform";
689 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
697 struct sockaddr_in *sin;
699 host = ngx_alloc(u->host.len + 1, pool->log);
704 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
708 port = htons(u->port);
710 in_addr = inet_addr((char *) host);
712 if (in_addr == INADDR_NONE) {
713 h = gethostbyname((char *) host);
717 if (h == NULL || h->h_addr_list[0] == NULL) {
718 u->err = "host not found";
722 if (u->one_addr == 0) {
723 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
729 /* MP: ngx_shared_palloc() */
731 u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
732 if (u->addrs == NULL) {
738 for (i = 0; h->h_addr_list[i] != NULL; i++) {
740 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
745 sin->sin_family = AF_INET;
746 sin->sin_port = port;
747 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
749 u->addrs[i].sockaddr = (struct sockaddr *) sin;
750 u->addrs[i].socklen = sizeof(struct sockaddr_in);
752 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
754 p = ngx_pnalloc(pool, len);
759 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
761 u->addrs[i].name.len = len;
762 u->addrs[i].name.data = p;
769 /* MP: ngx_shared_palloc() */
771 u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
772 if (u->addrs == NULL) {
776 sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
783 sin->sin_family = AF_INET;
784 sin->sin_port = port;
785 sin->sin_addr.s_addr = in_addr;
787 u->addrs[0].sockaddr = (struct sockaddr *) sin;
788 u->addrs[0].socklen = sizeof(struct sockaddr_in);
790 p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
795 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
796 &u->host, ntohs(port)) - p;
797 u->addrs[0].name.data = p;