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>