Annotation of embedaddon/nginx/src/core/ngx_inet.c, revision 1.1.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>