Annotation of embedaddon/nginx/src/core/ngx_inet.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: 
        !             8: #include <ngx_config.h>
        !             9: #include <ngx_core.h>
        !            10: 
        !            11: 
        !            12: static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
        !            13: static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
        !            14: static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
        !            15: 
        !            16: 
        !            17: in_addr_t
        !            18: ngx_inet_addr(u_char *text, size_t len)
        !            19: {
        !            20:     u_char      *p, c;
        !            21:     in_addr_t    addr;
        !            22:     ngx_uint_t   octet, n;
        !            23: 
        !            24:     addr = 0;
        !            25:     octet = 0;
        !            26:     n = 0;
        !            27: 
        !            28:     for (p = text; p < text + len; p++) {
        !            29: 
        !            30:         c = *p;
        !            31: 
        !            32:         if (c >= '0' && c <= '9') {
        !            33:             octet = octet * 10 + (c - '0');
        !            34:             continue;
        !            35:         }
        !            36: 
        !            37:         if (c == '.' && octet < 256) {
        !            38:             addr = (addr << 8) + octet;
        !            39:             octet = 0;
        !            40:             n++;
        !            41:             continue;
        !            42:         }
        !            43: 
        !            44:         return INADDR_NONE;
        !            45:     }
        !            46: 
        !            47:     if (n == 3 && octet < 256) {
        !            48:         addr = (addr << 8) + octet;
        !            49:         return htonl(addr);
        !            50:     }
        !            51: 
        !            52:     return INADDR_NONE;
        !            53: }
        !            54: 
        !            55: 
        !            56: #if (NGX_HAVE_INET6)
        !            57: 
        !            58: ngx_int_t
        !            59: ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
        !            60: {
        !            61:     u_char      c, *zero, *digit, *s, *d;
        !            62:     size_t      len4;
        !            63:     ngx_uint_t  n, nibbles, word;
        !            64: 
        !            65:     if (len == 0) {
        !            66:         return NGX_ERROR;
        !            67:     }
        !            68: 
        !            69:     zero = NULL;
        !            70:     digit = NULL;
        !            71:     len4 = 0;
        !            72:     nibbles = 0;
        !            73:     word = 0;
        !            74:     n = 8;
        !            75: 
        !            76:     if (p[0] == ':') {
        !            77:         p++;
        !            78:         len--;
        !            79:     }
        !            80: 
        !            81:     for (/* void */; len; len--) {
        !            82:         c = *p++;
        !            83: 
        !            84:         if (c == ':') {
        !            85:             if (nibbles) {
        !            86:                 digit = p;
        !            87:                 len4 = len;
        !            88:                 *addr++ = (u_char) (word >> 8);
        !            89:                 *addr++ = (u_char) (word & 0xff);
        !            90: 
        !            91:                 if (--n) {
        !            92:                     nibbles = 0;
        !            93:                     word = 0;
        !            94:                     continue;
        !            95:                 }
        !            96: 
        !            97:             } else {
        !            98:                 if (zero == NULL) {
        !            99:                     digit = p;
        !           100:                     len4 = len;
        !           101:                     zero = addr;
        !           102:                     continue;
        !           103:                 }
        !           104:             }
        !           105: 
        !           106:             return NGX_ERROR;
        !           107:         }
        !           108: 
        !           109:         if (c == '.' && nibbles) {
        !           110:             if (n < 2 || digit == NULL) {
        !           111:                 return NGX_ERROR;
        !           112:             }
        !           113: 
        !           114:             word = ngx_inet_addr(digit, len4 - 1);
        !           115:             if (word == INADDR_NONE) {
        !           116:                 return NGX_ERROR;
        !           117:             }
        !           118: 
        !           119:             word = ntohl(word);
        !           120:             *addr++ = (u_char) ((word >> 24) & 0xff);
        !           121:             *addr++ = (u_char) ((word >> 16) & 0xff);
        !           122:             n--;
        !           123:             break;
        !           124:         }
        !           125: 
        !           126:         if (++nibbles > 4) {
        !           127:             return NGX_ERROR;
        !           128:         }
        !           129: 
        !           130:         if (c >= '0' && c <= '9') {
        !           131:             word = word * 16 + (c - '0');
        !           132:             continue;
        !           133:         }
        !           134: 
        !           135:         c |= 0x20;
        !           136: 
        !           137:         if (c >= 'a' && c <= 'f') {
        !           138:             word = word * 16 + (c - 'a') + 10;
        !           139:             continue;
        !           140:         }
        !           141: 
        !           142:         return NGX_ERROR;
        !           143:     }
        !           144: 
        !           145:     if (nibbles == 0 && zero == NULL) {
        !           146:         return NGX_ERROR;
        !           147:     }
        !           148: 
        !           149:     *addr++ = (u_char) (word >> 8);
        !           150:     *addr++ = (u_char) (word & 0xff);
        !           151: 
        !           152:     if (--n) {
        !           153:         if (zero) {
        !           154:             n *= 2;
        !           155:             s = addr - 1;
        !           156:             d = s + n;
        !           157:             while (s >= zero) {
        !           158:                 *d-- = *s--;
        !           159:             }
        !           160:             ngx_memzero(zero, n);
        !           161:             return NGX_OK;
        !           162:         }
        !           163: 
        !           164:     } else {
        !           165:         if (zero == NULL) {
        !           166:             return NGX_OK;
        !           167:         }
        !           168:     }
        !           169: 
        !           170:     return NGX_ERROR;
        !           171: }
        !           172: 
        !           173: #endif
        !           174: 
        !           175: 
        !           176: size_t
        !           177: ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
        !           178: {
        !           179:     u_char               *p;
        !           180:     struct sockaddr_in   *sin;
        !           181: #if (NGX_HAVE_INET6)
        !           182:     size_t                n;
        !           183:     struct sockaddr_in6  *sin6;
        !           184: #endif
        !           185: #if (NGX_HAVE_UNIX_DOMAIN)
        !           186:     struct sockaddr_un   *saun;
        !           187: #endif
        !           188: 
        !           189:     switch (sa->sa_family) {
        !           190: 
        !           191:     case AF_INET:
        !           192: 
        !           193:         sin = (struct sockaddr_in *) sa;
        !           194:         p = (u_char *) &sin->sin_addr;
        !           195: 
        !           196:         if (port) {
        !           197:             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
        !           198:                              p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
        !           199:         } else {
        !           200:             p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
        !           201:                              p[0], p[1], p[2], p[3]);
        !           202:         }
        !           203: 
        !           204:         return (p - text);
        !           205: 
        !           206: #if (NGX_HAVE_INET6)
        !           207: 
        !           208:     case AF_INET6:
        !           209: 
        !           210:         sin6 = (struct sockaddr_in6 *) sa;
        !           211: 
        !           212:         n = 0;
        !           213: 
        !           214:         if (port) {
        !           215:             text[n++] = '[';
        !           216:         }
        !           217: 
        !           218:         n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
        !           219: 
        !           220:         if (port) {
        !           221:             n = ngx_sprintf(&text[1 + n], "]:%d",
        !           222:                             ntohs(sin6->sin6_port)) - text;
        !           223:         }
        !           224: 
        !           225:         return n;
        !           226: #endif
        !           227: 
        !           228: #if (NGX_HAVE_UNIX_DOMAIN)
        !           229: 
        !           230:     case AF_UNIX:
        !           231:         saun = (struct sockaddr_un *) sa;
        !           232: 
        !           233:         /* we do not include trailing zero in address length */
        !           234: 
        !           235:         return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
        !           236: 
        !           237: #endif
        !           238: 
        !           239:     default:
        !           240:         return 0;
        !           241:     }
        !           242: }
        !           243: 
        !           244: 
        !           245: size_t
        !           246: ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
        !           247: {
        !           248:     u_char  *p;
        !           249: 
        !           250:     switch (family) {
        !           251: 
        !           252:     case AF_INET:
        !           253: 
        !           254:         p = addr;
        !           255: 
        !           256:         return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
        !           257:                             p[0], p[1], p[2], p[3])
        !           258:                - text;
        !           259: 
        !           260: #if (NGX_HAVE_INET6)
        !           261: 
        !           262:     case AF_INET6:
        !           263:         return ngx_inet6_ntop(addr, text, len);
        !           264: 
        !           265: #endif
        !           266: 
        !           267:     default:
        !           268:         return 0;
        !           269:     }
        !           270: }
        !           271: 
        !           272: 
        !           273: #if (NGX_HAVE_INET6)
        !           274: 
        !           275: size_t
        !           276: ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
        !           277: {
        !           278:     u_char      *dst;
        !           279:     size_t       max, n;
        !           280:     ngx_uint_t   i, zero, last;
        !           281: 
        !           282:     if (len < NGX_INET6_ADDRSTRLEN) {
        !           283:         return 0;
        !           284:     }
        !           285: 
        !           286:     zero = (ngx_uint_t) -1;
        !           287:     last = (ngx_uint_t) -1;
        !           288:     max = 1;
        !           289:     n = 0;
        !           290: 
        !           291:     for (i = 0; i < 16; i += 2) {
        !           292: 
        !           293:         if (p[i] || p[i + 1]) {
        !           294: 
        !           295:             if (max < n) {
        !           296:                 zero = last;
        !           297:                 max = n;
        !           298:             }
        !           299: 
        !           300:             n = 0;
        !           301:             continue;
        !           302:         }
        !           303: 
        !           304:         if (n++ == 0) {
        !           305:             last = i;
        !           306:         }
        !           307:     }
        !           308: 
        !           309:     if (max < n) {
        !           310:         zero = last;
        !           311:         max = n;
        !           312:     }
        !           313: 
        !           314:     dst = text;
        !           315:     n = 16;
        !           316: 
        !           317:     if (zero == 0) {
        !           318: 
        !           319:         if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
        !           320:             || (max == 6)
        !           321:             || (max == 7 && p[14] != 0 && p[15] != 1))
        !           322:         {
        !           323:             n = 12;
        !           324:         }
        !           325: 
        !           326:         *dst++ = ':';
        !           327:     }
        !           328: 
        !           329:     for (i = 0; i < n; i += 2) {
        !           330: 
        !           331:         if (i == zero) {
        !           332:             *dst++ = ':';
        !           333:             i += (max - 1) * 2;
        !           334:             continue;
        !           335:         }
        !           336: 
        !           337:         dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
        !           338: 
        !           339:         if (i < 14) {
        !           340:             *dst++ = ':';
        !           341:         }
        !           342:     }
        !           343: 
        !           344:     if (n == 12) {
        !           345:         dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
        !           346:     }
        !           347: 
        !           348:     return dst - text;
        !           349: }
        !           350: 
        !           351: #endif
        !           352: 
        !           353: 
        !           354: ngx_int_t
        !           355: ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
        !           356: {
        !           357:     u_char      *addr, *mask, *last;
        !           358:     size_t       len;
        !           359:     ngx_int_t    shift;
        !           360: #if (NGX_HAVE_INET6)
        !           361:     ngx_int_t    rc;
        !           362:     ngx_uint_t   s, i;
        !           363: #endif
        !           364: 
        !           365:     addr = text->data;
        !           366:     last = addr + text->len;
        !           367: 
        !           368:     mask = ngx_strlchr(addr, last, '/');
        !           369:     len = (mask ? mask : last) - addr;
        !           370: 
        !           371:     cidr->u.in.addr = ngx_inet_addr(addr, len);
        !           372: 
        !           373:     if (cidr->u.in.addr != INADDR_NONE) {
        !           374:         cidr->family = AF_INET;
        !           375: 
        !           376:         if (mask == NULL) {
        !           377:             cidr->u.in.mask = 0xffffffff;
        !           378:             return NGX_OK;
        !           379:         }
        !           380: 
        !           381: #if (NGX_HAVE_INET6)
        !           382:     } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
        !           383:         cidr->family = AF_INET6;
        !           384: 
        !           385:         if (mask == NULL) {
        !           386:             ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
        !           387:             return NGX_OK;
        !           388:         }
        !           389: 
        !           390: #endif
        !           391:     } else {
        !           392:         return NGX_ERROR;
        !           393:     }
        !           394: 
        !           395:     mask++;
        !           396: 
        !           397:     shift = ngx_atoi(mask, last - mask);
        !           398:     if (shift == NGX_ERROR) {
        !           399:         return NGX_ERROR;
        !           400:     }
        !           401: 
        !           402:     switch (cidr->family) {
        !           403: 
        !           404: #if (NGX_HAVE_INET6)
        !           405:     case AF_INET6:
        !           406:         if (shift > 128) {
        !           407:             return NGX_ERROR;
        !           408:         }
        !           409: 
        !           410:         addr = cidr->u.in6.addr.s6_addr;
        !           411:         mask = cidr->u.in6.mask.s6_addr;
        !           412:         rc = NGX_OK;
        !           413: 
        !           414:         for (i = 0; i < 16; i++) {
        !           415: 
        !           416:             s = (shift > 8) ? 8 : shift;
        !           417:             shift -= s;
        !           418: 
        !           419:             mask[i] = (u_char) (0xffu << (8 - s));
        !           420: 
        !           421:             if (addr[i] != (addr[i] & mask[i])) {
        !           422:                 rc = NGX_DONE;
        !           423:                 addr[i] &= mask[i];
        !           424:             }
        !           425:         }
        !           426: 
        !           427:         return rc;
        !           428: #endif
        !           429: 
        !           430:     default: /* AF_INET */
        !           431:         if (shift > 32) {
        !           432:             return NGX_ERROR;
        !           433:         }
        !           434: 
        !           435:         if (shift) {
        !           436:             cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
        !           437: 
        !           438:         } else {
        !           439:             /* x86 compilers use a shl instruction that shifts by modulo 32 */
        !           440:             cidr->u.in.mask = 0;
        !           441:         }
        !           442: 
        !           443:         if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
        !           444:             return NGX_OK;
        !           445:         }
        !           446: 
        !           447:         cidr->u.in.addr &= cidr->u.in.mask;
        !           448: 
        !           449:         return NGX_DONE;
        !           450:     }
        !           451: }
        !           452: 
        !           453: 
        !           454: ngx_int_t
        !           455: ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
        !           456: {
        !           457:     in_addr_t             inaddr;
        !           458:     ngx_uint_t            family;
        !           459:     struct sockaddr_in   *sin;
        !           460: #if (NGX_HAVE_INET6)
        !           461:     struct in6_addr       inaddr6;
        !           462:     struct sockaddr_in6  *sin6;
        !           463: 
        !           464:     /*
        !           465:      * prevent MSVC8 warning:
        !           466:      *    potentially uninitialized local variable 'inaddr6' used
        !           467:      */
        !           468:     ngx_memzero(&inaddr6, sizeof(struct in6_addr));
        !           469: #endif
        !           470: 
        !           471:     inaddr = ngx_inet_addr(text, len);
        !           472: 
        !           473:     if (inaddr != INADDR_NONE) {
        !           474:         family = AF_INET;
        !           475:         len = sizeof(struct sockaddr_in);
        !           476: 
        !           477: #if (NGX_HAVE_INET6)
        !           478:     } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
        !           479:         family = AF_INET6;
        !           480:         len = sizeof(struct sockaddr_in6);
        !           481: 
        !           482: #endif
        !           483:     } else {
        !           484:         return NGX_DECLINED;
        !           485:     }
        !           486: 
        !           487:     addr->sockaddr = ngx_pcalloc(pool, len);
        !           488:     if (addr->sockaddr == NULL) {
        !           489:         return NGX_ERROR;
        !           490:     }
        !           491: 
        !           492:     addr->sockaddr->sa_family = (u_char) family;
        !           493:     addr->socklen = len;
        !           494: 
        !           495:     switch (family) {
        !           496: 
        !           497: #if (NGX_HAVE_INET6)
        !           498:     case AF_INET6:
        !           499:         sin6 = (struct sockaddr_in6 *) addr->sockaddr;
        !           500:         ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
        !           501:         break;
        !           502: #endif
        !           503: 
        !           504:     default: /* AF_INET */
        !           505:         sin = (struct sockaddr_in *) addr->sockaddr;
        !           506:         sin->sin_addr.s_addr = inaddr;
        !           507:         break;
        !           508:     }
        !           509: 
        !           510:     return NGX_OK;
        !           511: }
        !           512: 
        !           513: 
        !           514: ngx_int_t
        !           515: ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
        !           516: {
        !           517:     u_char  *p;
        !           518: 
        !           519:     p = u->url.data;
        !           520: 
        !           521:     if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
        !           522:         return ngx_parse_unix_domain_url(pool, u);
        !           523:     }
        !           524: 
        !           525:     if (p[0] == '[') {
        !           526:         return ngx_parse_inet6_url(pool, u);
        !           527:     }
        !           528: 
        !           529:     return ngx_parse_inet_url(pool, u);
        !           530: }
        !           531: 
        !           532: 
        !           533: static ngx_int_t
        !           534: ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
        !           535: {
        !           536: #if (NGX_HAVE_UNIX_DOMAIN)
        !           537:     u_char              *path, *uri, *last;
        !           538:     size_t               len;
        !           539:     struct sockaddr_un  *saun;
        !           540: 
        !           541:     len = u->url.len;
        !           542:     path = u->url.data;
        !           543: 
        !           544:     path += 5;
        !           545:     len -= 5;
        !           546: 
        !           547:     if (u->uri_part) {
        !           548: 
        !           549:         last = path + len;
        !           550:         uri = ngx_strlchr(path, last, ':');
        !           551: 
        !           552:         if (uri) {
        !           553:             len = uri - path;
        !           554:             uri++;
        !           555:             u->uri.len = last - uri;
        !           556:             u->uri.data = uri;
        !           557:         }
        !           558:     }
        !           559: 
        !           560:     if (len == 0) {
        !           561:         u->err = "no path in the unix domain socket";
        !           562:         return NGX_ERROR;
        !           563:     }
        !           564: 
        !           565:     u->host.len = len++;
        !           566:     u->host.data = path;
        !           567: 
        !           568:     if (len > sizeof(saun->sun_path)) {
        !           569:         u->err = "too long path in the unix domain socket";
        !           570:         return NGX_ERROR;
        !           571:     }
        !           572: 
        !           573:     u->socklen = sizeof(struct sockaddr_un);
        !           574:     saun = (struct sockaddr_un *) &u->sockaddr;
        !           575:     saun->sun_family = AF_UNIX;
        !           576:     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
        !           577: 
        !           578:     u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
        !           579:     if (u->addrs == NULL) {
        !           580:         return NGX_ERROR;
        !           581:     }
        !           582: 
        !           583:     saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
        !           584:     if (saun == NULL) {
        !           585:         return NGX_ERROR;
        !           586:     }
        !           587: 
        !           588:     u->family = AF_UNIX;
        !           589:     u->naddrs = 1;
        !           590: 
        !           591:     saun->sun_family = AF_UNIX;
        !           592:     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
        !           593: 
        !           594:     u->addrs[0].sockaddr = (struct sockaddr *) saun;
        !           595:     u->addrs[0].socklen = sizeof(struct sockaddr_un);
        !           596:     u->addrs[0].name.len = len + 4;
        !           597:     u->addrs[0].name.data = u->url.data;
        !           598: 
        !           599:     return NGX_OK;
        !           600: 
        !           601: #else
        !           602: 
        !           603:     u->err = "the unix domain sockets are not supported on this platform";
        !           604: 
        !           605:     return NGX_ERROR;
        !           606: 
        !           607: #endif
        !           608: }
        !           609: 
        !           610: 
        !           611: static ngx_int_t
        !           612: ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
        !           613: {
        !           614:     u_char               *p, *host, *port, *last, *uri, *args;
        !           615:     size_t                len;
        !           616:     ngx_int_t             n;
        !           617:     struct sockaddr_in   *sin;
        !           618: #if (NGX_HAVE_INET6)
        !           619:     struct sockaddr_in6  *sin6;
        !           620: #endif
        !           621: 
        !           622:     u->socklen = sizeof(struct sockaddr_in);
        !           623:     sin = (struct sockaddr_in *) &u->sockaddr;
        !           624:     sin->sin_family = AF_INET;
        !           625: 
        !           626:     u->family = AF_INET;
        !           627: 
        !           628:     host = u->url.data;
        !           629: 
        !           630:     last = host + u->url.len;
        !           631: 
        !           632:     port = ngx_strlchr(host, last, ':');
        !           633: 
        !           634:     uri = ngx_strlchr(host, last, '/');
        !           635: 
        !           636:     args = ngx_strlchr(host, last, '?');
        !           637: 
        !           638:     if (args) {
        !           639:         if (uri == NULL || args < uri) {
        !           640:             uri = args;
        !           641:         }
        !           642:     }
        !           643: 
        !           644:     if (uri) {
        !           645:         if (u->listen || !u->uri_part) {
        !           646:             u->err = "invalid host";
        !           647:             return NGX_ERROR;
        !           648:         }
        !           649: 
        !           650:         u->uri.len = last - uri;
        !           651:         u->uri.data = uri;
        !           652: 
        !           653:         last = uri;
        !           654: 
        !           655:         if (uri < port) {
        !           656:             port = NULL;
        !           657:         }
        !           658:     }
        !           659: 
        !           660:     if (port) {
        !           661:         port++;
        !           662: 
        !           663:         len = last - port;
        !           664: 
        !           665:         n = ngx_atoi(port, len);
        !           666: 
        !           667:         if (n < 1 || n > 65535) {
        !           668:             u->err = "invalid port";
        !           669:             return NGX_ERROR;
        !           670:         }
        !           671: 
        !           672:         u->port = (in_port_t) n;
        !           673:         sin->sin_port = htons((in_port_t) n);
        !           674: 
        !           675:         u->port_text.len = len;
        !           676:         u->port_text.data = port;
        !           677: 
        !           678:         last = port - 1;
        !           679: 
        !           680:     } else {
        !           681:         if (uri == NULL) {
        !           682: 
        !           683:             if (u->listen) {
        !           684: 
        !           685:                 /* test value as port only */
        !           686: 
        !           687:                 n = ngx_atoi(host, last - host);
        !           688: 
        !           689:                 if (n != NGX_ERROR) {
        !           690: 
        !           691:                     if (n < 1 || n > 65535) {
        !           692:                         u->err = "invalid port";
        !           693:                         return NGX_ERROR;
        !           694:                     }
        !           695: 
        !           696:                     u->port = (in_port_t) n;
        !           697:                     sin->sin_port = htons((in_port_t) n);
        !           698: 
        !           699:                     u->port_text.len = last - host;
        !           700:                     u->port_text.data = host;
        !           701: 
        !           702:                     u->wildcard = 1;
        !           703: 
        !           704:                     return NGX_OK;
        !           705:                 }
        !           706:             }
        !           707:         }
        !           708: 
        !           709:         u->no_port = 1;
        !           710:         u->port = u->default_port;
        !           711:         sin->sin_port = htons(u->default_port);
        !           712:     }
        !           713: 
        !           714:     len = last - host;
        !           715: 
        !           716:     if (len == 0) {
        !           717:         u->err = "no host";
        !           718:         return NGX_ERROR;
        !           719:     }
        !           720: 
        !           721:     u->host.len = len;
        !           722:     u->host.data = host;
        !           723: 
        !           724:     if (u->listen && len == 1 && *host == '*') {
        !           725:         sin->sin_addr.s_addr = INADDR_ANY;
        !           726:         u->wildcard = 1;
        !           727:         return NGX_OK;
        !           728:     }
        !           729: 
        !           730:     sin->sin_addr.s_addr = ngx_inet_addr(host, len);
        !           731: 
        !           732:     if (sin->sin_addr.s_addr != INADDR_NONE) {
        !           733: 
        !           734:         if (sin->sin_addr.s_addr == INADDR_ANY) {
        !           735:             u->wildcard = 1;
        !           736:         }
        !           737: 
        !           738:         u->naddrs = 1;
        !           739: 
        !           740:         u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
        !           741:         if (u->addrs == NULL) {
        !           742:             return NGX_ERROR;
        !           743:         }
        !           744: 
        !           745:         sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
        !           746:         if (sin == NULL) {
        !           747:             return NGX_ERROR;
        !           748:         }
        !           749: 
        !           750:         ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in));
        !           751: 
        !           752:         u->addrs[0].sockaddr = (struct sockaddr *) sin;
        !           753:         u->addrs[0].socklen = sizeof(struct sockaddr_in);
        !           754: 
        !           755:         p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
        !           756:         if (p == NULL) {
        !           757:             return NGX_ERROR;
        !           758:         }
        !           759: 
        !           760:         u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
        !           761:                                            &u->host, u->port) - p;
        !           762:         u->addrs[0].name.data = p;
        !           763: 
        !           764:         return NGX_OK;
        !           765:     }
        !           766: 
        !           767:     if (u->no_resolve) {
        !           768:         return NGX_OK;
        !           769:     }
        !           770: 
        !           771:     if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
        !           772:         return NGX_ERROR;
        !           773:     }
        !           774: 
        !           775:     u->family = u->addrs[0].sockaddr->sa_family;
        !           776:     u->socklen = u->addrs[0].socklen;
        !           777:     ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
        !           778: 
        !           779:     switch (u->family) {
        !           780: 
        !           781: #if (NGX_HAVE_INET6)
        !           782:     case AF_INET6:
        !           783:         sin6 = (struct sockaddr_in6 *) &u->sockaddr;
        !           784: 
        !           785:         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
        !           786:             u->wildcard = 1;
        !           787:         }
        !           788: 
        !           789:         break;
        !           790: #endif
        !           791: 
        !           792:     default: /* AF_INET */
        !           793:         sin = (struct sockaddr_in *) &u->sockaddr;
        !           794: 
        !           795:         if (sin->sin_addr.s_addr == INADDR_ANY) {
        !           796:             u->wildcard = 1;
        !           797:         }
        !           798: 
        !           799:         break;
        !           800:     }
        !           801: 
        !           802:     return NGX_OK;
        !           803: }
        !           804: 
        !           805: 
        !           806: static ngx_int_t
        !           807: ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
        !           808: {
        !           809: #if (NGX_HAVE_INET6)
        !           810:     u_char               *p, *host, *port, *last, *uri;
        !           811:     size_t                len;
        !           812:     ngx_int_t             n;
        !           813:     struct sockaddr_in6  *sin6;
        !           814: 
        !           815:     u->socklen = sizeof(struct sockaddr_in6);
        !           816:     sin6 = (struct sockaddr_in6 *) &u->sockaddr;
        !           817:     sin6->sin6_family = AF_INET6;
        !           818: 
        !           819:     host = u->url.data + 1;
        !           820: 
        !           821:     last = u->url.data + u->url.len;
        !           822: 
        !           823:     p = ngx_strlchr(host, last, ']');
        !           824: 
        !           825:     if (p == NULL) {
        !           826:         u->err = "invalid host";
        !           827:         return NGX_ERROR;
        !           828:     }
        !           829: 
        !           830:     if (last - p) {
        !           831: 
        !           832:         port = p + 1;
        !           833: 
        !           834:         uri = ngx_strlchr(port, last, '/');
        !           835: 
        !           836:         if (uri) {
        !           837:             if (u->listen || !u->uri_part) {
        !           838:                 u->err = "invalid host";
        !           839:                 return NGX_ERROR;
        !           840:             }
        !           841: 
        !           842:             u->uri.len = last - uri;
        !           843:             u->uri.data = uri;
        !           844: 
        !           845:             last = uri;
        !           846:         }
        !           847: 
        !           848:         if (*port == ':') {
        !           849:             port++;
        !           850: 
        !           851:             len = last - port;
        !           852: 
        !           853:             n = ngx_atoi(port, len);
        !           854: 
        !           855:             if (n < 1 || n > 65535) {
        !           856:                 u->err = "invalid port";
        !           857:                 return NGX_ERROR;
        !           858:             }
        !           859: 
        !           860:             u->port = (in_port_t) n;
        !           861:             sin6->sin6_port = htons((in_port_t) n);
        !           862: 
        !           863:             u->port_text.len = len;
        !           864:             u->port_text.data = port;
        !           865: 
        !           866:         } else {
        !           867:             u->no_port = 1;
        !           868:             u->port = u->default_port;
        !           869:             sin6->sin6_port = htons(u->default_port);
        !           870:         }
        !           871:     }
        !           872: 
        !           873:     len = p - host;
        !           874: 
        !           875:     if (len == 0) {
        !           876:         u->err = "no host";
        !           877:         return NGX_ERROR;
        !           878:     }
        !           879: 
        !           880:     u->host.len = len + 2;
        !           881:     u->host.data = host - 1;
        !           882: 
        !           883:     if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
        !           884:         u->err = "invalid IPv6 address";
        !           885:         return NGX_ERROR;
        !           886:     }
        !           887: 
        !           888:     if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
        !           889:         u->wildcard = 1;
        !           890:     }
        !           891: 
        !           892:     u->family = AF_INET6;
        !           893:     u->naddrs = 1;
        !           894: 
        !           895:     u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
        !           896:     if (u->addrs == NULL) {
        !           897:         return NGX_ERROR;
        !           898:     }
        !           899: 
        !           900:     sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
        !           901:     if (sin6 == NULL) {
        !           902:         return NGX_ERROR;
        !           903:     }
        !           904: 
        !           905:     ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6));
        !           906: 
        !           907:     u->addrs[0].sockaddr = (struct sockaddr *) sin6;
        !           908:     u->addrs[0].socklen = sizeof(struct sockaddr_in6);
        !           909: 
        !           910:     p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
        !           911:     if (p == NULL) {
        !           912:         return NGX_ERROR;
        !           913:     }
        !           914: 
        !           915:     u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
        !           916:                                        &u->host, u->port) - p;
        !           917:     u->addrs[0].name.data = p;
        !           918: 
        !           919:     return NGX_OK;
        !           920: 
        !           921: #else
        !           922: 
        !           923:     u->err = "the INET6 sockets are not supported on this platform";
        !           924: 
        !           925:     return NGX_ERROR;
        !           926: 
        !           927: #endif
        !           928: }
        !           929: 
        !           930: 
        !           931: #if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
        !           932: 
        !           933: ngx_int_t
        !           934: ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
        !           935: {
        !           936:     u_char               *p, *host;
        !           937:     size_t                len;
        !           938:     in_port_t             port;
        !           939:     ngx_uint_t            i;
        !           940:     struct addrinfo       hints, *res, *rp;
        !           941:     struct sockaddr_in   *sin;
        !           942:     struct sockaddr_in6  *sin6;
        !           943: 
        !           944:     port = htons(u->port);
        !           945: 
        !           946:     host = ngx_alloc(u->host.len + 1, pool->log);
        !           947:     if (host == NULL) {
        !           948:         return NGX_ERROR;
        !           949:     }
        !           950: 
        !           951:     (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
        !           952: 
        !           953:     ngx_memzero(&hints, sizeof(struct addrinfo));
        !           954:     hints.ai_family = AF_UNSPEC;
        !           955:     hints.ai_socktype = SOCK_STREAM;
        !           956: 
        !           957:     if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
        !           958:         u->err = "host not found";
        !           959:         ngx_free(host);
        !           960:         return NGX_ERROR;
        !           961:     }
        !           962: 
        !           963:     ngx_free(host);
        !           964: 
        !           965:     for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) {
        !           966: 
        !           967:         switch (rp->ai_family) {
        !           968: 
        !           969:         case AF_INET:
        !           970:         case AF_INET6:
        !           971:             break;
        !           972: 
        !           973:         default:
        !           974:             continue;
        !           975:         }
        !           976: 
        !           977:         i++;
        !           978:     }
        !           979: 
        !           980:     if (i == 0) {
        !           981:         u->err = "host not found";
        !           982:         goto failed;
        !           983:     }
        !           984: 
        !           985:     /* MP: ngx_shared_palloc() */
        !           986: 
        !           987:     u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
        !           988:     if (u->addrs == NULL) {
        !           989:         goto failed;
        !           990:     }
        !           991: 
        !           992:     u->naddrs = i;
        !           993: 
        !           994:     i = 0;
        !           995: 
        !           996:     /* AF_INET addresses first */
        !           997: 
        !           998:     for (rp = res; rp != NULL; rp = rp->ai_next) {
        !           999: 
        !          1000:         if (rp->ai_family != AF_INET) {
        !          1001:             continue;
        !          1002:         }
        !          1003: 
        !          1004:         sin = ngx_pcalloc(pool, rp->ai_addrlen);
        !          1005:         if (sin == NULL) {
        !          1006:             goto failed;
        !          1007:         }
        !          1008: 
        !          1009:         ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
        !          1010: 
        !          1011:         sin->sin_port = port;
        !          1012: 
        !          1013:         u->addrs[i].sockaddr = (struct sockaddr *) sin;
        !          1014:         u->addrs[i].socklen = rp->ai_addrlen;
        !          1015: 
        !          1016:         len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
        !          1017: 
        !          1018:         p = ngx_pnalloc(pool, len);
        !          1019:         if (p == NULL) {
        !          1020:             goto failed;
        !          1021:         }
        !          1022: 
        !          1023:         len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
        !          1024: 
        !          1025:         u->addrs[i].name.len = len;
        !          1026:         u->addrs[i].name.data = p;
        !          1027: 
        !          1028:         i++;
        !          1029:     }
        !          1030: 
        !          1031:     for (rp = res; rp != NULL; rp = rp->ai_next) {
        !          1032: 
        !          1033:         if (rp->ai_family != AF_INET6) {
        !          1034:             continue;
        !          1035:         }
        !          1036: 
        !          1037:         sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
        !          1038:         if (sin6 == NULL) {
        !          1039:             goto failed;
        !          1040:         }
        !          1041: 
        !          1042:         ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
        !          1043: 
        !          1044:         sin6->sin6_port = port;
        !          1045: 
        !          1046:         u->addrs[i].sockaddr = (struct sockaddr *) sin6;
        !          1047:         u->addrs[i].socklen = rp->ai_addrlen;
        !          1048: 
        !          1049:         len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
        !          1050: 
        !          1051:         p = ngx_pnalloc(pool, len);
        !          1052:         if (p == NULL) {
        !          1053:             goto failed;
        !          1054:         }
        !          1055: 
        !          1056:         len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
        !          1057: 
        !          1058:         u->addrs[i].name.len = len;
        !          1059:         u->addrs[i].name.data = p;
        !          1060: 
        !          1061:         i++;
        !          1062:     }
        !          1063: 
        !          1064:     freeaddrinfo(res);
        !          1065:     return NGX_OK;
        !          1066: 
        !          1067: failed:
        !          1068: 
        !          1069:     freeaddrinfo(res);
        !          1070:     return NGX_ERROR;
        !          1071: }
        !          1072: 
        !          1073: #else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
        !          1074: 
        !          1075: ngx_int_t
        !          1076: ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
        !          1077: {
        !          1078:     u_char              *p, *host;
        !          1079:     size_t               len;
        !          1080:     in_port_t            port;
        !          1081:     in_addr_t            in_addr;
        !          1082:     ngx_uint_t           i;
        !          1083:     struct hostent      *h;
        !          1084:     struct sockaddr_in  *sin;
        !          1085: 
        !          1086:     /* AF_INET only */
        !          1087: 
        !          1088:     port = htons(u->port);
        !          1089: 
        !          1090:     in_addr = ngx_inet_addr(u->host.data, u->host.len);
        !          1091: 
        !          1092:     if (in_addr == INADDR_NONE) {
        !          1093:         host = ngx_alloc(u->host.len + 1, pool->log);
        !          1094:         if (host == NULL) {
        !          1095:             return NGX_ERROR;
        !          1096:         }
        !          1097: 
        !          1098:         (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
        !          1099: 
        !          1100:         h = gethostbyname((char *) host);
        !          1101: 
        !          1102:         ngx_free(host);
        !          1103: 
        !          1104:         if (h == NULL || h->h_addr_list[0] == NULL) {
        !          1105:             u->err = "host not found";
        !          1106:             return NGX_ERROR;
        !          1107:         }
        !          1108: 
        !          1109:         for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
        !          1110: 
        !          1111:         /* MP: ngx_shared_palloc() */
        !          1112: 
        !          1113:         u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
        !          1114:         if (u->addrs == NULL) {
        !          1115:             return NGX_ERROR;
        !          1116:         }
        !          1117: 
        !          1118:         u->naddrs = i;
        !          1119: 
        !          1120:         for (i = 0; i < u->naddrs; i++) {
        !          1121: 
        !          1122:             sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
        !          1123:             if (sin == NULL) {
        !          1124:                 return NGX_ERROR;
        !          1125:             }
        !          1126: 
        !          1127:             sin->sin_family = AF_INET;
        !          1128:             sin->sin_port = port;
        !          1129:             sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
        !          1130: 
        !          1131:             u->addrs[i].sockaddr = (struct sockaddr *) sin;
        !          1132:             u->addrs[i].socklen = sizeof(struct sockaddr_in);
        !          1133: 
        !          1134:             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
        !          1135: 
        !          1136:             p = ngx_pnalloc(pool, len);
        !          1137:             if (p == NULL) {
        !          1138:                 return NGX_ERROR;
        !          1139:             }
        !          1140: 
        !          1141:             len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
        !          1142: 
        !          1143:             u->addrs[i].name.len = len;
        !          1144:             u->addrs[i].name.data = p;
        !          1145:         }
        !          1146: 
        !          1147:     } else {
        !          1148: 
        !          1149:         /* MP: ngx_shared_palloc() */
        !          1150: 
        !          1151:         u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
        !          1152:         if (u->addrs == NULL) {
        !          1153:             return NGX_ERROR;
        !          1154:         }
        !          1155: 
        !          1156:         sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
        !          1157:         if (sin == NULL) {
        !          1158:             return NGX_ERROR;
        !          1159:         }
        !          1160: 
        !          1161:         u->naddrs = 1;
        !          1162: 
        !          1163:         sin->sin_family = AF_INET;
        !          1164:         sin->sin_port = port;
        !          1165:         sin->sin_addr.s_addr = in_addr;
        !          1166: 
        !          1167:         u->addrs[0].sockaddr = (struct sockaddr *) sin;
        !          1168:         u->addrs[0].socklen = sizeof(struct sockaddr_in);
        !          1169: 
        !          1170:         p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
        !          1171:         if (p == NULL) {
        !          1172:             return NGX_ERROR;
        !          1173:         }
        !          1174: 
        !          1175:         u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
        !          1176:                                            &u->host, ntohs(port)) - p;
        !          1177:         u->addrs[0].name.data = p;
        !          1178:     }
        !          1179: 
        !          1180:     return NGX_OK;
        !          1181: }
        !          1182: 
        !          1183: #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>