Back to home page

Nginx displayed by LXR

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