src/core/ngx_inet.c - nginx source code

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. static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u,
  11.     struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total);


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

  18.     addr = 0;
  19.     octet = 0;
  20.     n = 0;

  21.     for (p = text; p < text + len; p++) {
  22.         c = *p;

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

  25.             if (octet > 255) {
  26.                 return INADDR_NONE;
  27.             }

  28.             continue;
  29.         }

  30.         if (c == '.') {
  31.             addr = (addr << 8) + octet;
  32.             octet = 0;
  33.             n++;
  34.             continue;
  35.         }

  36.         return INADDR_NONE;
  37.     }

  38.     if (n == 3) {
  39.         addr = (addr << 8) + octet;
  40.         return htonl(addr);
  41.     }

  42.     return INADDR_NONE;
  43. }


  44. #if (NGX_HAVE_INET6)

  45. ngx_int_t
  46. ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
  47. {
  48.     u_char      c, *zero, *digit, *s, *d;
  49.     size_t      len4;
  50.     ngx_uint_t  n, nibbles, word;

  51.     if (len == 0) {
  52.         return NGX_ERROR;
  53.     }

  54.     zero = NULL;
  55.     digit = NULL;
  56.     len4 = 0;
  57.     nibbles = 0;
  58.     word = 0;
  59.     n = 8;

  60.     if (p[0] == ':') {
  61.         p++;
  62.         len--;
  63.     }

  64.     for (/* void */; len; len--) {
  65.         c = *p++;

  66.         if (c == ':') {
  67.             if (nibbles) {
  68.                 digit = p;
  69.                 len4 = len;
  70.                 *addr++ = (u_char) (word >> 8);
  71.                 *addr++ = (u_char) (word & 0xff);

  72.                 if (--n) {
  73.                     nibbles = 0;
  74.                     word = 0;
  75.                     continue;
  76.                 }

  77.             } else {
  78.                 if (zero == NULL) {
  79.                     digit = p;
  80.                     len4 = len;
  81.                     zero = addr;
  82.                     continue;
  83.                 }
  84.             }

  85.             return NGX_ERROR;
  86.         }

  87.         if (c == '.' && nibbles) {
  88.             if (n < 2 || digit == NULL) {
  89.                 return NGX_ERROR;
  90.             }

  91.             word = ngx_inet_addr(digit, len4 - 1);
  92.             if (word == INADDR_NONE) {
  93.                 return NGX_ERROR;
  94.             }

  95.             word = ntohl(word);
  96.             *addr++ = (u_char) ((word >> 24) & 0xff);
  97.             *addr++ = (u_char) ((word >> 16) & 0xff);
  98.             n--;
  99.             break;
  100.         }

  101.         if (++nibbles > 4) {
  102.             return NGX_ERROR;
  103.         }

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

  108.         c |= 0x20;

  109.         if (c >= 'a' && c <= 'f') {
  110.             word = word * 16 + (c - 'a') + 10;
  111.             continue;
  112.         }

  113.         return NGX_ERROR;
  114.     }

  115.     if (nibbles == 0 && zero == NULL) {
  116.         return NGX_ERROR;
  117.     }

  118.     *addr++ = (u_char) (word >> 8);
  119.     *addr++ = (u_char) (word & 0xff);

  120.     if (--n) {
  121.         if (zero) {
  122.             n *= 2;
  123.             s = addr - 1;
  124.             d = s + n;
  125.             while (s >= zero) {
  126.                 *d-- = *s--;
  127.             }
  128.             ngx_memzero(zero, n);
  129.             return NGX_OK;
  130.         }

  131.     } else {
  132.         if (zero == NULL) {
  133.             return NGX_OK;
  134.         }
  135.     }

  136.     return NGX_ERROR;
  137. }

  138. #endif


  139. size_t
  140. ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len,
  141.     ngx_uint_t port)
  142. {
  143.     u_char               *p;
  144. #if (NGX_HAVE_INET6 || NGX_HAVE_UNIX_DOMAIN)
  145.     size_t                n;
  146. #endif
  147.     struct sockaddr_in   *sin;
  148. #if (NGX_HAVE_INET6)
  149.     struct sockaddr_in6  *sin6;
  150. #endif
  151. #if (NGX_HAVE_UNIX_DOMAIN)
  152.     struct sockaddr_un   *saun;
  153. #endif

  154.     switch (sa->sa_family) {

  155.     case AF_INET:

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

  158.         if (port) {
  159.             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
  160.                              p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
  161.         } else {
  162.             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
  163.                              p[0], p[1], p[2], p[3]);
  164.         }

  165.         return (p - text);

  166. #if (NGX_HAVE_INET6)

  167.     case AF_INET6:

  168.         sin6 = (struct sockaddr_in6 *) sa;

  169.         n = 0;

  170.         if (port) {
  171.             text[n++] = '[';
  172.         }

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

  174.         if (port) {
  175.             n = ngx_sprintf(&text[1 + n], "]:%d",
  176.                             ntohs(sin6->sin6_port)) - text;
  177.         }

  178.         return n;
  179. #endif

  180. #if (NGX_HAVE_UNIX_DOMAIN)

  181.     case AF_UNIX:
  182.         saun = (struct sockaddr_un *) sa;

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

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

  186.         } else {
  187.             n = ngx_strnlen((u_char *) saun->sun_path,
  188.                             socklen - offsetof(struct sockaddr_un, sun_path));
  189.             p = ngx_snprintf(text, len, "unix:%*s%Z", n, saun->sun_path);
  190.         }

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

  192.         return (p - text - 1);

  193. #endif

  194.     default:
  195.         return 0;
  196.     }
  197. }


  198. size_t
  199. ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
  200. {
  201.     u_char  *p;

  202.     switch (family) {

  203.     case AF_INET:

  204.         p = addr;

  205.         return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
  206.                             p[0], p[1], p[2], p[3])
  207.                - text;

  208. #if (NGX_HAVE_INET6)

  209.     case AF_INET6:
  210.         return ngx_inet6_ntop(addr, text, len);

  211. #endif

  212.     default:
  213.         return 0;
  214.     }
  215. }


  216. #if (NGX_HAVE_INET6)

  217. size_t
  218. ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
  219. {
  220.     u_char      *dst;
  221.     size_t       max, n;
  222.     ngx_uint_t   i, zero, last;

  223.     if (len < NGX_INET6_ADDRSTRLEN) {
  224.         return 0;
  225.     }

  226.     zero = (ngx_uint_t) -1;
  227.     last = (ngx_uint_t) -1;
  228.     max = 1;
  229.     n = 0;

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

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

  232.             if (max < n) {
  233.                 zero = last;
  234.                 max = n;
  235.             }

  236.             n = 0;
  237.             continue;
  238.         }

  239.         if (n++ == 0) {
  240.             last = i;
  241.         }
  242.     }

  243.     if (max < n) {
  244.         zero = last;
  245.         max = n;
  246.     }

  247.     dst = text;
  248.     n = 16;

  249.     if (zero == 0) {

  250.         if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
  251.             || (max == 6)
  252.             || (max == 7 && p[14] != 0 && p[15] != 1))
  253.         {
  254.             n = 12;
  255.         }

  256.         *dst++ = ':';
  257.     }

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

  259.         if (i == zero) {
  260.             *dst++ = ':';
  261.             i += (max - 1) * 2;
  262.             continue;
  263.         }

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

  265.         if (i < 14) {
  266.             *dst++ = ':';
  267.         }
  268.     }

  269.     if (n == 12) {
  270.         dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
  271.     }

  272.     return dst - text;
  273. }

  274. #endif


  275. ngx_int_t
  276. ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
  277. {
  278.     u_char      *addr, *mask, *last;
  279.     size_t       len;
  280.     ngx_int_t    shift;
  281. #if (NGX_HAVE_INET6)
  282.     ngx_int_t    rc;
  283.     ngx_uint_t   s, i;
  284. #endif

  285.     addr = text->data;
  286.     last = addr + text->len;

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

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

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

  292.         if (mask == NULL) {
  293.             cidr->u.in.mask = 0xffffffff;
  294.             return NGX_OK;
  295.         }

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

  299.         if (mask == NULL) {
  300.             ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
  301.             return NGX_OK;
  302.         }

  303. #endif
  304.     } else {
  305.         return NGX_ERROR;
  306.     }

  307.     mask++;

  308.     shift = ngx_atoi(mask, last - mask);
  309.     if (shift == NGX_ERROR) {
  310.         return NGX_ERROR;
  311.     }

  312.     switch (cidr->family) {

  313. #if (NGX_HAVE_INET6)
  314.     case AF_INET6:
  315.         if (shift > 128) {
  316.             return NGX_ERROR;
  317.         }

  318.         addr = cidr->u.in6.addr.s6_addr;
  319.         mask = cidr->u.in6.mask.s6_addr;
  320.         rc = NGX_OK;

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

  322.             s = (shift > 8) ? 8 : shift;
  323.             shift -= s;

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

  325.             if (addr[i] != (addr[i] & mask[i])) {
  326.                 rc = NGX_DONE;
  327.                 addr[i] &= mask[i];
  328.             }
  329.         }

  330.         return rc;
  331. #endif

  332.     default: /* AF_INET */
  333.         if (shift > 32) {
  334.             return NGX_ERROR;
  335.         }

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

  338.         } else {
  339.             /* x86 compilers use a shl instruction that shifts by modulo 32 */
  340.             cidr->u.in.mask = 0;
  341.         }

  342.         if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
  343.             return NGX_OK;
  344.         }

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

  346.         return NGX_DONE;
  347.     }
  348. }


  349. ngx_int_t
  350. ngx_cidr_match(struct sockaddr *sa, ngx_array_t *cidrs)
  351. {
  352. #if (NGX_HAVE_INET6)
  353.     u_char           *p;
  354. #endif
  355.     in_addr_t         inaddr;
  356.     ngx_cidr_t       *cidr;
  357.     ngx_uint_t        family, i;
  358. #if (NGX_HAVE_INET6)
  359.     ngx_uint_t        n;
  360.     struct in6_addr  *inaddr6;
  361. #endif

  362. #if (NGX_SUPPRESS_WARN)
  363.     inaddr = 0;
  364. #if (NGX_HAVE_INET6)
  365.     inaddr6 = NULL;
  366. #endif
  367. #endif

  368.     family = sa->sa_family;

  369.     if (family == AF_INET) {
  370.         inaddr = ((struct sockaddr_in *) sa)->sin_addr.s_addr;
  371.     }

  372. #if (NGX_HAVE_INET6)
  373.     else if (family == AF_INET6) {
  374.         inaddr6 = &((struct sockaddr_in6 *) sa)->sin6_addr;

  375.         if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
  376.             family = AF_INET;

  377.             p = inaddr6->s6_addr;

  378.             inaddr = (in_addr_t) p[12] << 24;
  379.             inaddr += p[13] << 16;
  380.             inaddr += p[14] << 8;
  381.             inaddr += p[15];

  382.             inaddr = htonl(inaddr);
  383.         }
  384.     }
  385. #endif

  386.     for (cidr = cidrs->elts, i = 0; i < cidrs->nelts; i++) {
  387.         if (cidr[i].family != family) {
  388.             goto next;
  389.         }

  390.         switch (family) {

  391. #if (NGX_HAVE_INET6)
  392.         case AF_INET6:
  393.             for (n = 0; n < 16; n++) {
  394.                 if ((inaddr6->s6_addr[n] & cidr[i].u.in6.mask.s6_addr[n])
  395.                     != cidr[i].u.in6.addr.s6_addr[n])
  396.                 {
  397.                     goto next;
  398.                 }
  399.             }
  400.             break;
  401. #endif

  402. #if (NGX_HAVE_UNIX_DOMAIN)
  403.         case AF_UNIX:
  404.             break;
  405. #endif

  406.         default: /* AF_INET */
  407.             if ((inaddr & cidr[i].u.in.mask) != cidr[i].u.in.addr) {
  408.                 goto next;
  409.             }
  410.             break;
  411.         }

  412.         return NGX_OK;

  413.     next:
  414.         continue;
  415.     }

  416.     return NGX_DECLINED;
  417. }


  418. ngx_int_t
  419. ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
  420. {
  421.     in_addr_t             inaddr;
  422.     ngx_uint_t            family;
  423.     struct sockaddr_in   *sin;
  424. #if (NGX_HAVE_INET6)
  425.     struct in6_addr       inaddr6;
  426.     struct sockaddr_in6  *sin6;

  427.     /*
  428.      * prevent MSVC8 warning:
  429.      *    potentially uninitialized local variable 'inaddr6' used
  430.      */
  431.     ngx_memzero(&inaddr6, sizeof(struct in6_addr));
  432. #endif

  433.     inaddr = ngx_inet_addr(text, len);

  434.     if (inaddr != INADDR_NONE) {
  435.         family = AF_INET;
  436.         len = sizeof(struct sockaddr_in);

  437. #if (NGX_HAVE_INET6)
  438.     } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
  439.         family = AF_INET6;
  440.         len = sizeof(struct sockaddr_in6);

  441. #endif
  442.     } else {
  443.         return NGX_DECLINED;
  444.     }

  445.     addr->sockaddr = ngx_pcalloc(pool, len);
  446.     if (addr->sockaddr == NULL) {
  447.         return NGX_ERROR;
  448.     }

  449.     addr->sockaddr->sa_family = (u_char) family;
  450.     addr->socklen = len;

  451.     switch (family) {

  452. #if (NGX_HAVE_INET6)
  453.     case AF_INET6:
  454.         sin6 = (struct sockaddr_in6 *) addr->sockaddr;
  455.         ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
  456.         break;
  457. #endif

  458.     default: /* AF_INET */
  459.         sin = (struct sockaddr_in *) addr->sockaddr;
  460.         sin->sin_addr.s_addr = inaddr;
  461.         break;
  462.     }

  463.     return NGX_OK;
  464. }


  465. ngx_int_t
  466. ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
  467.     size_t len)
  468. {
  469.     u_char     *p, *last;
  470.     size_t      plen;
  471.     ngx_int_t   rc, port;

  472.     rc = ngx_parse_addr(pool, addr, text, len);

  473.     if (rc != NGX_DECLINED) {
  474.         return rc;
  475.     }

  476.     last = text + len;

  477. #if (NGX_HAVE_INET6)
  478.     if (len && text[0] == '[') {

  479.         p = ngx_strlchr(text, last, ']');

  480.         if (p == last - 1) {
  481.             return ngx_parse_addr(pool, addr, text + 1, len - 2);
  482.         }

  483.         if (p == NULL || *++p != ':') {
  484.             return NGX_DECLINED;
  485.         }

  486.         text++;
  487.         len -= 2;

  488.     } else
  489. #endif

  490.     {
  491.         p = ngx_strlchr(text, last, ':');

  492.         if (p == NULL) {
  493.             return NGX_DECLINED;
  494.         }
  495.     }

  496.     p++;
  497.     plen = last - p;

  498.     port = ngx_atoi(p, plen);

  499.     if (port < 1 || port > 65535) {
  500.         return NGX_DECLINED;
  501.     }

  502.     len -= plen + 1;

  503.     rc = ngx_parse_addr(pool, addr, text, len);

  504.     if (rc != NGX_OK) {
  505.         return rc;
  506.     }

  507.     ngx_inet_set_port(addr->sockaddr, (in_port_t) port);

  508.     return NGX_OK;
  509. }


  510. ngx_int_t
  511. ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
  512. {
  513.     u_char  *p;
  514.     size_t   len;

  515.     p = u->url.data;
  516.     len = u->url.len;

  517.     if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
  518.         return ngx_parse_unix_domain_url(pool, u);
  519.     }

  520.     if (len && p[0] == '[') {
  521.         return ngx_parse_inet6_url(pool, u);
  522.     }

  523.     return ngx_parse_inet_url(pool, u);
  524. }


  525. static ngx_int_t
  526. ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
  527. {
  528. #if (NGX_HAVE_UNIX_DOMAIN)
  529.     u_char              *path, *uri, *last;
  530.     size_t               len;
  531.     struct sockaddr_un  *saun;

  532.     len = u->url.len;
  533.     path = u->url.data;

  534.     path += 5;
  535.     len -= 5;

  536.     if (u->uri_part) {

  537.         last = path + len;
  538.         uri = ngx_strlchr(path, last, ':');

  539.         if (uri) {
  540.             len = uri - path;
  541.             uri++;
  542.             u->uri.len = last - uri;
  543.             u->uri.data = uri;
  544.         }
  545.     }

  546.     if (len == 0) {
  547.         u->err = "no path in the unix domain socket";
  548.         return NGX_ERROR;
  549.     }

  550.     u->host.len = len++;
  551.     u->host.data = path;

  552.     if (len > sizeof(saun->sun_path)) {
  553.         u->err = "too long path in the unix domain socket";
  554.         return NGX_ERROR;
  555.     }

  556.     u->socklen = sizeof(struct sockaddr_un);
  557.     saun = (struct sockaddr_un *) &u->sockaddr;
  558.     saun->sun_family = AF_UNIX;
  559.     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);

  560.     u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
  561.     if (u->addrs == NULL) {
  562.         return NGX_ERROR;
  563.     }

  564.     saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
  565.     if (saun == NULL) {
  566.         return NGX_ERROR;
  567.     }

  568.     u->family = AF_UNIX;
  569.     u->naddrs = 1;

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

  572.     u->addrs[0].sockaddr = (struct sockaddr *) saun;
  573.     u->addrs[0].socklen = sizeof(struct sockaddr_un);
  574.     u->addrs[0].name.len = len + 4;
  575.     u->addrs[0].name.data = u->url.data;

  576.     return NGX_OK;

  577. #else

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

  579.     return NGX_ERROR;

  580. #endif
  581. }


  582. static ngx_int_t
  583. ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
  584. {
  585.     u_char              *host, *port, *last, *uri, *args, *dash;
  586.     size_t               len;
  587.     ngx_int_t            n;
  588.     struct sockaddr_in  *sin;

  589.     u->socklen = sizeof(struct sockaddr_in);
  590.     sin = (struct sockaddr_in *) &u->sockaddr;
  591.     sin->sin_family = AF_INET;

  592.     u->family = AF_INET;

  593.     host = u->url.data;

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

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

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

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

  598.     if (args) {
  599.         if (uri == NULL || args < uri) {
  600.             uri = args;
  601.         }
  602.     }

  603.     if (uri) {
  604.         if (u->listen || !u->uri_part) {
  605.             u->err = "invalid host";
  606.             return NGX_ERROR;
  607.         }

  608.         u->uri.len = last - uri;
  609.         u->uri.data = uri;

  610.         last = uri;

  611.         if (uri < port) {
  612.             port = NULL;
  613.         }
  614.     }

  615.     if (port) {
  616.         port++;

  617.         len = last - port;

  618.         if (u->listen) {
  619.             dash = ngx_strlchr(port, last, '-');

  620.             if (dash) {
  621.                 dash++;

  622.                 n = ngx_atoi(dash, last - dash);

  623.                 if (n < 1 || n > 65535) {
  624.                     u->err = "invalid port";
  625.                     return NGX_ERROR;
  626.                 }

  627.                 u->last_port = (in_port_t) n;

  628.                 len = dash - port - 1;
  629.             }
  630.         }

  631.         n = ngx_atoi(port, len);

  632.         if (n < 1 || n > 65535) {
  633.             u->err = "invalid port";
  634.             return NGX_ERROR;
  635.         }

  636.         if (u->last_port && n > u->last_port) {
  637.             u->err = "invalid port range";
  638.             return NGX_ERROR;
  639.         }

  640.         u->port = (in_port_t) n;
  641.         sin->sin_port = htons((in_port_t) n);

  642.         u->port_text.len = last - port;
  643.         u->port_text.data = port;

  644.         last = port - 1;

  645.     } else {
  646.         if (uri == NULL) {

  647.             if (u->listen) {

  648.                 /* test value as port only */

  649.                 len = last - host;

  650.                 dash = ngx_strlchr(host, last, '-');

  651.                 if (dash) {
  652.                     dash++;

  653.                     n = ngx_atoi(dash, last - dash);

  654.                     if (n == NGX_ERROR) {
  655.                         goto no_port;
  656.                     }

  657.                     if (n < 1 || n > 65535) {
  658.                         u->err = "invalid port";

  659.                     } else {
  660.                         u->last_port = (in_port_t) n;
  661.                     }

  662.                     len = dash - host - 1;
  663.                 }

  664.                 n = ngx_atoi(host, len);

  665.                 if (n != NGX_ERROR) {

  666.                     if (u->err) {
  667.                         return NGX_ERROR;
  668.                     }

  669.                     if (n < 1 || n > 65535) {
  670.                         u->err = "invalid port";
  671.                         return NGX_ERROR;
  672.                     }

  673.                     if (u->last_port && n > u->last_port) {
  674.                         u->err = "invalid port range";
  675.                         return NGX_ERROR;
  676.                     }

  677.                     u->port = (in_port_t) n;
  678.                     sin->sin_port = htons((in_port_t) n);
  679.                     sin->sin_addr.s_addr = INADDR_ANY;

  680.                     u->port_text.len = last - host;
  681.                     u->port_text.data = host;

  682.                     u->wildcard = 1;

  683.                     return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr,
  684.                                              u->socklen, 1);
  685.                 }
  686.             }
  687.         }

  688. no_port:

  689.         u->err = NULL;
  690.         u->no_port = 1;
  691.         u->port = u->default_port;
  692.         sin->sin_port = htons(u->default_port);
  693.         u->last_port = 0;
  694.     }

  695.     len = last - host;

  696.     if (len == 0) {
  697.         u->err = "no host";
  698.         return NGX_ERROR;
  699.     }

  700.     u->host.len = len;
  701.     u->host.data = host;

  702.     if (u->listen && len == 1 && *host == '*') {
  703.         sin->sin_addr.s_addr = INADDR_ANY;
  704.         u->wildcard = 1;
  705.         return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
  706.     }

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

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

  709.         if (sin->sin_addr.s_addr == INADDR_ANY) {
  710.             u->wildcard = 1;
  711.         }

  712.         return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
  713.     }

  714.     if (u->no_resolve) {
  715.         return NGX_OK;
  716.     }

  717.     if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
  718.         return NGX_ERROR;
  719.     }

  720.     u->family = u->addrs[0].sockaddr->sa_family;
  721.     u->socklen = u->addrs[0].socklen;
  722.     ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
  723.     u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr);

  724.     return NGX_OK;
  725. }


  726. static ngx_int_t
  727. ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
  728. {
  729. #if (NGX_HAVE_INET6)
  730.     u_char               *p, *host, *port, *last, *uri, *dash;
  731.     size_t                len;
  732.     ngx_int_t             n;
  733.     struct sockaddr_in6  *sin6;

  734.     u->socklen = sizeof(struct sockaddr_in6);
  735.     sin6 = (struct sockaddr_in6 *) &u->sockaddr;
  736.     sin6->sin6_family = AF_INET6;

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

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

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

  740.     if (p == NULL) {
  741.         u->err = "invalid host";
  742.         return NGX_ERROR;
  743.     }

  744.     port = p + 1;

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

  746.     if (uri) {
  747.         if (u->listen || !u->uri_part) {
  748.             u->err = "invalid host";
  749.             return NGX_ERROR;
  750.         }

  751.         u->uri.len = last - uri;
  752.         u->uri.data = uri;

  753.         last = uri;
  754.     }

  755.     if (port < last) {
  756.         if (*port != ':') {
  757.             u->err = "invalid host";
  758.             return NGX_ERROR;
  759.         }

  760.         port++;

  761.         len = last - port;

  762.         if (u->listen) {
  763.             dash = ngx_strlchr(port, last, '-');

  764.             if (dash) {
  765.                 dash++;

  766.                 n = ngx_atoi(dash, last - dash);

  767.                 if (n < 1 || n > 65535) {
  768.                     u->err = "invalid port";
  769.                     return NGX_ERROR;
  770.                 }

  771.                 u->last_port = (in_port_t) n;

  772.                 len = dash - port - 1;
  773.             }
  774.         }

  775.         n = ngx_atoi(port, len);

  776.         if (n < 1 || n > 65535) {
  777.             u->err = "invalid port";
  778.             return NGX_ERROR;
  779.         }

  780.         if (u->last_port && n > u->last_port) {
  781.             u->err = "invalid port range";
  782.             return NGX_ERROR;
  783.         }

  784.         u->port = (in_port_t) n;
  785.         sin6->sin6_port = htons((in_port_t) n);

  786.         u->port_text.len = last - port;
  787.         u->port_text.data = port;

  788.     } else {
  789.         u->no_port = 1;
  790.         u->port = u->default_port;
  791.         sin6->sin6_port = htons(u->default_port);
  792.     }

  793.     len = p - host;

  794.     if (len == 0) {
  795.         u->err = "no host";
  796.         return NGX_ERROR;
  797.     }

  798.     u->host.len = len + 2;
  799.     u->host.data = host - 1;

  800.     if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
  801.         u->err = "invalid IPv6 address";
  802.         return NGX_ERROR;
  803.     }

  804.     if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  805.         u->wildcard = 1;
  806.     }

  807.     u->family = AF_INET6;

  808.     return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);

  809. #else

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

  811.     return NGX_ERROR;

  812. #endif
  813. }


  814. #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)

  815. ngx_int_t
  816. ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
  817. {
  818.     u_char           *host;
  819.     ngx_uint_t        n;
  820.     struct addrinfo   hints, *res, *rp;

  821.     host = ngx_alloc(u->host.len + 1, pool->log);
  822.     if (host == NULL) {
  823.         return NGX_ERROR;
  824.     }

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

  826.     ngx_memzero(&hints, sizeof(struct addrinfo));
  827.     hints.ai_family = AF_UNSPEC;
  828.     hints.ai_socktype = SOCK_STREAM;
  829. #ifdef AI_ADDRCONFIG
  830.     hints.ai_flags = AI_ADDRCONFIG;
  831. #endif

  832.     if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
  833.         u->err = "host not found";
  834.         ngx_free(host);
  835.         return NGX_ERROR;
  836.     }

  837.     ngx_free(host);

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

  839.         switch (rp->ai_family) {

  840.         case AF_INET:
  841.         case AF_INET6:
  842.             break;

  843.         default:
  844.             continue;
  845.         }

  846.         n++;
  847.     }

  848.     if (n == 0) {
  849.         u->err = "host not found";
  850.         goto failed;
  851.     }

  852.     /* MP: ngx_shared_palloc() */

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

  854.         switch (rp->ai_family) {

  855.         case AF_INET:
  856.         case AF_INET6:
  857.             break;

  858.         default:
  859.             continue;
  860.         }

  861.         if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n)
  862.             != NGX_OK)
  863.         {
  864.             goto failed;
  865.         }
  866.     }

  867.     freeaddrinfo(res);
  868.     return NGX_OK;

  869. failed:

  870.     freeaddrinfo(res);
  871.     return NGX_ERROR;
  872. }

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

  874. ngx_int_t
  875. ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
  876. {
  877.     u_char              *host;
  878.     ngx_uint_t           i, n;
  879.     struct hostent      *h;
  880.     struct sockaddr_in   sin;

  881.     /* AF_INET only */

  882.     ngx_memzero(&sin, sizeof(struct sockaddr_in));

  883.     sin.sin_family = AF_INET;
  884.     sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len);

  885.     if (sin.sin_addr.s_addr == INADDR_NONE) {
  886.         host = ngx_alloc(u->host.len + 1, pool->log);
  887.         if (host == NULL) {
  888.             return NGX_ERROR;
  889.         }

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

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

  892.         ngx_free(host);

  893.         if (h == NULL || h->h_addr_list[0] == NULL) {
  894.             u->err = "host not found";
  895.             return NGX_ERROR;
  896.         }

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

  898.         /* MP: ngx_shared_palloc() */

  899.         for (i = 0; i < n; i++) {
  900.             sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);

  901.             if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
  902.                                   sizeof(struct sockaddr_in), n)
  903.                 != NGX_OK)
  904.             {
  905.                 return NGX_ERROR;
  906.             }
  907.         }

  908.     } else {

  909.         /* MP: ngx_shared_palloc() */

  910.         if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
  911.                               sizeof(struct sockaddr_in), 1)
  912.             != NGX_OK)
  913.         {
  914.             return NGX_ERROR;
  915.         }
  916.     }

  917.     return NGX_OK;
  918. }

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


  920. static ngx_int_t
  921. ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr,
  922.     socklen_t socklen, ngx_uint_t total)
  923. {
  924.     u_char           *p;
  925.     size_t            len;
  926.     ngx_uint_t        i, nports;
  927.     ngx_addr_t       *addr;
  928.     struct sockaddr  *sa;

  929.     nports = u->last_port ? u->last_port - u->port + 1 : 1;

  930.     if (u->addrs == NULL) {
  931.         u->addrs = ngx_palloc(pool, total * nports * sizeof(ngx_addr_t));
  932.         if (u->addrs == NULL) {
  933.             return NGX_ERROR;
  934.         }
  935.     }

  936.     for (i = 0; i < nports; i++) {
  937.         sa = ngx_pcalloc(pool, socklen);
  938.         if (sa == NULL) {
  939.             return NGX_ERROR;
  940.         }

  941.         ngx_memcpy(sa, sockaddr, socklen);

  942.         ngx_inet_set_port(sa, u->port + i);

  943.         switch (sa->sa_family) {

  944. #if (NGX_HAVE_INET6)
  945.         case AF_INET6:
  946.             len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1;
  947.             break;
  948. #endif

  949.         default: /* AF_INET */
  950.             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
  951.         }

  952.         p = ngx_pnalloc(pool, len);
  953.         if (p == NULL) {
  954.             return NGX_ERROR;
  955.         }

  956.         len = ngx_sock_ntop(sa, socklen, p, len, 1);

  957.         addr = &u->addrs[u->naddrs++];

  958.         addr->sockaddr = sa;
  959.         addr->socklen = socklen;

  960.         addr->name.len = len;
  961.         addr->name.data = p;
  962.     }

  963.     return NGX_OK;
  964. }


  965. ngx_int_t
  966. ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
  967.     struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
  968. {
  969.     struct sockaddr_in   *sin1, *sin2;
  970. #if (NGX_HAVE_INET6)
  971.     struct sockaddr_in6  *sin61, *sin62;
  972. #endif
  973. #if (NGX_HAVE_UNIX_DOMAIN)
  974.     size_t                len;
  975.     struct sockaddr_un   *saun1, *saun2;
  976. #endif

  977.     if (sa1->sa_family != sa2->sa_family) {
  978.         return NGX_DECLINED;
  979.     }

  980.     switch (sa1->sa_family) {

  981. #if (NGX_HAVE_INET6)
  982.     case AF_INET6:

  983.         sin61 = (struct sockaddr_in6 *) sa1;
  984.         sin62 = (struct sockaddr_in6 *) sa2;

  985.         if (cmp_port && sin61->sin6_port != sin62->sin6_port) {
  986.             return NGX_DECLINED;
  987.         }

  988.         if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
  989.             return NGX_DECLINED;
  990.         }

  991.         break;
  992. #endif

  993. #if (NGX_HAVE_UNIX_DOMAIN)
  994.     case AF_UNIX:

  995.         saun1 = (struct sockaddr_un *) sa1;
  996.         saun2 = (struct sockaddr_un *) sa2;

  997.         if (slen1 < slen2) {
  998.             len = slen1 - offsetof(struct sockaddr_un, sun_path);

  999.         } else {
  1000.             len = slen2 - offsetof(struct sockaddr_un, sun_path);
  1001.         }

  1002.         if (len > sizeof(saun1->sun_path)) {
  1003.             len = sizeof(saun1->sun_path);
  1004.         }

  1005.         if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path, len) != 0) {
  1006.             return NGX_DECLINED;
  1007.         }

  1008.         break;
  1009. #endif

  1010.     default: /* AF_INET */

  1011.         sin1 = (struct sockaddr_in *) sa1;
  1012.         sin2 = (struct sockaddr_in *) sa2;

  1013.         if (cmp_port && sin1->sin_port != sin2->sin_port) {
  1014.             return NGX_DECLINED;
  1015.         }

  1016.         if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
  1017.             return NGX_DECLINED;
  1018.         }

  1019.         break;
  1020.     }

  1021.     return NGX_OK;
  1022. }


  1023. in_port_t
  1024. ngx_inet_get_port(struct sockaddr *sa)
  1025. {
  1026.     struct sockaddr_in   *sin;
  1027. #if (NGX_HAVE_INET6)
  1028.     struct sockaddr_in6  *sin6;
  1029. #endif

  1030.     switch (sa->sa_family) {

  1031. #if (NGX_HAVE_INET6)
  1032.     case AF_INET6:
  1033.         sin6 = (struct sockaddr_in6 *) sa;
  1034.         return ntohs(sin6->sin6_port);
  1035. #endif

  1036. #if (NGX_HAVE_UNIX_DOMAIN)
  1037.     case AF_UNIX:
  1038.         return 0;
  1039. #endif

  1040.     default: /* AF_INET */
  1041.         sin = (struct sockaddr_in *) sa;
  1042.         return ntohs(sin->sin_port);
  1043.     }
  1044. }


  1045. void
  1046. ngx_inet_set_port(struct sockaddr *sa, in_port_t port)
  1047. {
  1048.     struct sockaddr_in   *sin;
  1049. #if (NGX_HAVE_INET6)
  1050.     struct sockaddr_in6  *sin6;
  1051. #endif

  1052.     switch (sa->sa_family) {

  1053. #if (NGX_HAVE_INET6)
  1054.     case AF_INET6:
  1055.         sin6 = (struct sockaddr_in6 *) sa;
  1056.         sin6->sin6_port = htons(port);
  1057.         break;
  1058. #endif

  1059. #if (NGX_HAVE_UNIX_DOMAIN)
  1060.     case AF_UNIX:
  1061.         break;
  1062. #endif

  1063.     default: /* AF_INET */
  1064.         sin = (struct sockaddr_in *) sa;
  1065.         sin->sin_port = htons(port);
  1066.         break;
  1067.     }
  1068. }


  1069. ngx_uint_t
  1070. ngx_inet_wildcard(struct sockaddr *sa)
  1071. {
  1072.     struct sockaddr_in   *sin;
  1073. #if (NGX_HAVE_INET6)
  1074.     struct sockaddr_in6  *sin6;
  1075. #endif

  1076.     switch (sa->sa_family) {

  1077.     case AF_INET:
  1078.         sin = (struct sockaddr_in *) sa;

  1079.         if (sin->sin_addr.s_addr == INADDR_ANY) {
  1080.             return 1;
  1081.         }

  1082.         break;

  1083. #if (NGX_HAVE_INET6)

  1084.     case AF_INET6:
  1085.         sin6 = (struct sockaddr_in6 *) sa;

  1086.         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  1087.             return 1;
  1088.         }

  1089.         break;

  1090. #endif
  1091.     }

  1092.     return 0;
  1093. }