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 #ifdef HAVE_CONFIG_H 69 #include <config.h> 70 #endif 71 72 #include <sys/types.h> 73 #include <ctype.h> 74 #include <sys/socket.h> 75 #include "ntp_rfc2553.h" 76 #ifdef HAVE_NETINET_IN_H 77 #include <netinet/in.h> 78 #endif 79 #include <netdb.h> 80 81 #include "ntpd.h" 82 #include "ntp_malloc.h" 83 #include "ntp_stdlib.h" 84 #include "ntp_string.h" 85 86 #ifndef HAVE_IPV6 87 88 #if defined(SYS_WINNT) 89 /* XXX This is the preferred way, but for some reason the SunOS compiler 90 * does not like it. 91 */ 92 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 93 #else 94 const struct in6_addr in6addr_any; 95 #endif 96 97 static char *ai_errlist[] = { 98 "Success", 99 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 100 "Temporary failure in name resolution", /* EAI_AGAIN */ 101 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 102 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 103 "ai_family not supported", /* EAI_FAMILY */ 104 "Memory allocation failure", /* EAI_MEMORY */ 105 "No address associated with hostname", /* EAI_NODATA */ 106 "hostname nor servname provided, or not known", /* EAI_NONAME */ 107 "servname not supported for ai_socktype", /* EAI_SERVICE */ 108 "ai_socktype not supported", /* EAI_SOCKTYPE */ 109 "System error returned in errno", /* EAI_SYSTEM */ 110 "Invalid value for hints", /* EAI_BADHINTS */ 111 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 112 "Unknown error", /* EAI_MAX */ 113 }; 114 115 static int ipv4_aton P((const char *, struct sockaddr_storage *)); 116 static int do_nodename P((const char *nodename, struct addrinfo *ai, 117 const struct addrinfo *hints)); 118 119 int 120 getaddrinfo (const char *nodename, const char *servname, 121 const struct addrinfo *hints, struct addrinfo **res) 122 { 123 int rval; 124 struct addrinfo *ai; 125 struct sockaddr_in *sockin; 126 127 ai = calloc(sizeof(struct addrinfo), 1); 128 if (ai == NULL) 129 return (EAI_MEMORY); 130 131 if (nodename != NULL) { 132 rval = do_nodename(nodename, ai, hints); 133 if (rval != 0) { 134 freeaddrinfo(ai); 135 return (rval); 136 } 137 } 138 if (nodename == NULL && hints != NULL) { 139 ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1); 140 if (ai->ai_addr == NULL) { 141 freeaddrinfo(ai); 142 return (EAI_MEMORY); 143 } 144 ai->ai_family = AF_INET; 145 ai->ai_addrlen = sizeof(struct sockaddr_storage); 146 sockin = (struct sockaddr_in *)ai->ai_addr; 147 sockin->sin_family = AF_INET; 148 sockin->sin_addr.s_addr = htonl(INADDR_ANY); 149 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 150 ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr); 151 #endif 152 } 153 if (servname != NULL) { 154 ai->ai_family = AF_INET; 155 ai->ai_socktype = SOCK_DGRAM; 156 if (strcmp(servname, "ntp") != 0) { 157 freeaddrinfo(ai); 158 return (EAI_SERVICE); 159 } 160 sockin = (struct sockaddr_in *)ai->ai_addr; 161 sockin->sin_port = htons(NTP_PORT); 162 } 163 *res = ai; 164 return (0); 165 } 166 167 void 168 freeaddrinfo(struct addrinfo *ai) 169 { 170 if (ai->ai_canonname != NULL) 171 free(ai->ai_canonname); 172 if (ai->ai_addr != NULL) 173 free(ai->ai_addr); 174 free(ai); 175 } 176 177 int 178 getnameinfo (const struct sockaddr *sa, u_int salen, char *host, 179 size_t hostlen, char *serv, size_t servlen, int flags) 180 { 181 struct hostent *hp; 182 183 if (sa->sa_family != AF_INET) 184 return (EAI_FAMILY); 185 hp = gethostbyaddr( 186 (const char *)&((const struct sockaddr_in *)sa)->sin_addr, 187 4, AF_INET); 188 if (hp == NULL) { 189 if (h_errno == TRY_AGAIN) 190 return (EAI_AGAIN); 191 else 192 return (EAI_FAIL); 193 } 194 if (host != NULL) { 195 strncpy(host, hp->h_name, hostlen); 196 host[hostlen] = '\0'; 197 } 198 return (0); 199 } 200 201 char * 202 gai_strerror(int ecode) 203 { 204 if (ecode < 0 || ecode > EAI_MAX) 205 ecode = EAI_MAX; 206 return ai_errlist[ecode]; 207 } 208 209 static int 210 do_nodename( 211 const char *nodename, 212 struct addrinfo *ai, 213 const struct addrinfo *hints) 214 { 215 struct hostent *hp; 216 struct sockaddr_in *sockin; 217 218 ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1); 219 if (ai->ai_addr == NULL) 220 return (EAI_MEMORY); 221 222 if (hints != NULL && hints->ai_flags & AI_NUMERICHOST) { 223 if (ipv4_aton(nodename, 224 (struct sockaddr_storage *)ai->ai_addr) == 1) { 225 ai->ai_family = AF_INET; 226 ai->ai_addrlen = sizeof(struct sockaddr_in); 227 return (0); 228 } 229 return (EAI_NONAME); 230 } 231 hp = gethostbyname(nodename); 232 if (hp == NULL) { 233 if (h_errno == TRY_AGAIN) 234 return (EAI_AGAIN); 235 else { 236 if (ipv4_aton(nodename, 237 (struct sockaddr_storage *)ai->ai_addr) == 1) { 238 ai->ai_family = AF_INET; 239 ai->ai_addrlen = sizeof(struct sockaddr_in); 240 return (0); 241 } 242 return (EAI_FAIL); 243 } 244 } 245 ai->ai_family = hp->h_addrtype; 246 ai->ai_addrlen = sizeof(struct sockaddr); 247 sockin = (struct sockaddr_in *)ai->ai_addr; 248 memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length); 249 ai->ai_addr->sa_family = hp->h_addrtype; 250 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 251 ai->ai_addr->sa_len = sizeof(struct sockaddr); 252 #endif 253 if (hints != NULL && hints->ai_flags & AI_CANONNAME) { 254 ai->ai_canonname = malloc(strlen(hp->h_name) + 1); 255 if (ai->ai_canonname == NULL) 256 return (EAI_MEMORY); 257 strcpy(ai->ai_canonname, hp->h_name); 258 } 259 return (0); 260 } 261 262 /* 263 * ipv4_aton - return a net number (this is crude, but careful) 264 */ 265 static int 266 ipv4_aton( 267 const char *num, 268 struct sockaddr_storage *saddr 269 ) 270 { 271 const char *cp; 272 char *bp; 273 int i; 274 int temp; 275 char buf[80]; /* will core dump on really stupid stuff */ 276 u_int32 netnum; 277 struct sockaddr_in *addr; 278 279 cp = num; 280 netnum = 0; 281 for (i = 0; i < 4; i++) { 282 bp = buf; 283 while (isdigit((int)*cp)) 284 *bp++ = *cp++; 285 if (bp == buf) 286 break; 287 288 if (i < 3) { 289 if (*cp++ != '.') 290 break; 291 } else if (*cp != '\0') 292 break; 293 294 *bp = '\0'; 295 temp = atoi(buf); 296 if (temp > 255) 297 break; 298 netnum <<= 8; 299 netnum += temp; 300 #ifdef DEBUG 301 if (debug > 3) 302 printf("ipv4_aton %s step %d buf %s temp %d netnum %lu\n", 303 num, i, buf, temp, (u_long)netnum); 304 #endif 305 } 306 307 if (i < 4) { 308 #ifdef DEBUG 309 if (debug > 3) 310 printf( 311 "ipv4_aton: \"%s\" invalid host number, line ignored\n", 312 num); 313 #endif 314 return (0); 315 } 316 317 /* 318 * make up socket address. Clear it out for neatness. 319 */ 320 memset((void *)saddr, 0, sizeof(struct sockaddr_storage)); 321 addr = (struct sockaddr_in *)saddr; 322 addr->sin_family = AF_INET; 323 addr->sin_port = htons(NTP_PORT); 324 addr->sin_addr.s_addr = htonl(netnum); 325 #ifdef DEBUG 326 if (debug > 1) 327 printf("ipv4_aton given %s, got %s.\n", num, ntoa(saddr)); 328 #endif 329 return (1); 330 } 331 #endif /* !HAVE_IPV6 */ 332