Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 
0011 
0012 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
0013 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
0014 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
0015 static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u,
0016     struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total);
0017 
0018 
0019 in_addr_t
0020 ngx_inet_addr(u_char *text, size_t len)
0021 {
0022     u_char      *p, c;
0023     in_addr_t    addr;
0024     ngx_uint_t   octet, n;
0025 
0026     addr = 0;
0027     octet = 0;
0028     n = 0;
0029 
0030     for (p = text; p < text + len; p++) {
0031         c = *p;
0032 
0033         if (c >= '0' && c <= '9') {
0034             octet = octet * 10 + (c - '0');
0035 
0036             if (octet > 255) {
0037                 return INADDR_NONE;
0038             }
0039 
0040             continue;
0041         }
0042 
0043         if (c == '.') {
0044             addr = (addr << 8) + octet;
0045             octet = 0;
0046             n++;
0047             continue;
0048         }
0049 
0050         return INADDR_NONE;
0051     }
0052 
0053     if (n == 3) {
0054         addr = (addr << 8) + octet;
0055         return htonl(addr);
0056     }
0057 
0058     return INADDR_NONE;
0059 }
0060 
0061 
0062 #if (NGX_HAVE_INET6)
0063 
0064 ngx_int_t
0065 ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
0066 {
0067     u_char      c, *zero, *digit, *s, *d;
0068     size_t      len4;
0069     ngx_uint_t  n, nibbles, word;
0070 
0071     if (len == 0) {
0072         return NGX_ERROR;
0073     }
0074 
0075     zero = NULL;
0076     digit = NULL;
0077     len4 = 0;
0078     nibbles = 0;
0079     word = 0;
0080     n = 8;
0081 
0082     if (p[0] == ':') {
0083         p++;
0084         len--;
0085     }
0086 
0087     for (/* void */; len; len--) {
0088         c = *p++;
0089 
0090         if (c == ':') {
0091             if (nibbles) {
0092                 digit = p;
0093                 len4 = len;
0094                 *addr++ = (u_char) (word >> 8);
0095                 *addr++ = (u_char) (word & 0xff);
0096 
0097                 if (--n) {
0098                     nibbles = 0;
0099                     word = 0;
0100                     continue;
0101                 }
0102 
0103             } else {
0104                 if (zero == NULL) {
0105                     digit = p;
0106                     len4 = len;
0107                     zero = addr;
0108                     continue;
0109                 }
0110             }
0111 
0112             return NGX_ERROR;
0113         }
0114 
0115         if (c == '.' && nibbles) {
0116             if (n < 2 || digit == NULL) {
0117                 return NGX_ERROR;
0118             }
0119 
0120             word = ngx_inet_addr(digit, len4 - 1);
0121             if (word == INADDR_NONE) {
0122                 return NGX_ERROR;
0123             }
0124 
0125             word = ntohl(word);
0126             *addr++ = (u_char) ((word >> 24) & 0xff);
0127             *addr++ = (u_char) ((word >> 16) & 0xff);
0128             n--;
0129             break;
0130         }
0131 
0132         if (++nibbles > 4) {
0133             return NGX_ERROR;
0134         }
0135 
0136         if (c >= '0' && c <= '9') {
0137             word = word * 16 + (c - '0');
0138             continue;
0139         }
0140 
0141         c |= 0x20;
0142 
0143         if (c >= 'a' && c <= 'f') {
0144             word = word * 16 + (c - 'a') + 10;
0145             continue;
0146         }
0147 
0148         return NGX_ERROR;
0149     }
0150 
0151     if (nibbles == 0 && zero == NULL) {
0152         return NGX_ERROR;
0153     }
0154 
0155     *addr++ = (u_char) (word >> 8);
0156     *addr++ = (u_char) (word & 0xff);
0157 
0158     if (--n) {
0159         if (zero) {
0160             n *= 2;
0161             s = addr - 1;
0162             d = s + n;
0163             while (s >= zero) {
0164                 *d-- = *s--;
0165             }
0166             ngx_memzero(zero, n);
0167             return NGX_OK;
0168         }
0169 
0170     } else {
0171         if (zero == NULL) {
0172             return NGX_OK;
0173         }
0174     }
0175 
0176     return NGX_ERROR;
0177 }
0178 
0179 #endif
0180 
0181 
0182 size_t
0183 ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len,
0184     ngx_uint_t port)
0185 {
0186     u_char               *p;
0187 #if (NGX_HAVE_INET6 || NGX_HAVE_UNIX_DOMAIN)
0188     size_t                n;
0189 #endif
0190     struct sockaddr_in   *sin;
0191 #if (NGX_HAVE_INET6)
0192     struct sockaddr_in6  *sin6;
0193 #endif
0194 #if (NGX_HAVE_UNIX_DOMAIN)
0195     struct sockaddr_un   *saun;
0196 #endif
0197 
0198     switch (sa->sa_family) {
0199 
0200     case AF_INET:
0201 
0202         sin = (struct sockaddr_in *) sa;
0203         p = (u_char *) &sin->sin_addr;
0204 
0205         if (port) {
0206             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
0207                              p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
0208         } else {
0209             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
0210                              p[0], p[1], p[2], p[3]);
0211         }
0212 
0213         return (p - text);
0214 
0215 #if (NGX_HAVE_INET6)
0216 
0217     case AF_INET6:
0218 
0219         sin6 = (struct sockaddr_in6 *) sa;
0220 
0221         n = 0;
0222 
0223         if (port) {
0224             text[n++] = '[';
0225         }
0226 
0227         n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
0228 
0229         if (port) {
0230             n = ngx_sprintf(&text[1 + n], "]:%d",
0231                             ntohs(sin6->sin6_port)) - text;
0232         }
0233 
0234         return n;
0235 #endif
0236 
0237 #if (NGX_HAVE_UNIX_DOMAIN)
0238 
0239     case AF_UNIX:
0240         saun = (struct sockaddr_un *) sa;
0241 
0242         /* on Linux sockaddr might not include sun_path at all */
0243 
0244         if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
0245             p = ngx_snprintf(text, len, "unix:%Z");
0246 
0247         } else {
0248             n = ngx_strnlen((u_char *) saun->sun_path,
0249                             socklen - offsetof(struct sockaddr_un, sun_path));
0250             p = ngx_snprintf(text, len, "unix:%*s%Z", n, saun->sun_path);
0251         }
0252 
0253         /* we do not include trailing zero in address length */
0254 
0255         return (p - text - 1);
0256 
0257 #endif
0258 
0259     default:
0260         return 0;
0261     }
0262 }
0263 
0264 
0265 size_t
0266 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
0267 {
0268     u_char  *p;
0269 
0270     switch (family) {
0271 
0272     case AF_INET:
0273 
0274         p = addr;
0275 
0276         return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
0277                             p[0], p[1], p[2], p[3])
0278                - text;
0279 
0280 #if (NGX_HAVE_INET6)
0281 
0282     case AF_INET6:
0283         return ngx_inet6_ntop(addr, text, len);
0284 
0285 #endif
0286 
0287     default:
0288         return 0;
0289     }
0290 }
0291 
0292 
0293 #if (NGX_HAVE_INET6)
0294 
0295 size_t
0296 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
0297 {
0298     u_char      *dst;
0299     size_t       max, n;
0300     ngx_uint_t   i, zero, last;
0301 
0302     if (len < NGX_INET6_ADDRSTRLEN) {
0303         return 0;
0304     }
0305 
0306     zero = (ngx_uint_t) -1;
0307     last = (ngx_uint_t) -1;
0308     max = 1;
0309     n = 0;
0310 
0311     for (i = 0; i < 16; i += 2) {
0312 
0313         if (p[i] || p[i + 1]) {
0314 
0315             if (max < n) {
0316                 zero = last;
0317                 max = n;
0318             }
0319 
0320             n = 0;
0321             continue;
0322         }
0323 
0324         if (n++ == 0) {
0325             last = i;
0326         }
0327     }
0328 
0329     if (max < n) {
0330         zero = last;
0331         max = n;
0332     }
0333 
0334     dst = text;
0335     n = 16;
0336 
0337     if (zero == 0) {
0338 
0339         if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
0340             || (max == 6)
0341             || (max == 7 && p[14] != 0 && p[15] != 1))
0342         {
0343             n = 12;
0344         }
0345 
0346         *dst++ = ':';
0347     }
0348 
0349     for (i = 0; i < n; i += 2) {
0350 
0351         if (i == zero) {
0352             *dst++ = ':';
0353             i += (max - 1) * 2;
0354             continue;
0355         }
0356 
0357         dst = ngx_sprintf(dst, "%xd", p[i] * 256 + p[i + 1]);
0358 
0359         if (i < 14) {
0360             *dst++ = ':';
0361         }
0362     }
0363 
0364     if (n == 12) {
0365         dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
0366     }
0367 
0368     return dst - text;
0369 }
0370 
0371 #endif
0372 
0373 
0374 ngx_int_t
0375 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
0376 {
0377     u_char      *addr, *mask, *last;
0378     size_t       len;
0379     ngx_int_t    shift;
0380 #if (NGX_HAVE_INET6)
0381     ngx_int_t    rc;
0382     ngx_uint_t   s, i;
0383 #endif
0384 
0385     addr = text->data;
0386     last = addr + text->len;
0387 
0388     mask = ngx_strlchr(addr, last, '/');
0389     len = (mask ? mask : last) - addr;
0390 
0391     cidr->u.in.addr = ngx_inet_addr(addr, len);
0392 
0393     if (cidr->u.in.addr != INADDR_NONE) {
0394         cidr->family = AF_INET;
0395 
0396         if (mask == NULL) {
0397             cidr->u.in.mask = 0xffffffff;
0398             return NGX_OK;
0399         }
0400 
0401 #if (NGX_HAVE_INET6)
0402     } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
0403         cidr->family = AF_INET6;
0404 
0405         if (mask == NULL) {
0406             ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
0407             return NGX_OK;
0408         }
0409 
0410 #endif
0411     } else {
0412         return NGX_ERROR;
0413     }
0414 
0415     mask++;
0416 
0417     shift = ngx_atoi(mask, last - mask);
0418     if (shift == NGX_ERROR) {
0419         return NGX_ERROR;
0420     }
0421 
0422     switch (cidr->family) {
0423 
0424 #if (NGX_HAVE_INET6)
0425     case AF_INET6:
0426         if (shift > 128) {
0427             return NGX_ERROR;
0428         }
0429 
0430         addr = cidr->u.in6.addr.s6_addr;
0431         mask = cidr->u.in6.mask.s6_addr;
0432         rc = NGX_OK;
0433 
0434         for (i = 0; i < 16; i++) {
0435 
0436             s = (shift > 8) ? 8 : shift;
0437             shift -= s;
0438 
0439             mask[i] = (u_char) (0xffu << (8 - s));
0440 
0441             if (addr[i] != (addr[i] & mask[i])) {
0442                 rc = NGX_DONE;
0443                 addr[i] &= mask[i];
0444             }
0445         }
0446 
0447         return rc;
0448 #endif
0449 
0450     default: /* AF_INET */
0451         if (shift > 32) {
0452             return NGX_ERROR;
0453         }
0454 
0455         if (shift) {
0456             cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
0457 
0458         } else {
0459             /* x86 compilers use a shl instruction that shifts by modulo 32 */
0460             cidr->u.in.mask = 0;
0461         }
0462 
0463         if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
0464             return NGX_OK;
0465         }
0466 
0467         cidr->u.in.addr &= cidr->u.in.mask;
0468 
0469         return NGX_DONE;
0470     }
0471 }
0472 
0473 
0474 ngx_int_t
0475 ngx_cidr_match(struct sockaddr *sa, ngx_array_t *cidrs)
0476 {
0477 #if (NGX_HAVE_INET6)
0478     u_char           *p;
0479 #endif
0480     in_addr_t         inaddr;
0481     ngx_cidr_t       *cidr;
0482     ngx_uint_t        family, i;
0483 #if (NGX_HAVE_INET6)
0484     ngx_uint_t        n;
0485     struct in6_addr  *inaddr6;
0486 #endif
0487 
0488 #if (NGX_SUPPRESS_WARN)
0489     inaddr = 0;
0490 #if (NGX_HAVE_INET6)
0491     inaddr6 = NULL;
0492 #endif
0493 #endif
0494 
0495     family = sa->sa_family;
0496 
0497     if (family == AF_INET) {
0498         inaddr = ((struct sockaddr_in *) sa)->sin_addr.s_addr;
0499     }
0500 
0501 #if (NGX_HAVE_INET6)
0502     else if (family == AF_INET6) {
0503         inaddr6 = &((struct sockaddr_in6 *) sa)->sin6_addr;
0504 
0505         if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
0506             family = AF_INET;
0507 
0508             p = inaddr6->s6_addr;
0509 
0510             inaddr = p[12] << 24;
0511             inaddr += p[13] << 16;
0512             inaddr += p[14] << 8;
0513             inaddr += p[15];
0514 
0515             inaddr = htonl(inaddr);
0516         }
0517     }
0518 #endif
0519 
0520     for (cidr = cidrs->elts, i = 0; i < cidrs->nelts; i++) {
0521         if (cidr[i].family != family) {
0522             goto next;
0523         }
0524 
0525         switch (family) {
0526 
0527 #if (NGX_HAVE_INET6)
0528         case AF_INET6:
0529             for (n = 0; n < 16; n++) {
0530                 if ((inaddr6->s6_addr[n] & cidr[i].u.in6.mask.s6_addr[n])
0531                     != cidr[i].u.in6.addr.s6_addr[n])
0532                 {
0533                     goto next;
0534                 }
0535             }
0536             break;
0537 #endif
0538 
0539 #if (NGX_HAVE_UNIX_DOMAIN)
0540         case AF_UNIX:
0541             break;
0542 #endif
0543 
0544         default: /* AF_INET */
0545             if ((inaddr & cidr[i].u.in.mask) != cidr[i].u.in.addr) {
0546                 goto next;
0547             }
0548             break;
0549         }
0550 
0551         return NGX_OK;
0552 
0553     next:
0554         continue;
0555     }
0556 
0557     return NGX_DECLINED;
0558 }
0559 
0560 
0561 ngx_int_t
0562 ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
0563 {
0564     in_addr_t             inaddr;
0565     ngx_uint_t            family;
0566     struct sockaddr_in   *sin;
0567 #if (NGX_HAVE_INET6)
0568     struct in6_addr       inaddr6;
0569     struct sockaddr_in6  *sin6;
0570 
0571     /*
0572      * prevent MSVC8 warning:
0573      *    potentially uninitialized local variable 'inaddr6' used
0574      */
0575     ngx_memzero(&inaddr6, sizeof(struct in6_addr));
0576 #endif
0577 
0578     inaddr = ngx_inet_addr(text, len);
0579 
0580     if (inaddr != INADDR_NONE) {
0581         family = AF_INET;
0582         len = sizeof(struct sockaddr_in);
0583 
0584 #if (NGX_HAVE_INET6)
0585     } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
0586         family = AF_INET6;
0587         len = sizeof(struct sockaddr_in6);
0588 
0589 #endif
0590     } else {
0591         return NGX_DECLINED;
0592     }
0593 
0594     addr->sockaddr = ngx_pcalloc(pool, len);
0595     if (addr->sockaddr == NULL) {
0596         return NGX_ERROR;
0597     }
0598 
0599     addr->sockaddr->sa_family = (u_char) family;
0600     addr->socklen = len;
0601 
0602     switch (family) {
0603 
0604 #if (NGX_HAVE_INET6)
0605     case AF_INET6:
0606         sin6 = (struct sockaddr_in6 *) addr->sockaddr;
0607         ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
0608         break;
0609 #endif
0610 
0611     default: /* AF_INET */
0612         sin = (struct sockaddr_in *) addr->sockaddr;
0613         sin->sin_addr.s_addr = inaddr;
0614         break;
0615     }
0616 
0617     return NGX_OK;
0618 }
0619 
0620 
0621 ngx_int_t
0622 ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
0623     size_t len)
0624 {
0625     u_char     *p, *last;
0626     size_t      plen;
0627     ngx_int_t   rc, port;
0628 
0629     rc = ngx_parse_addr(pool, addr, text, len);
0630 
0631     if (rc != NGX_DECLINED) {
0632         return rc;
0633     }
0634 
0635     last = text + len;
0636 
0637 #if (NGX_HAVE_INET6)
0638     if (len && text[0] == '[') {
0639 
0640         p = ngx_strlchr(text, last, ']');
0641 
0642         if (p == NULL || p == last - 1 || *++p != ':') {
0643             return NGX_DECLINED;
0644         }
0645 
0646         text++;
0647         len -= 2;
0648 
0649     } else
0650 #endif
0651 
0652     {
0653         p = ngx_strlchr(text, last, ':');
0654 
0655         if (p == NULL) {
0656             return NGX_DECLINED;
0657         }
0658     }
0659 
0660     p++;
0661     plen = last - p;
0662 
0663     port = ngx_atoi(p, plen);
0664 
0665     if (port < 1 || port > 65535) {
0666         return NGX_DECLINED;
0667     }
0668 
0669     len -= plen + 1;
0670 
0671     rc = ngx_parse_addr(pool, addr, text, len);
0672 
0673     if (rc != NGX_OK) {
0674         return rc;
0675     }
0676 
0677     ngx_inet_set_port(addr->sockaddr, (in_port_t) port);
0678 
0679     return NGX_OK;
0680 }
0681 
0682 
0683 ngx_int_t
0684 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
0685 {
0686     u_char  *p;
0687     size_t   len;
0688 
0689     p = u->url.data;
0690     len = u->url.len;
0691 
0692     if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
0693         return ngx_parse_unix_domain_url(pool, u);
0694     }
0695 
0696     if (len && p[0] == '[') {
0697         return ngx_parse_inet6_url(pool, u);
0698     }
0699 
0700     return ngx_parse_inet_url(pool, u);
0701 }
0702 
0703 
0704 static ngx_int_t
0705 ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
0706 {
0707 #if (NGX_HAVE_UNIX_DOMAIN)
0708     u_char              *path, *uri, *last;
0709     size_t               len;
0710     struct sockaddr_un  *saun;
0711 
0712     len = u->url.len;
0713     path = u->url.data;
0714 
0715     path += 5;
0716     len -= 5;
0717 
0718     if (u->uri_part) {
0719 
0720         last = path + len;
0721         uri = ngx_strlchr(path, last, ':');
0722 
0723         if (uri) {
0724             len = uri - path;
0725             uri++;
0726             u->uri.len = last - uri;
0727             u->uri.data = uri;
0728         }
0729     }
0730 
0731     if (len == 0) {
0732         u->err = "no path in the unix domain socket";
0733         return NGX_ERROR;
0734     }
0735 
0736     u->host.len = len++;
0737     u->host.data = path;
0738 
0739     if (len > sizeof(saun->sun_path)) {
0740         u->err = "too long path in the unix domain socket";
0741         return NGX_ERROR;
0742     }
0743 
0744     u->socklen = sizeof(struct sockaddr_un);
0745     saun = (struct sockaddr_un *) &u->sockaddr;
0746     saun->sun_family = AF_UNIX;
0747     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
0748 
0749     u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
0750     if (u->addrs == NULL) {
0751         return NGX_ERROR;
0752     }
0753 
0754     saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
0755     if (saun == NULL) {
0756         return NGX_ERROR;
0757     }
0758 
0759     u->family = AF_UNIX;
0760     u->naddrs = 1;
0761 
0762     saun->sun_family = AF_UNIX;
0763     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
0764 
0765     u->addrs[0].sockaddr = (struct sockaddr *) saun;
0766     u->addrs[0].socklen = sizeof(struct sockaddr_un);
0767     u->addrs[0].name.len = len + 4;
0768     u->addrs[0].name.data = u->url.data;
0769 
0770     return NGX_OK;
0771 
0772 #else
0773 
0774     u->err = "the unix domain sockets are not supported on this platform";
0775 
0776     return NGX_ERROR;
0777 
0778 #endif
0779 }
0780 
0781 
0782 static ngx_int_t
0783 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
0784 {
0785     u_char              *host, *port, *last, *uri, *args, *dash;
0786     size_t               len;
0787     ngx_int_t            n;
0788     struct sockaddr_in  *sin;
0789 
0790     u->socklen = sizeof(struct sockaddr_in);
0791     sin = (struct sockaddr_in *) &u->sockaddr;
0792     sin->sin_family = AF_INET;
0793 
0794     u->family = AF_INET;
0795 
0796     host = u->url.data;
0797 
0798     last = host + u->url.len;
0799 
0800     port = ngx_strlchr(host, last, ':');
0801 
0802     uri = ngx_strlchr(host, last, '/');
0803 
0804     args = ngx_strlchr(host, last, '?');
0805 
0806     if (args) {
0807         if (uri == NULL || args < uri) {
0808             uri = args;
0809         }
0810     }
0811 
0812     if (uri) {
0813         if (u->listen || !u->uri_part) {
0814             u->err = "invalid host";
0815             return NGX_ERROR;
0816         }
0817 
0818         u->uri.len = last - uri;
0819         u->uri.data = uri;
0820 
0821         last = uri;
0822 
0823         if (uri < port) {
0824             port = NULL;
0825         }
0826     }
0827 
0828     if (port) {
0829         port++;
0830 
0831         len = last - port;
0832 
0833         if (u->listen) {
0834             dash = ngx_strlchr(port, last, '-');
0835 
0836             if (dash) {
0837                 dash++;
0838 
0839                 n = ngx_atoi(dash, last - dash);
0840 
0841                 if (n < 1 || n > 65535) {
0842                     u->err = "invalid port";
0843                     return NGX_ERROR;
0844                 }
0845 
0846                 u->last_port = (in_port_t) n;
0847 
0848                 len = dash - port - 1;
0849             }
0850         }
0851 
0852         n = ngx_atoi(port, len);
0853 
0854         if (n < 1 || n > 65535) {
0855             u->err = "invalid port";
0856             return NGX_ERROR;
0857         }
0858 
0859         if (u->last_port && n > u->last_port) {
0860             u->err = "invalid port range";
0861             return NGX_ERROR;
0862         }
0863 
0864         u->port = (in_port_t) n;
0865         sin->sin_port = htons((in_port_t) n);
0866 
0867         u->port_text.len = last - port;
0868         u->port_text.data = port;
0869 
0870         last = port - 1;
0871 
0872     } else {
0873         if (uri == NULL) {
0874 
0875             if (u->listen) {
0876 
0877                 /* test value as port only */
0878 
0879                 len = last - host;
0880 
0881                 dash = ngx_strlchr(host, last, '-');
0882 
0883                 if (dash) {
0884                     dash++;
0885 
0886                     n = ngx_atoi(dash, last - dash);
0887 
0888                     if (n == NGX_ERROR) {
0889                         goto no_port;
0890                     }
0891 
0892                     if (n < 1 || n > 65535) {
0893                         u->err = "invalid port";
0894 
0895                     } else {
0896                         u->last_port = (in_port_t) n;
0897                     }
0898 
0899                     len = dash - host - 1;
0900                 }
0901 
0902                 n = ngx_atoi(host, len);
0903 
0904                 if (n != NGX_ERROR) {
0905 
0906                     if (u->err) {
0907                         return NGX_ERROR;
0908                     }
0909 
0910                     if (n < 1 || n > 65535) {
0911                         u->err = "invalid port";
0912                         return NGX_ERROR;
0913                     }
0914 
0915                     if (u->last_port && n > u->last_port) {
0916                         u->err = "invalid port range";
0917                         return NGX_ERROR;
0918                     }
0919 
0920                     u->port = (in_port_t) n;
0921                     sin->sin_port = htons((in_port_t) n);
0922                     sin->sin_addr.s_addr = INADDR_ANY;
0923 
0924                     u->port_text.len = last - host;
0925                     u->port_text.data = host;
0926 
0927                     u->wildcard = 1;
0928 
0929                     return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr,
0930                                              u->socklen, 1);
0931                 }
0932             }
0933         }
0934 
0935 no_port:
0936 
0937         u->err = NULL;
0938         u->no_port = 1;
0939         u->port = u->default_port;
0940         sin->sin_port = htons(u->default_port);
0941         u->last_port = 0;
0942     }
0943 
0944     len = last - host;
0945 
0946     if (len == 0) {
0947         u->err = "no host";
0948         return NGX_ERROR;
0949     }
0950 
0951     u->host.len = len;
0952     u->host.data = host;
0953 
0954     if (u->listen && len == 1 && *host == '*') {
0955         sin->sin_addr.s_addr = INADDR_ANY;
0956         u->wildcard = 1;
0957         return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
0958     }
0959 
0960     sin->sin_addr.s_addr = ngx_inet_addr(host, len);
0961 
0962     if (sin->sin_addr.s_addr != INADDR_NONE) {
0963 
0964         if (sin->sin_addr.s_addr == INADDR_ANY) {
0965             u->wildcard = 1;
0966         }
0967 
0968         return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
0969     }
0970 
0971     if (u->no_resolve) {
0972         return NGX_OK;
0973     }
0974 
0975     if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
0976         return NGX_ERROR;
0977     }
0978 
0979     u->family = u->addrs[0].sockaddr->sa_family;
0980     u->socklen = u->addrs[0].socklen;
0981     ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
0982     u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr);
0983 
0984     return NGX_OK;
0985 }
0986 
0987 
0988 static ngx_int_t
0989 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
0990 {
0991 #if (NGX_HAVE_INET6)
0992     u_char               *p, *host, *port, *last, *uri, *dash;
0993     size_t                len;
0994     ngx_int_t             n;
0995     struct sockaddr_in6  *sin6;
0996 
0997     u->socklen = sizeof(struct sockaddr_in6);
0998     sin6 = (struct sockaddr_in6 *) &u->sockaddr;
0999     sin6->sin6_family = AF_INET6;
1000 
1001     host = u->url.data + 1;
1002 
1003     last = u->url.data + u->url.len;
1004 
1005     p = ngx_strlchr(host, last, ']');
1006 
1007     if (p == NULL) {
1008         u->err = "invalid host";
1009         return NGX_ERROR;
1010     }
1011 
1012     port = p + 1;
1013 
1014     uri = ngx_strlchr(port, last, '/');
1015 
1016     if (uri) {
1017         if (u->listen || !u->uri_part) {
1018             u->err = "invalid host";
1019             return NGX_ERROR;
1020         }
1021 
1022         u->uri.len = last - uri;
1023         u->uri.data = uri;
1024 
1025         last = uri;
1026     }
1027 
1028     if (port < last) {
1029         if (*port != ':') {
1030             u->err = "invalid host";
1031             return NGX_ERROR;
1032         }
1033 
1034         port++;
1035 
1036         len = last - port;
1037 
1038         if (u->listen) {
1039             dash = ngx_strlchr(port, last, '-');
1040 
1041             if (dash) {
1042                 dash++;
1043 
1044                 n = ngx_atoi(dash, last - dash);
1045 
1046                 if (n < 1 || n > 65535) {
1047                     u->err = "invalid port";
1048                     return NGX_ERROR;
1049                 }
1050 
1051                 u->last_port = (in_port_t) n;
1052 
1053                 len = dash - port - 1;
1054             }
1055         }
1056 
1057         n = ngx_atoi(port, len);
1058 
1059         if (n < 1 || n > 65535) {
1060             u->err = "invalid port";
1061             return NGX_ERROR;
1062         }
1063 
1064         if (u->last_port && n > u->last_port) {
1065             u->err = "invalid port range";
1066             return NGX_ERROR;
1067         }
1068 
1069         u->port = (in_port_t) n;
1070         sin6->sin6_port = htons((in_port_t) n);
1071 
1072         u->port_text.len = last - port;
1073         u->port_text.data = port;
1074 
1075     } else {
1076         u->no_port = 1;
1077         u->port = u->default_port;
1078         sin6->sin6_port = htons(u->default_port);
1079     }
1080 
1081     len = p - host;
1082 
1083     if (len == 0) {
1084         u->err = "no host";
1085         return NGX_ERROR;
1086     }
1087 
1088     u->host.len = len + 2;
1089     u->host.data = host - 1;
1090 
1091     if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
1092         u->err = "invalid IPv6 address";
1093         return NGX_ERROR;
1094     }
1095 
1096     if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1097         u->wildcard = 1;
1098     }
1099 
1100     u->family = AF_INET6;
1101 
1102     return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1);
1103 
1104 #else
1105 
1106     u->err = "the INET6 sockets are not supported on this platform";
1107 
1108     return NGX_ERROR;
1109 
1110 #endif
1111 }
1112 
1113 
1114 #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
1115 
1116 ngx_int_t
1117 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
1118 {
1119     u_char           *host;
1120     ngx_uint_t        n;
1121     struct addrinfo   hints, *res, *rp;
1122 
1123     host = ngx_alloc(u->host.len + 1, pool->log);
1124     if (host == NULL) {
1125         return NGX_ERROR;
1126     }
1127 
1128     (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
1129 
1130     ngx_memzero(&hints, sizeof(struct addrinfo));
1131     hints.ai_family = AF_UNSPEC;
1132     hints.ai_socktype = SOCK_STREAM;
1133 #ifdef AI_ADDRCONFIG
1134     hints.ai_flags = AI_ADDRCONFIG;
1135 #endif
1136 
1137     if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
1138         u->err = "host not found";
1139         ngx_free(host);
1140         return NGX_ERROR;
1141     }
1142 
1143     ngx_free(host);
1144 
1145     for (n = 0, rp = res; rp != NULL; rp = rp->ai_next) {
1146 
1147         switch (rp->ai_family) {
1148 
1149         case AF_INET:
1150         case AF_INET6:
1151             break;
1152 
1153         default:
1154             continue;
1155         }
1156 
1157         n++;
1158     }
1159 
1160     if (n == 0) {
1161         u->err = "host not found";
1162         goto failed;
1163     }
1164 
1165     /* MP: ngx_shared_palloc() */
1166 
1167     for (rp = res; rp != NULL; rp = rp->ai_next) {
1168 
1169         switch (rp->ai_family) {
1170 
1171         case AF_INET:
1172         case AF_INET6:
1173             break;
1174 
1175         default:
1176             continue;
1177         }
1178 
1179         if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n)
1180             != NGX_OK)
1181         {
1182             goto failed;
1183         }
1184     }
1185 
1186     freeaddrinfo(res);
1187     return NGX_OK;
1188 
1189 failed:
1190 
1191     freeaddrinfo(res);
1192     return NGX_ERROR;
1193 }
1194 
1195 #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
1196 
1197 ngx_int_t
1198 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
1199 {
1200     u_char              *host;
1201     ngx_uint_t           i, n;
1202     struct hostent      *h;
1203     struct sockaddr_in   sin;
1204 
1205     /* AF_INET only */
1206 
1207     ngx_memzero(&sin, sizeof(struct sockaddr_in));
1208 
1209     sin.sin_family = AF_INET;
1210     sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len);
1211 
1212     if (sin.sin_addr.s_addr == INADDR_NONE) {
1213         host = ngx_alloc(u->host.len + 1, pool->log);
1214         if (host == NULL) {
1215             return NGX_ERROR;
1216         }
1217 
1218         (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
1219 
1220         h = gethostbyname((char *) host);
1221 
1222         ngx_free(host);
1223 
1224         if (h == NULL || h->h_addr_list[0] == NULL) {
1225             u->err = "host not found";
1226             return NGX_ERROR;
1227         }
1228 
1229         for (n = 0; h->h_addr_list[n] != NULL; n++) { /* void */ }
1230 
1231         /* MP: ngx_shared_palloc() */
1232 
1233         for (i = 0; i < n; i++) {
1234             sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
1235 
1236             if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
1237                                   sizeof(struct sockaddr_in), n)
1238                 != NGX_OK)
1239             {
1240                 return NGX_ERROR;
1241             }
1242         }
1243 
1244     } else {
1245 
1246         /* MP: ngx_shared_palloc() */
1247 
1248         if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin,
1249                               sizeof(struct sockaddr_in), 1)
1250             != NGX_OK)
1251         {
1252             return NGX_ERROR;
1253         }
1254     }
1255 
1256     return NGX_OK;
1257 }
1258 
1259 #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
1260 
1261 
1262 static ngx_int_t
1263 ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr,
1264     socklen_t socklen, ngx_uint_t total)
1265 {
1266     u_char           *p;
1267     size_t            len;
1268     ngx_uint_t        i, nports;
1269     ngx_addr_t       *addr;
1270     struct sockaddr  *sa;
1271 
1272     nports = u->last_port ? u->last_port - u->port + 1 : 1;
1273 
1274     if (u->addrs == NULL) {
1275         u->addrs = ngx_palloc(pool, total * nports * sizeof(ngx_addr_t));
1276         if (u->addrs == NULL) {
1277             return NGX_ERROR;
1278         }
1279     }
1280 
1281     for (i = 0; i < nports; i++) {
1282         sa = ngx_pcalloc(pool, socklen);
1283         if (sa == NULL) {
1284             return NGX_ERROR;
1285         }
1286 
1287         ngx_memcpy(sa, sockaddr, socklen);
1288 
1289         ngx_inet_set_port(sa, u->port + i);
1290 
1291         switch (sa->sa_family) {
1292 
1293 #if (NGX_HAVE_INET6)
1294         case AF_INET6:
1295             len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1;
1296             break;
1297 #endif
1298 
1299         default: /* AF_INET */
1300             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
1301         }
1302 
1303         p = ngx_pnalloc(pool, len);
1304         if (p == NULL) {
1305             return NGX_ERROR;
1306         }
1307 
1308         len = ngx_sock_ntop(sa, socklen, p, len, 1);
1309 
1310         addr = &u->addrs[u->naddrs++];
1311 
1312         addr->sockaddr = sa;
1313         addr->socklen = socklen;
1314 
1315         addr->name.len = len;
1316         addr->name.data = p;
1317     }
1318 
1319     return NGX_OK;
1320 }
1321 
1322 
1323 ngx_int_t
1324 ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
1325     struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
1326 {
1327     struct sockaddr_in   *sin1, *sin2;
1328 #if (NGX_HAVE_INET6)
1329     struct sockaddr_in6  *sin61, *sin62;
1330 #endif
1331 #if (NGX_HAVE_UNIX_DOMAIN)
1332     size_t                len;
1333     struct sockaddr_un   *saun1, *saun2;
1334 #endif
1335 
1336     if (sa1->sa_family != sa2->sa_family) {
1337         return NGX_DECLINED;
1338     }
1339 
1340     switch (sa1->sa_family) {
1341 
1342 #if (NGX_HAVE_INET6)
1343     case AF_INET6:
1344 
1345         sin61 = (struct sockaddr_in6 *) sa1;
1346         sin62 = (struct sockaddr_in6 *) sa2;
1347 
1348         if (cmp_port && sin61->sin6_port != sin62->sin6_port) {
1349             return NGX_DECLINED;
1350         }
1351 
1352         if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
1353             return NGX_DECLINED;
1354         }
1355 
1356         break;
1357 #endif
1358 
1359 #if (NGX_HAVE_UNIX_DOMAIN)
1360     case AF_UNIX:
1361 
1362         saun1 = (struct sockaddr_un *) sa1;
1363         saun2 = (struct sockaddr_un *) sa2;
1364 
1365         if (slen1 < slen2) {
1366             len = slen1 - offsetof(struct sockaddr_un, sun_path);
1367 
1368         } else {
1369             len = slen2 - offsetof(struct sockaddr_un, sun_path);
1370         }
1371 
1372         if (len > sizeof(saun1->sun_path)) {
1373             len = sizeof(saun1->sun_path);
1374         }
1375 
1376         if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path, len) != 0) {
1377             return NGX_DECLINED;
1378         }
1379 
1380         break;
1381 #endif
1382 
1383     default: /* AF_INET */
1384 
1385         sin1 = (struct sockaddr_in *) sa1;
1386         sin2 = (struct sockaddr_in *) sa2;
1387 
1388         if (cmp_port && sin1->sin_port != sin2->sin_port) {
1389             return NGX_DECLINED;
1390         }
1391 
1392         if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1393             return NGX_DECLINED;
1394         }
1395 
1396         break;
1397     }
1398 
1399     return NGX_OK;
1400 }
1401 
1402 
1403 in_port_t
1404 ngx_inet_get_port(struct sockaddr *sa)
1405 {
1406     struct sockaddr_in   *sin;
1407 #if (NGX_HAVE_INET6)
1408     struct sockaddr_in6  *sin6;
1409 #endif
1410 
1411     switch (sa->sa_family) {
1412 
1413 #if (NGX_HAVE_INET6)
1414     case AF_INET6:
1415         sin6 = (struct sockaddr_in6 *) sa;
1416         return ntohs(sin6->sin6_port);
1417 #endif
1418 
1419 #if (NGX_HAVE_UNIX_DOMAIN)
1420     case AF_UNIX:
1421         return 0;
1422 #endif
1423 
1424     default: /* AF_INET */
1425         sin = (struct sockaddr_in *) sa;
1426         return ntohs(sin->sin_port);
1427     }
1428 }
1429 
1430 
1431 void
1432 ngx_inet_set_port(struct sockaddr *sa, in_port_t port)
1433 {
1434     struct sockaddr_in   *sin;
1435 #if (NGX_HAVE_INET6)
1436     struct sockaddr_in6  *sin6;
1437 #endif
1438 
1439     switch (sa->sa_family) {
1440 
1441 #if (NGX_HAVE_INET6)
1442     case AF_INET6:
1443         sin6 = (struct sockaddr_in6 *) sa;
1444         sin6->sin6_port = htons(port);
1445         break;
1446 #endif
1447 
1448 #if (NGX_HAVE_UNIX_DOMAIN)
1449     case AF_UNIX:
1450         break;
1451 #endif
1452 
1453     default: /* AF_INET */
1454         sin = (struct sockaddr_in *) sa;
1455         sin->sin_port = htons(port);
1456         break;
1457     }
1458 }
1459 
1460 
1461 ngx_uint_t
1462 ngx_inet_wildcard(struct sockaddr *sa)
1463 {
1464     struct sockaddr_in   *sin;
1465 #if (NGX_HAVE_INET6)
1466     struct sockaddr_in6  *sin6;
1467 #endif
1468 
1469     switch (sa->sa_family) {
1470 
1471     case AF_INET:
1472         sin = (struct sockaddr_in *) sa;
1473 
1474         if (sin->sin_addr.s_addr == INADDR_ANY) {
1475             return 1;
1476         }
1477 
1478         break;
1479 
1480 #if (NGX_HAVE_INET6)
1481 
1482     case AF_INET6:
1483         sin6 = (struct sockaddr_in6 *) sa;
1484 
1485         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1486             return 1;
1487         }
1488 
1489         break;
1490 
1491 #endif
1492     }
1493 
1494     return 0;
1495 }