Annotation of embedaddon/ntp/libntp/ntp_rfc2553.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the project nor the names of its contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29: 
                     30: /*
                     31:  * Copyright (c) 1982, 1986, 1990, 1993
                     32:  *     The Regents of the University of California.  All rights reserved.
                     33:  *
                     34:  * Redistribution and use in source and binary forms, with or without
                     35:  * modification, are permitted provided that the following conditions
                     36:  * are met:
                     37:  * 1. Redistributions of source code must retain the above copyright
                     38:  *    notice, this list of conditions and the following disclaimer.
                     39:  * 2. Redistributions in binary form must reproduce the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer in the
                     41:  *    documentation and/or other materials provided with the distribution.
                     42:  * 3. All advertising materials mentioning features or use of this software
                     43:  *    must display the following acknowledgement:
                     44:  *     This product includes software developed by the University of
                     45:  *     California, Berkeley and its contributors.
                     46:  * 4. Neither the name of the University nor the names of its contributors
                     47:  *    may be used to endorse or promote products derived from this software
                     48:  *    without specific prior written permission.
                     49:  *
                     50:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     51:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     52:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     53:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     54:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     55:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     56:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     57:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     58:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     59:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     60:  * SUCH DAMAGE.
                     61:  *
                     62:  */
                     63: 
                     64: /*
                     65:  * Compatability shims with the rfc2553 API to simplify ntp.
                     66:  */
                     67: 
                     68: #include <config.h>
                     69: 
                     70: #include <sys/types.h>
                     71: #include <ctype.h>
                     72: #ifdef HAVE_SYS_SOCKET_H
                     73: #include <sys/socket.h>
                     74: #endif
                     75: #include <isc/net.h>
                     76: #ifdef HAVE_NETINET_IN_H
                     77: #include <netinet/in.h>
                     78: #endif
                     79: #include "ntp_rfc2553.h"
                     80: 
                     81: #include "ntpd.h"
                     82: #include "ntp_malloc.h"
                     83: #include "ntp_stdlib.h"
                     84: #include "ntp_string.h"
                     85: 
                     86: #ifndef ISC_PLATFORM_HAVEIPV6
                     87: 
                     88: static char *ai_errlist[] = {
                     89:        "Success",
                     90:        "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
                     91:        "Temporary failure in name resolution",         /* EAI_AGAIN      */
                     92:        "Invalid value for ai_flags",                   /* EAI_BADFLAGS   */
                     93:        "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
                     94:        "ai_family not supported",                      /* EAI_FAMILY     */
                     95:        "Memory allocation failure",                    /* EAI_MEMORY     */
                     96:        "No address associated with hostname",          /* EAI_NODATA     */
                     97:        "hostname nor servname provided, or not known", /* EAI_NONAME     */
                     98:        "servname not supported for ai_socktype",       /* EAI_SERVICE    */
                     99:        "ai_socktype not supported",                    /* EAI_SOCKTYPE   */
                    100:        "System error returned in errno",               /* EAI_SYSTEM     */
                    101:        "Invalid value for hints",                      /* EAI_BADHINTS   */
                    102:        "Resolved protocol is unknown",                 /* EAI_PROTOCOL   */
                    103:        "Unknown error",                                /* EAI_MAX        */
                    104: };
                    105: 
                    106: /*
                    107:  * Local declaration
                    108:  */
                    109: int
                    110: DNSlookup_name(
                    111:        const char *name,
                    112:        int ai_family,
                    113:        struct hostent **Addresses
                    114: );
                    115: 
                    116: #ifndef SYS_WINNT
                    117: /*
                    118:  * Encapsulate gethostbyname to control the error code
                    119:  */
                    120: int
                    121: DNSlookup_name(
                    122:        const char *name,
                    123:        int ai_family,
                    124:        struct hostent **Addresses
                    125: )
                    126: {
                    127:        *Addresses = gethostbyname(name);
                    128:        return (h_errno);
                    129: }
                    130: #endif
                    131: 
                    132: static int do_nodename (const char *nodename, struct addrinfo *ai,
                    133:     const struct addrinfo *hints);
                    134: 
                    135: int
                    136: getaddrinfo (const char *nodename, const char *servname,
                    137:        const struct addrinfo *hints, struct addrinfo **res)
                    138: {
                    139:        int rval;
                    140:        struct servent *sp;
                    141:        struct addrinfo *ai = NULL;
                    142:        int port;
                    143:        const char *proto = NULL;
                    144:        int family, socktype, flags, protocol;
                    145: 
                    146: 
                    147:        /*
                    148:         * If no name is provide just return an error
                    149:         */
                    150:        if (nodename == NULL && servname == NULL)
                    151:                return (EAI_NONAME);
                    152:        
                    153:        ai = calloc(sizeof(struct addrinfo), 1);
                    154:        if (ai == NULL)
                    155:                return (EAI_MEMORY);
                    156: 
                    157:        /*
                    158:         * Copy default values from hints, if available
                    159:         */
                    160:        if (hints != NULL) {
                    161:                ai->ai_flags = hints->ai_flags;
                    162:                ai->ai_family = hints->ai_family;
                    163:                ai->ai_socktype = hints->ai_socktype;
                    164:                ai->ai_protocol = hints->ai_protocol;
                    165: 
                    166:                family = hints->ai_family;
                    167:                socktype = hints->ai_socktype;
                    168:                protocol = hints->ai_protocol;
                    169:                flags = hints->ai_flags;
                    170: 
                    171:                switch (family) {
                    172:                case AF_UNSPEC:
                    173:                        switch (hints->ai_socktype) {
                    174:                        case SOCK_STREAM:
                    175:                                proto = "tcp";
                    176:                                break;
                    177:                        case SOCK_DGRAM:
                    178:                                proto = "udp";
                    179:                                break;
                    180:                        }
                    181:                        break;
                    182:                case AF_INET:
                    183:                case AF_INET6:
                    184:                        switch (hints->ai_socktype) {
                    185:                        case 0:
                    186:                                break;
                    187:                        case SOCK_STREAM:
                    188:                                proto = "tcp";
                    189:                                break;
                    190:                        case SOCK_DGRAM:
                    191:                                proto = "udp";
                    192:                                break;
                    193:                        case SOCK_RAW:
                    194:                                break;
                    195:                        default:
                    196:                                return (EAI_SOCKTYPE);
                    197:                        }
                    198:                        break;
                    199: #ifdef AF_LOCAL
                    200:                case AF_LOCAL:
                    201:                        switch (hints->ai_socktype) {
                    202:                        case 0:
                    203:                                break;
                    204:                        case SOCK_STREAM:
                    205:                                break;
                    206:                        case SOCK_DGRAM:
                    207:                                break;
                    208:                        default:
                    209:                                return (EAI_SOCKTYPE);
                    210:                        }
                    211:                        break;
                    212: #endif
                    213:                default:
                    214:                        return (EAI_FAMILY);
                    215:                }
                    216:        } else {
                    217:                protocol = 0;
                    218:                family = 0;
                    219:                socktype = 0;
                    220:                flags = 0;
                    221:        }
                    222: 
                    223:        rval = do_nodename(nodename, ai, hints);
                    224:        if (rval != 0) {
                    225:                freeaddrinfo(ai);
                    226:                return (rval);
                    227:        }
                    228: 
                    229:        /*
                    230:         * First, look up the service name (port) if it was
                    231:         * requested.  If the socket type wasn't specified, then
                    232:         * try and figure it out.
                    233:         */
                    234:        if (servname != NULL) {
                    235:                char *e;
                    236: 
                    237:                port = strtol(servname, &e, 10);
                    238:                if (*e == '\0') {
                    239:                        if (socktype == 0)
                    240:                                return (EAI_SOCKTYPE);
                    241:                        if (port < 0 || port > 65535)
                    242:                                return (EAI_SERVICE);
                    243:                        port = htons((unsigned short) port);
                    244:                } else {
                    245:                        sp = getservbyname(servname, proto);
                    246:                        if (sp == NULL)
                    247:                                return (EAI_SERVICE);
                    248:                        port = sp->s_port;
                    249:                        if (socktype == 0) {
                    250:                                if (strcmp(sp->s_proto, "tcp") == 0)
                    251:                                        socktype = SOCK_STREAM;
                    252:                                else if (strcmp(sp->s_proto, "udp") == 0)
                    253:                                        socktype = SOCK_DGRAM;
                    254:                        }
                    255:                }
                    256:        } else
                    257:                port = 0;
                    258: 
                    259:        /*
                    260:         *
                    261:         * Set up the port number
                    262:         */
                    263:        if (ai->ai_family == AF_INET)
                    264:                ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
                    265:        else if (ai->ai_family == AF_INET6)
                    266:                ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
                    267:        *res = ai;
                    268:        return (0);
                    269: }
                    270: 
                    271: void
                    272: freeaddrinfo(struct addrinfo *ai)
                    273: {
                    274:        if (ai->ai_canonname != NULL)
                    275:        {
                    276:                free(ai->ai_canonname);
                    277:                ai->ai_canonname = NULL;
                    278:        }
                    279:        if (ai->ai_addr != NULL)
                    280:        {
                    281:                free(ai->ai_addr);
                    282:                ai->ai_addr = NULL;
                    283:        }
                    284:        free(ai);
                    285:        ai = NULL;
                    286: }
                    287: 
                    288: int
                    289: getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
                    290:        size_t hostlen, char *serv, size_t servlen, int flags)
                    291: {
                    292:        struct hostent *hp;
                    293:        int namelen;
                    294: 
                    295:        if (sa->sa_family != AF_INET)
                    296:                return (EAI_FAMILY);
                    297:        hp = gethostbyaddr(
                    298:            (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
                    299:            4, AF_INET);
                    300:        if (hp == NULL) {
                    301:                if (h_errno == TRY_AGAIN)
                    302:                        return (EAI_AGAIN);
                    303:                else
                    304:                        return (EAI_FAIL);
                    305:        }
                    306:        if (host != NULL && hostlen > 0) {
                    307:                /*
                    308:                 * Don't exceed buffer
                    309:                 */
                    310:                namelen = min(strlen(hp->h_name), hostlen - 1);
                    311:                if (namelen > 0) {
                    312:                        strncpy(host, hp->h_name, namelen);
                    313:                        host[namelen] = '\0';
                    314:                }
                    315:        }
                    316:        return (0);
                    317: }
                    318: 
                    319: char *
                    320: gai_strerror(int ecode)
                    321: {
                    322:        if (ecode < 0 || ecode > EAI_MAX)
                    323:                ecode = EAI_MAX;
                    324:        return ai_errlist[ecode];
                    325: }
                    326: 
                    327: static int
                    328: do_nodename(
                    329:        const char *nodename,
                    330:        struct addrinfo *ai,
                    331:        const struct addrinfo *hints)
                    332: {
                    333:        struct hostent *hp = NULL;
                    334:        struct sockaddr_in *sockin;
                    335:        struct sockaddr_in6 *sockin6;
                    336:        int errval;
                    337: 
                    338:        ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
                    339:        if (ai->ai_addr == NULL)
                    340:                return (EAI_MEMORY);
                    341: 
                    342:        /*
                    343:         * For an empty node name just use the wildcard.
                    344:         * NOTE: We need to assume that the address family is
                    345:         * set elsewhere so that we can set the appropriate wildcard
                    346:         */
                    347:        if (nodename == NULL) {
                    348:                ai->ai_addrlen = sizeof(struct sockaddr_storage);
                    349:                if (ai->ai_family == AF_INET)
                    350:                {
                    351:                        sockin = (struct sockaddr_in *)ai->ai_addr;
                    352:                        sockin->sin_family = (short) ai->ai_family;
                    353:                        sockin->sin_addr.s_addr = htonl(INADDR_ANY);
                    354:                }
                    355:                else
                    356:                {
                    357:                        sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
                    358:                        sockin6->sin6_family = (short) ai->ai_family;
                    359:                        /*
                    360:                         * we have already zeroed out the address
                    361:                         * so we don't actually need to do this
                    362:                         * This assignment is causing problems so
                    363:                         * we don't do what this would do.
                    364:                         sockin6->sin6_addr = in6addr_any;
                    365:                         */
                    366:                }
                    367: #ifdef ISC_PLATFORM_HAVESALEN
                    368:                ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
                    369: #endif
                    370: 
                    371:                return (0);
                    372:        }
                    373: 
                    374:        /*
                    375:         * See if we have an IPv6 address
                    376:         */
                    377:        if(strchr(nodename, ':') != NULL) {
                    378:                if (inet_pton(AF_INET6, nodename,
                    379:                    &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
                    380:                        ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
                    381:                        ai->ai_family = AF_INET6;
                    382:                        ai->ai_addrlen = sizeof(struct sockaddr_in6);
                    383:                        return (0);
                    384:                }
                    385:        }
                    386: 
                    387:        /*
                    388:         * See if we have an IPv4 address
                    389:         */
                    390:        if (inet_pton(AF_INET, nodename,
                    391:            &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
                    392:                ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
                    393:                ai->ai_family = AF_INET;
                    394:                ai->ai_addrlen = sizeof(struct sockaddr_in);
                    395:                return (0);
                    396:        }
                    397: 
                    398:        /*
                    399:         * If the numeric host flag is set, don't attempt resolution
                    400:         */
                    401:        if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
                    402:                return (EAI_NONAME);
                    403: 
                    404:        /*
                    405:         * Look for a name
                    406:         */
                    407: 
                    408:        errval = DNSlookup_name(nodename, AF_INET, &hp);
                    409: 
                    410:        if (hp == NULL) {
                    411:                if (errval == TRY_AGAIN || errval == EAI_AGAIN)
                    412:                        return (EAI_AGAIN);
                    413:                else if (errval == EAI_NONAME) {
                    414:                        if (inet_pton(AF_INET, nodename,
                    415:                            &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
                    416:                                ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
                    417:                                ai->ai_family = AF_INET;
                    418:                                ai->ai_addrlen = sizeof(struct sockaddr_in);
                    419:                                return (0);
                    420:                        }
                    421:                        return (errval);
                    422:                }
                    423:                else
                    424:                {
                    425:                        return (errval);
                    426:                }
                    427:        }
                    428:        ai->ai_family = hp->h_addrtype;
                    429:        ai->ai_addrlen = sizeof(struct sockaddr);
                    430:        sockin = (struct sockaddr_in *)ai->ai_addr;
                    431:        memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
                    432:        ai->ai_addr->sa_family = hp->h_addrtype;
                    433: #ifdef ISC_PLATFORM_HAVESALEN
                    434:        ai->ai_addr->sa_len = sizeof(struct sockaddr);
                    435: #endif
                    436:        if (hints != NULL && hints->ai_flags & AI_CANONNAME)
                    437:                ai->ai_canonname = estrdup(hp->h_name);
                    438:        return (0);
                    439: }
                    440: 
                    441: #endif /* !ISC_PLATFORM_HAVEIPV6 */

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