Annotation of embedaddon/ntp/libntp/ntp_rfc2553.c, revision 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>