src/core/ngx_inet.c - nginx-1.7.10

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
  8. static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
  9. static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);


  10. in_addr_t
  11. ngx_inet_addr(u_char *text, size_t len)
  12. {
  13.     u_char      *p, c;
  14.     in_addr_t    addr;
  15.     ngx_uint_t   octet, n;

  16.     addr = 0;
  17.     octet = 0;
  18.     n = 0;

  19.     for (p = text; p < text + len; p++) {

  20.         c = *p;

  21.         if (c >= '0' && c <= '9') {
  22.             octet = octet * 10 + (c - '0');
  23.             continue;
  24.         }

  25.         if (c == '.' && octet < 256) {
  26.             addr = (addr << 8) + octet;
  27.             octet = 0;
  28.             n++;
  29.             continue;
  30.         }

  31.         return INADDR_NONE;
  32.     }

  33.     if (n == 3 && octet < 256) {
  34.         addr = (addr << 8) + octet;
  35.         return htonl(addr);
  36.     }

  37.     return INADDR_NONE;
  38. }


  39. #if (NGX_HAVE_INET6)

  40. ngx_int_t
  41. ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
  42. {
  43.     u_char      c, *zero, *digit, *s, *d;
  44.     size_t      len4;
  45.     ngx_uint_t  n, nibbles, word;

  46.     if (len == 0) {
  47.         return NGX_ERROR;
  48.     }

  49.     zero = NULL;
  50.     digit = NULL;
  51.     len4 = 0;
  52.     nibbles = 0;
  53.     word = 0;
  54.     n = 8;

  55.     if (p[0] == ':') {
  56.         p++;
  57.         len--;
  58.     }

  59.     for (/* void */; len; len--) {
  60.         c = *p++;

  61.         if (c == ':') {
  62.             if (nibbles) {
  63.                 digit = p;
  64.                 len4 = len;
  65.                 *addr++ = (u_char) (word >> 8);
  66.                 *addr++ = (u_char) (word & 0xff);

  67.                 if (--n) {
  68.                     nibbles = 0;
  69.                     word = 0;
  70.                     continue;
  71.                 }

  72.             } else {
  73.                 if (zero == NULL) {
  74.                     digit = p;
  75.                     len4 = len;
  76.                     zero = addr;
  77.                     continue;
  78.                 }
  79.             }

  80.             return NGX_ERROR;
  81.         }

  82.         if (c == '.' && nibbles) {
  83.             if (n < 2 || digit == NULL) {
  84.                 return NGX_ERROR;
  85.             }

  86.             word = ngx_inet_addr(digit, len4 - 1);
  87.             if (word == INADDR_NONE) {
  88.                 return NGX_ERROR;
  89.             }

  90.             word = ntohl(word);
  91.             *addr++ = (u_char) ((word >> 24) & 0xff);
  92.             *addr++ = (u_char) ((word >> 16) & 0xff);
  93.             n--;
  94.             break;
  95.         }

  96.         if (++nibbles > 4) {
  97.             return NGX_ERROR;
  98.         }

  99.         if (c >= '0' && c <= '9') {
  100.             word = word * 16 + (c - '0');
  101.             continue;
  102.         }

  103.         c |= 0x20;

  104.         if (c >= 'a' && c <= 'f') {
  105.             word = word * 16 + (c - 'a') + 10;
  106.             continue;
  107.         }

  108.         return NGX_ERROR;
  109.     }

  110.     if (nibbles == 0 && zero == NULL) {
  111.         return NGX_ERROR;
  112.     }

  113.     *addr++ = (u_char) (word >> 8);
  114.     *addr++ = (u_char) (word & 0xff);

  115.     if (--n) {
  116.         if (zero) {
  117.             n *= 2;
  118.             s = addr - 1;
  119.             d = s + n;
  120.             while (s >= zero) {
  121.                 *d-- = *s--;
  122.             }
  123.             ngx_memzero(zero, n);
  124.             return NGX_OK;
  125.         }

  126.     } else {
  127.         if (zero == NULL) {
  128.             return NGX_OK;
  129.         }
  130.     }

  131.     return NGX_ERROR;
  132. }

  133. #endif


  134. size_t
  135. ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len,
  136.     ngx_uint_t port)
  137. {
  138.     u_char               *p;
  139.     struct sockaddr_in   *sin;
  140. #if (NGX_HAVE_INET6)
  141.     size_t                n;
  142.     struct sockaddr_in6  *sin6;
  143. #endif
  144. #if (NGX_HAVE_UNIX_DOMAIN)
  145.     struct sockaddr_un   *saun;
  146. #endif

  147.     switch (sa->sa_family) {

  148.     case AF_INET:

  149.         sin = (struct sockaddr_in *) sa;
  150.         p = (u_char *) &sin->sin_addr;

  151.         if (port) {
  152.             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
  153.                              p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
  154.         } else {
  155.             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
  156.                              p[0], p[1], p[2], p[3]);
  157.         }

  158.         return (p - text);

  159. #if (NGX_HAVE_INET6)

  160.     case AF_INET6:

  161.         sin6 = (struct sockaddr_in6 *) sa;

  162.         n = 0;

  163.         if (port) {
  164.             text[n++] = '[';
  165.         }

  166.         n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);

  167.         if (port) {
  168.             n = ngx_sprintf(&text[1 + n], "]:%d",
  169.                             ntohs(sin6->sin6_port)) - text;
  170.         }

  171.         return n;
  172. #endif

  173. #if (NGX_HAVE_UNIX_DOMAIN)

  174.     case AF_UNIX:
  175.         saun = (struct sockaddr_un *) sa;

  176.         /* on Linux sockaddr might not include sun_path at all */

  177.         if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
  178.             p = ngx_snprintf(text, len, "unix:%Z");

  179.         } else {
  180.             p = ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path);
  181.         }

  182.         /* we do not include trailing zero in address length */

  183.         return (p - text - 1);

  184. #endif

  185.     default:
  186.         return 0;
  187.     }
  188. }


  189. size_t
  190. ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
  191. {
  192.     u_char  *p;

  193.     switch (family) {

  194.     case AF_INET:

  195.         p = addr;

  196.         return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
  197.                             p[0], p[1], p[2], p[3])
  198.                - text;

  199. #if (NGX_HAVE_INET6)

  200.     case AF_INET6:
  201.         return ngx_inet6_ntop(addr, text, len);

  202. #endif

  203.     default:
  204.         return 0;
  205.     }
  206. }


  207. #if (NGX_HAVE_INET6)

  208. size_t
  209. ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
  210. {
  211.     u_char      *dst;
  212.     size_t       max, n;
  213.     ngx_uint_t   i, zero, last;

  214.     if (len < NGX_INET6_ADDRSTRLEN) {
  215.         return 0;
  216.     }

  217.     zero = (ngx_uint_t) -1;
  218.     last = (ngx_uint_t) -1;
  219.     max = 1;
  220.     n = 0;

  221.     for (i = 0; i < 16; i += 2) {

  222.         if (p[i] || p[i + 1]) {

  223.             if (max < n) {
  224.                 zero = last;
  225.                 max = n;
  226.             }

  227.             n = 0;
  228.             continue;
  229.         }

  230.         if (n++ == 0) {
  231.             last = i;
  232.         }
  233.     }

  234.     if (max < n) {
  235.         zero = last;
  236.         max = n;
  237.     }

  238.     dst = text;
  239.     n = 16;

  240.     if (zero == 0) {

  241.         if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
  242.             || (max == 6)
  243.             || (max == 7 && p[14] != 0 && p[15] != 1))
  244.         {
  245.             n = 12;
  246.         }

  247.         *dst++ = ':';
  248.     }

  249.     for (i = 0; i < n; i += 2) {

  250.         if (i == zero) {
  251.             *dst++ = ':';
  252.             i += (max - 1) * 2;
  253.             continue;
  254.         }

  255.         dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);

  256.         if (i < 14) {
  257.             *dst++ = ':';
  258.         }
  259.     }

  260.     if (n == 12) {
  261.         dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
  262.     }

  263.     return dst - text;
  264. }

  265. #endif


  266. ngx_int_t
  267. ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
  268. {
  269.     u_char      *addr, *mask, *last;
  270.     size_t       len;
  271.     ngx_int_t    shift;
  272. #if (NGX_HAVE_INET6)
  273.     ngx_int_t    rc;
  274.     ngx_uint_t   s, i;
  275. #endif

  276.     addr = text->data;
  277.     last = addr + text->len;

  278.     mask = ngx_strlchr(addr, last, '/');
  279.     len = (mask ? mask : last) - addr;

  280.     cidr->u.in.addr = ngx_inet_addr(addr, len);

  281.     if (cidr->u.in.addr != INADDR_NONE) {
  282.         cidr->family = AF_INET;

  283.         if (mask == NULL) {
  284.             cidr->u.in.mask = 0xffffffff;
  285.             return NGX_OK;
  286.         }

  287. #if (NGX_HAVE_INET6)
  288.     } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
  289.         cidr->family = AF_INET6;

  290.         if (mask == NULL) {
  291.             ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
  292.             return NGX_OK;
  293.         }

  294. #endif
  295.     } else {
  296.         return NGX_ERROR;
  297.     }

  298.     mask++;

  299.     shift = ngx_atoi(mask, last - mask);
  300.     if (shift == NGX_ERROR) {
  301.         return NGX_ERROR;
  302.     }

  303.     switch (cidr->family) {

  304. #if (NGX_HAVE_INET6)
  305.     case AF_INET6:
  306.         if (shift > 128) {
  307.             return NGX_ERROR;
  308.         }

  309.         addr = cidr->u.in6.addr.s6_addr;
  310.         mask = cidr->u.in6.mask.s6_addr;
  311.         rc = NGX_OK;

  312.         for (i = 0; i < 16; i++) {

  313.             s = (shift > 8) ? 8 : shift;
  314.             shift -= s;

  315.             mask[i] = (u_char) (0xffu << (8 - s));

  316.             if (addr[i] != (addr[i] & mask[i])) {
  317.                 rc = NGX_DONE;
  318.                 addr[i] &= mask[i];
  319.             }
  320.         }

  321.         return rc;
  322. #endif

  323.     default: /* AF_INET */
  324.         if (shift > 32) {
  325.             return NGX_ERROR;
  326.         }

  327.         if (shift) {
  328.             cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));

  329.         } else {
  330.             /* x86 compilers use a shl instruction that shifts by modulo 32 */
  331.             cidr->u.in.mask = 0;
  332.         }

  333.         if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
  334.             return NGX_OK;
  335.         }

  336.         cidr->u.in.addr &= cidr->u.in.mask;

  337.         return NGX_DONE;
  338.     }
  339. }


  340. ngx_int_t
  341. ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
  342. {
  343.     in_addr_t             inaddr;
  344.     ngx_uint_t            family;
  345.     struct sockaddr_in   *sin;
  346. #if (NGX_HAVE_INET6)
  347.     struct in6_addr       inaddr6;
  348.     struct sockaddr_in6  *sin6;

  349.     /*
  350.      * prevent MSVC8 warning:
  351.      *    potentially uninitialized local variable 'inaddr6' used
  352.      */
  353.     ngx_memzero(&inaddr6, sizeof(struct in6_addr));
  354. #endif

  355.     inaddr = ngx_inet_addr(text, len);

  356.     if (inaddr != INADDR_NONE) {
  357.         family = AF_INET;
  358.         len = sizeof(struct sockaddr_in);

  359. #if (NGX_HAVE_INET6)
  360.     } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
  361.         family = AF_INET6;
  362.         len = sizeof(struct sockaddr_in6);

  363. #endif
  364.     } else {
  365.         return NGX_DECLINED;
  366.     }

  367.     addr->sockaddr = ngx_pcalloc(pool, len);
  368.     if (addr->sockaddr == NULL) {
  369.         return NGX_ERROR;
  370.     }

  371.     addr->sockaddr->sa_family = (u_char) family;
  372.     addr->socklen = len;

  373.     switch (family) {

  374. #if (NGX_HAVE_INET6)
  375.     case AF_INET6:
  376.         sin6 = (struct sockaddr_in6 *) addr->sockaddr;
  377.         ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
  378.         break;
  379. #endif

  380.     default: /* AF_INET */
  381.         sin = (struct sockaddr_in *) addr->sockaddr;
  382.         sin->sin_addr.s_addr = inaddr;
  383.         break;
  384.     }

  385.     return NGX_OK;
  386. }


  387. ngx_int_t
  388. ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
  389. {
  390.     u_char  *p;

  391.     p = u->url.data;

  392.     if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
  393.         return ngx_parse_unix_domain_url(pool, u);
  394.     }

  395.     if (p[0] == '[') {
  396.         return ngx_parse_inet6_url(pool, u);
  397.     }

  398.     return ngx_parse_inet_url(pool, u);
  399. }


  400. static ngx_int_t
  401. ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
  402. {
  403. #if (NGX_HAVE_UNIX_DOMAIN)
  404.     u_char              *path, *uri, *last;
  405.     size_t               len;
  406.     struct sockaddr_un  *saun;

  407.     len = u->url.len;
  408.     path = u->url.data;

  409.     path += 5;
  410.     len -= 5;

  411.     if (u->uri_part) {

  412.         last = path + len;
  413.         uri = ngx_strlchr(path, last, ':');

  414.         if (uri) {
  415.             len = uri - path;
  416.             uri++;
  417.             u->uri.len = last - uri;
  418.             u->uri.data = uri;
  419.         }
  420.     }

  421.     if (len == 0) {
  422.         u->err = "no path in the unix domain socket";
  423.         return NGX_ERROR;
  424.     }

  425.     u->host.len = len++;
  426.     u->host.data = path;

  427.     if (len > sizeof(saun->sun_path)) {
  428.         u->err = "too long path in the unix domain socket";
  429.         return NGX_ERROR;
  430.     }

  431.     u->socklen = sizeof(struct sockaddr_un);
  432.     saun = (struct sockaddr_un *) &u->sockaddr;
  433.     saun->sun_family = AF_UNIX;
  434.     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);

  435.     u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
  436.     if (u->addrs == NULL) {
  437.         return NGX_ERROR;
  438.     }

  439.     saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
  440.     if (saun == NULL) {
  441.         return NGX_ERROR;
  442.     }

  443.     u->family = AF_UNIX;
  444.     u->naddrs = 1;

  445.     saun->sun_family = AF_UNIX;
  446.     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);

  447.     u->addrs[0].sockaddr = (struct sockaddr *) saun;
  448.     u->addrs[0].socklen = sizeof(struct sockaddr_un);
  449.     u->addrs[0].name.len = len + 4;
  450.     u->addrs[0].name.data = u->url.data;

  451.     return NGX_OK;

  452. #else

  453.     u->err = "the unix domain sockets are not supported on this platform";

  454.     return NGX_ERROR;

  455. #endif
  456. }


  457. static ngx_int_t
  458. ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
  459. {
  460.     u_char               *p, *host, *port, *last, *uri, *args;
  461.     size_t                len;
  462.     ngx_int_t             n;
  463.     struct sockaddr_in   *sin;
  464. #if (NGX_HAVE_INET6)
  465.     struct sockaddr_in6  *sin6;
  466. #endif

  467.     u->socklen = sizeof(struct sockaddr_in);
  468.     sin = (struct sockaddr_in *) &u->sockaddr;
  469.     sin->sin_family = AF_INET;

  470.     u->family = AF_INET;

  471.     host = u->url.data;

  472.     last = host + u->url.len;

  473.     port = ngx_strlchr(host, last, ':');

  474.     uri = ngx_strlchr(host, last, '/');

  475.     args = ngx_strlchr(host, last, '?');

  476.     if (args) {
  477.         if (uri == NULL || args < uri) {
  478.             uri = args;
  479.         }
  480.     }

  481.     if (uri) {
  482.         if (u->listen || !u->uri_part) {
  483.             u->err = "invalid host";
  484.             return NGX_ERROR;
  485.         }

  486.         u->uri.len = last - uri;
  487.         u->uri.data = uri;

  488.         last = uri;

  489.         if (uri < port) {
  490.             port = NULL;
  491.         }
  492.     }

  493.     if (port) {
  494.         port++;

  495.         len = last - port;

  496.         n = ngx_atoi(port, len);

  497.         if (n < 1 || n > 65535) {
  498.             u->err = "invalid port";
  499.             return NGX_ERROR;
  500.         }

  501.         u->port = (in_port_t) n;
  502.         sin->sin_port = htons((in_port_t) n);

  503.         u->port_text.len = len;
  504.         u->port_text.data = port;

  505.         last = port - 1;

  506.     } else {
  507.         if (uri == NULL) {

  508.             if (u->listen) {

  509.                 /* test value as port only */

  510.                 n = ngx_atoi(host, last - host);

  511.                 if (n != NGX_ERROR) {

  512.                     if (n < 1 || n > 65535) {
  513.                         u->err = "invalid port";
  514.                         return NGX_ERROR;
  515.                     }

  516.                     u->port = (in_port_t) n;
  517.                     sin->sin_port = htons((in_port_t) n);

  518.                     u->port_text.len = last - host;
  519.                     u->port_text.data = host;

  520.                     u->wildcard = 1;

  521.                     return NGX_OK;
  522.                 }
  523.             }
  524.         }

  525.         u->no_port = 1;
  526.         u->port = u->default_port;
  527.         sin->sin_port = htons(u->default_port);
  528.     }

  529.     len = last - host;

  530.     if (len == 0) {
  531.         u->err = "no host";
  532.         return NGX_ERROR;
  533.     }

  534.     u->host.len = len;
  535.     u->host.data = host;

  536.     if (u->listen && len == 1 && *host == '*') {
  537.         sin->sin_addr.s_addr = INADDR_ANY;
  538.         u->wildcard = 1;
  539.         return NGX_OK;
  540.     }

  541.     sin->sin_addr.s_addr = ngx_inet_addr(host, len);

  542.     if (sin->sin_addr.s_addr != INADDR_NONE) {

  543.         if (sin->sin_addr.s_addr == INADDR_ANY) {
  544.             u->wildcard = 1;
  545.         }

  546.         u->naddrs = 1;

  547.         u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
  548.         if (u->addrs == NULL) {
  549.             return NGX_ERROR;
  550.         }

  551.         sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
  552.         if (sin == NULL) {
  553.             return NGX_ERROR;
  554.         }

  555.         ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in));

  556.         u->addrs[0].sockaddr = (struct sockaddr *) sin;
  557.         u->addrs[0].socklen = sizeof(struct sockaddr_in);

  558.         p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
  559.         if (p == NULL) {
  560.             return NGX_ERROR;
  561.         }

  562.         u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
  563.                                            &u->host, u->port) - p;
  564.         u->addrs[0].name.data = p;

  565.         return NGX_OK;
  566.     }

  567.     if (u->no_resolve) {
  568.         return NGX_OK;
  569.     }

  570.     if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
  571.         return NGX_ERROR;
  572.     }

  573.     u->family = u->addrs[0].sockaddr->sa_family;
  574.     u->socklen = u->addrs[0].socklen;
  575.     ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);

  576.     switch (u->family) {

  577. #if (NGX_HAVE_INET6)
  578.     case AF_INET6:
  579.         sin6 = (struct sockaddr_in6 *) &u->sockaddr;

  580.         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  581.             u->wildcard = 1;
  582.         }

  583.         break;
  584. #endif

  585.     default: /* AF_INET */
  586.         sin = (struct sockaddr_in *) &u->sockaddr;

  587.         if (sin->sin_addr.s_addr == INADDR_ANY) {
  588.             u->wildcard = 1;
  589.         }

  590.         break;
  591.     }

  592.     return NGX_OK;
  593. }


  594. static ngx_int_t
  595. ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
  596. {
  597. #if (NGX_HAVE_INET6)
  598.     u_char               *p, *host, *port, *last, *uri;
  599.     size_t                len;
  600.     ngx_int_t             n;
  601.     struct sockaddr_in6  *sin6;

  602.     u->socklen = sizeof(struct sockaddr_in6);
  603.     sin6 = (struct sockaddr_in6 *) &u->sockaddr;
  604.     sin6->sin6_family = AF_INET6;

  605.     host = u->url.data + 1;

  606.     last = u->url.data + u->url.len;

  607.     p = ngx_strlchr(host, last, ']');

  608.     if (p == NULL) {
  609.         u->err = "invalid host";
  610.         return NGX_ERROR;
  611.     }

  612.     if (last - p) {

  613.         port = p + 1;

  614.         uri = ngx_strlchr(port, last, '/');

  615.         if (uri) {
  616.             if (u->listen || !u->uri_part) {
  617.                 u->err = "invalid host";
  618.                 return NGX_ERROR;
  619.             }

  620.             u->uri.len = last - uri;
  621.             u->uri.data = uri;

  622.             last = uri;
  623.         }

  624.         if (*port == ':') {
  625.             port++;

  626.             len = last - port;

  627.             n = ngx_atoi(port, len);

  628.             if (n < 1 || n > 65535) {
  629.                 u->err = "invalid port";
  630.                 return NGX_ERROR;
  631.             }

  632.             u->port = (in_port_t) n;
  633.             sin6->sin6_port = htons((in_port_t) n);

  634.             u->port_text.len = len;
  635.             u->port_text.data = port;

  636.         } else {
  637.             u->no_port = 1;
  638.             u->port = u->default_port;
  639.             sin6->sin6_port = htons(u->default_port);
  640.         }
  641.     }

  642.     len = p - host;

  643.     if (len == 0) {
  644.         u->err = "no host";
  645.         return NGX_ERROR;
  646.     }

  647.     u->host.len = len + 2;
  648.     u->host.data = host - 1;

  649.     if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
  650.         u->err = "invalid IPv6 address";
  651.         return NGX_ERROR;
  652.     }

  653.     if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  654.         u->wildcard = 1;
  655.     }

  656.     u->family = AF_INET6;
  657.     u->naddrs = 1;

  658.     u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
  659.     if (u->addrs == NULL) {
  660.         return NGX_ERROR;
  661.     }

  662.     sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
  663.     if (sin6 == NULL) {
  664.         return NGX_ERROR;
  665.     }

  666.     ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6));

  667.     u->addrs[0].sockaddr = (struct sockaddr *) sin6;
  668.     u->addrs[0].socklen = sizeof(struct sockaddr_in6);

  669.     p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
  670.     if (p == NULL) {
  671.         return NGX_ERROR;
  672.     }

  673.     u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
  674.                                        &u->host, u->port) - p;
  675.     u->addrs[0].name.data = p;

  676.     return NGX_OK;

  677. #else

  678.     u->err = "the INET6 sockets are not supported on this platform";

  679.     return NGX_ERROR;

  680. #endif
  681. }


  682. #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)

  683. ngx_int_t
  684. ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
  685. {
  686.     u_char               *p, *host;
  687.     size_t                len;
  688.     in_port_t             port;
  689.     ngx_uint_t            i;
  690.     struct addrinfo       hints, *res, *rp;
  691.     struct sockaddr_in   *sin;
  692.     struct sockaddr_in6  *sin6;

  693.     port = htons(u->port);

  694.     host = ngx_alloc(u->host.len + 1, pool->log);
  695.     if (host == NULL) {
  696.         return NGX_ERROR;
  697.     }

  698.     (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);

  699.     ngx_memzero(&hints, sizeof(struct addrinfo));
  700.     hints.ai_family = AF_UNSPEC;
  701.     hints.ai_socktype = SOCK_STREAM;
  702. #ifdef AI_ADDRCONFIG
  703.     hints.ai_flags = AI_ADDRCONFIG;
  704. #endif

  705.     if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
  706.         u->err = "host not found";
  707.         ngx_free(host);
  708.         return NGX_ERROR;
  709.     }

  710.     ngx_free(host);

  711.     for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) {

  712.         switch (rp->ai_family) {

  713.         case AF_INET:
  714.         case AF_INET6:
  715.             break;

  716.         default:
  717.             continue;
  718.         }

  719.         i++;
  720.     }

  721.     if (i == 0) {
  722.         u->err = "host not found";
  723.         goto failed;
  724.     }

  725.     /* MP: ngx_shared_palloc() */

  726.     u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
  727.     if (u->addrs == NULL) {
  728.         goto failed;
  729.     }

  730.     u->naddrs = i;

  731.     i = 0;

  732.     /* AF_INET addresses first */

  733.     for (rp = res; rp != NULL; rp = rp->ai_next) {

  734.         if (rp->ai_family != AF_INET) {
  735.             continue;
  736.         }

  737.         sin = ngx_pcalloc(pool, rp->ai_addrlen);
  738.         if (sin == NULL) {
  739.             goto failed;
  740.         }

  741.         ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);

  742.         sin->sin_port = port;

  743.         u->addrs[i].sockaddr = (struct sockaddr *) sin;
  744.         u->addrs[i].socklen = rp->ai_addrlen;

  745.         len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;

  746.         p = ngx_pnalloc(pool, len);
  747.         if (p == NULL) {
  748.             goto failed;
  749.         }

  750.         len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1);

  751.         u->addrs[i].name.len = len;
  752.         u->addrs[i].name.data = p;

  753.         i++;
  754.     }

  755.     for (rp = res; rp != NULL; rp = rp->ai_next) {

  756.         if (rp->ai_family != AF_INET6) {
  757.             continue;
  758.         }

  759.         sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
  760.         if (sin6 == NULL) {
  761.             goto failed;
  762.         }

  763.         ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);

  764.         sin6->sin6_port = port;

  765.         u->addrs[i].sockaddr = (struct sockaddr *) sin6;
  766.         u->addrs[i].socklen = rp->ai_addrlen;

  767.         len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;

  768.         p = ngx_pnalloc(pool, len);
  769.         if (p == NULL) {
  770.             goto failed;
  771.         }

  772.         len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p,
  773.                             len, 1);

  774.         u->addrs[i].name.len = len;
  775.         u->addrs[i].name.data = p;

  776.         i++;
  777.     }

  778.     freeaddrinfo(res);
  779.     return NGX_OK;

  780. failed:

  781.     freeaddrinfo(res);
  782.     return NGX_ERROR;
  783. }

  784. #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */

  785. ngx_int_t
  786. ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
  787. {
  788.     u_char              *p, *host;
  789.     size_t               len;
  790.     in_port_t            port;
  791.     in_addr_t            in_addr;
  792.     ngx_uint_t           i;
  793.     struct hostent      *h;
  794.     struct sockaddr_in  *sin;

  795.     /* AF_INET only */

  796.     port = htons(u->port);

  797.     in_addr = ngx_inet_addr(u->host.data, u->host.len);

  798.     if (in_addr == INADDR_NONE) {
  799.         host = ngx_alloc(u->host.len + 1, pool->log);
  800.         if (host == NULL) {
  801.             return NGX_ERROR;
  802.         }

  803.         (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);

  804.         h = gethostbyname((char *) host);

  805.         ngx_free(host);

  806.         if (h == NULL || h->h_addr_list[0] == NULL) {
  807.             u->err = "host not found";
  808.             return NGX_ERROR;
  809.         }

  810.         for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }

  811.         /* MP: ngx_shared_palloc() */

  812.         u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
  813.         if (u->addrs == NULL) {
  814.             return NGX_ERROR;
  815.         }

  816.         u->naddrs = i;

  817.         for (i = 0; i < u->naddrs; i++) {

  818.             sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
  819.             if (sin == NULL) {
  820.                 return NGX_ERROR;
  821.             }

  822.             sin->sin_family = AF_INET;
  823.             sin->sin_port = port;
  824.             sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);

  825.             u->addrs[i].sockaddr = (struct sockaddr *) sin;
  826.             u->addrs[i].socklen = sizeof(struct sockaddr_in);

  827.             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;

  828.             p = ngx_pnalloc(pool, len);
  829.             if (p == NULL) {
  830.                 return NGX_ERROR;
  831.             }

  832.             len = ngx_sock_ntop((struct sockaddr *) sin,
  833.                                 sizeof(struct sockaddr_in), p, len, 1);

  834.             u->addrs[i].name.len = len;
  835.             u->addrs[i].name.data = p;
  836.         }

  837.     } else {

  838.         /* MP: ngx_shared_palloc() */

  839.         u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
  840.         if (u->addrs == NULL) {
  841.             return NGX_ERROR;
  842.         }

  843.         sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
  844.         if (sin == NULL) {
  845.             return NGX_ERROR;
  846.         }

  847.         u->naddrs = 1;

  848.         sin->sin_family = AF_INET;
  849.         sin->sin_port = port;
  850.         sin->sin_addr.s_addr = in_addr;

  851.         u->addrs[0].sockaddr = (struct sockaddr *) sin;
  852.         u->addrs[0].socklen = sizeof(struct sockaddr_in);

  853.         p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
  854.         if (p == NULL) {
  855.             return NGX_ERROR;
  856.         }

  857.         u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
  858.                                            &u->host, ntohs(port)) - p;
  859.         u->addrs[0].name.data = p;
  860.     }

  861.     return NGX_OK;
  862. }

  863. #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */


  864. ngx_int_t
  865. ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
  866.     struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
  867. {
  868.     struct sockaddr_in   *sin1, *sin2;
  869. #if (NGX_HAVE_INET6)
  870.     struct sockaddr_in6  *sin61, *sin62;
  871. #endif
  872. #if (NGX_HAVE_UNIX_DOMAIN)
  873.     struct sockaddr_un   *saun1, *saun2;
  874. #endif

  875.     if (sa1->sa_family != sa2->sa_family) {
  876.         return NGX_DECLINED;
  877.     }

  878.     switch (sa1->sa_family) {

  879. #if (NGX_HAVE_INET6)
  880.     case AF_INET6:

  881.         sin61 = (struct sockaddr_in6 *) sa1;
  882.         sin62 = (struct sockaddr_in6 *) sa2;

  883.         if (cmp_port && sin61->sin6_port != sin62->sin6_port) {
  884.             return NGX_DECLINED;
  885.         }

  886.         if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
  887.             return NGX_DECLINED;
  888.         }

  889.         break;
  890. #endif

  891. #if (NGX_HAVE_UNIX_DOMAIN)
  892.     case AF_UNIX:

  893.        /* TODO length */

  894.        saun1 = (struct sockaddr_un *) sa1;
  895.        saun2 = (struct sockaddr_un *) sa2;

  896.        if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
  897.                       sizeof(saun1->sun_path))
  898.            != 0)
  899.        {
  900.            return NGX_DECLINED;
  901.        }

  902.        break;
  903. #endif

  904.     default: /* AF_INET */

  905.         sin1 = (struct sockaddr_in *) sa1;
  906.         sin2 = (struct sockaddr_in *) sa2;

  907.         if (cmp_port && sin1->sin_port != sin2->sin_port) {
  908.             return NGX_DECLINED;
  909.         }

  910.         if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
  911.             return NGX_DECLINED;
  912.         }

  913.         break;
  914.     }

  915.     return NGX_OK;
  916. }