1 /* 2 * Copyright (c) 1985, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)gethostnamadr.c 6.40 (Berkeley) 05/21/90"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/param.h> 23 #include <sys/socket.h> 24 #include <netinet/in.h> 25 #include <ctype.h> 26 #include <netdb.h> 27 #include <stdio.h> 28 #include <errno.h> 29 #include <arpa/inet.h> 30 #include <arpa/nameser.h> 31 #include <resolv.h> 32 33 #define MAXALIASES 35 34 #define MAXADDRS 35 35 36 static char *h_addr_ptrs[MAXADDRS + 1]; 37 38 static struct hostent host; 39 static char *host_aliases[MAXALIASES]; 40 static char hostbuf[BUFSIZ+1]; 41 static struct in_addr host_addr; 42 static FILE *hostf = NULL; 43 static char hostaddr[MAXADDRS]; 44 static char *host_addrs[2]; 45 static int stayopen = 0; 46 char *strpbrk(); 47 48 #if PACKETSZ > 1024 49 #define MAXPACKET PACKETSZ 50 #else 51 #define MAXPACKET 1024 52 #endif 53 54 typedef union { 55 HEADER hdr; 56 u_char buf[MAXPACKET]; 57 } querybuf; 58 59 typedef union { 60 long al; 61 char ac; 62 } align; 63 64 65 int h_errno; 66 extern errno; 67 68 static struct hostent * 69 getanswer(answer, anslen, iquery) 70 querybuf *answer; 71 int anslen; 72 int iquery; 73 { 74 register HEADER *hp; 75 register u_char *cp; 76 register int n; 77 u_char *eom; 78 char *bp, **ap; 79 int type, class, buflen, ancount, qdcount; 80 int haveanswer, getclass = C_ANY; 81 char **hap; 82 83 eom = answer->buf + anslen; 84 /* 85 * find first satisfactory answer 86 */ 87 hp = &answer->hdr; 88 ancount = ntohs(hp->ancount); 89 qdcount = ntohs(hp->qdcount); 90 bp = hostbuf; 91 buflen = sizeof(hostbuf); 92 cp = answer->buf + sizeof(HEADER); 93 if (qdcount) { 94 if (iquery) { 95 if ((n = dn_expand((char *)answer->buf, eom, 96 cp, bp, buflen)) < 0) { 97 h_errno = NO_RECOVERY; 98 return ((struct hostent *) NULL); 99 } 100 cp += n + QFIXEDSZ; 101 host.h_name = bp; 102 n = strlen(bp) + 1; 103 bp += n; 104 buflen -= n; 105 } else 106 cp += dn_skipname(cp, eom) + QFIXEDSZ; 107 while (--qdcount > 0) 108 cp += dn_skipname(cp, eom) + QFIXEDSZ; 109 } else if (iquery) { 110 if (hp->aa) 111 h_errno = HOST_NOT_FOUND; 112 else 113 h_errno = TRY_AGAIN; 114 return ((struct hostent *) NULL); 115 } 116 ap = host_aliases; 117 *ap = NULL; 118 host.h_aliases = host_aliases; 119 hap = h_addr_ptrs; 120 *hap = NULL; 121 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 122 host.h_addr_list = h_addr_ptrs; 123 #endif 124 haveanswer = 0; 125 while (--ancount >= 0 && cp < eom) { 126 if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0) 127 break; 128 cp += n; 129 type = _getshort(cp); 130 cp += sizeof(u_short); 131 class = _getshort(cp); 132 cp += sizeof(u_short) + sizeof(u_long); 133 n = _getshort(cp); 134 cp += sizeof(u_short); 135 if (type == T_CNAME) { 136 cp += n; 137 if (ap >= &host_aliases[MAXALIASES-1]) 138 continue; 139 *ap++ = bp; 140 n = strlen(bp) + 1; 141 bp += n; 142 buflen -= n; 143 continue; 144 } 145 if (iquery && type == T_PTR) { 146 if ((n = dn_expand((char *)answer->buf, eom, 147 cp, bp, buflen)) < 0) { 148 cp += n; 149 continue; 150 } 151 cp += n; 152 host.h_name = bp; 153 return(&host); 154 } 155 if (iquery || type != T_A) { 156 #ifdef DEBUG 157 if (_res.options & RES_DEBUG) 158 printf("unexpected answer type %d, size %d\n", 159 type, n); 160 #endif 161 cp += n; 162 continue; 163 } 164 if (haveanswer) { 165 if (n != host.h_length) { 166 cp += n; 167 continue; 168 } 169 if (class != getclass) { 170 cp += n; 171 continue; 172 } 173 } else { 174 host.h_length = n; 175 getclass = class; 176 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 177 if (!iquery) { 178 host.h_name = bp; 179 bp += strlen(bp) + 1; 180 } 181 } 182 183 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 184 185 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 186 #ifdef DEBUG 187 if (_res.options & RES_DEBUG) 188 printf("size (%d) too big\n", n); 189 #endif 190 break; 191 } 192 bcopy(cp, *hap++ = bp, n); 193 bp +=n; 194 cp += n; 195 haveanswer++; 196 } 197 if (haveanswer) { 198 *ap = NULL; 199 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 200 *hap = NULL; 201 #else 202 host.h_addr = h_addr_ptrs[0]; 203 #endif 204 return (&host); 205 } else { 206 h_errno = TRY_AGAIN; 207 return ((struct hostent *) NULL); 208 } 209 } 210 211 struct hostent * 212 gethostbyname(name) 213 char *name; 214 { 215 querybuf buf; 216 register char *cp; 217 int n; 218 extern struct hostent *_gethtbyname(); 219 220 /* 221 * disallow names consisting only of digits/dots, unless 222 * they end in a dot. 223 */ 224 if (isdigit(name[0])) 225 for (cp = name;; ++cp) { 226 if (!*cp) { 227 if (*--cp == '.') 228 break; 229 /* 230 * All-numeric, no dot at the end. 231 * Fake up a hostent as if we'd actually 232 * done a lookup. What if someone types 233 * 255.255.255.255? The test below will 234 * succeed spuriously... ??? 235 */ 236 if ((host_addr.s_addr = inet_addr(name)) == -1) { 237 h_errno = HOST_NOT_FOUND; 238 return((struct hostent *) NULL); 239 } 240 host.h_name = name; 241 host.h_aliases = host_aliases; 242 host_aliases[0] = NULL; 243 host.h_addrtype = AF_INET; 244 host.h_length = sizeof(u_long); 245 h_addr_ptrs[0] = (char *)&host_addr; 246 h_addr_ptrs[1] = (char *)0; 247 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 248 host.h_addr_list = h_addr_ptrs; 249 #else 250 host.h_addr = h_addr_ptrs[0]; 251 #endif 252 return (&host); 253 } 254 if (!isdigit(*cp) && *cp != '.') 255 break; 256 } 257 258 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 259 #ifdef DEBUG 260 if (_res.options & RES_DEBUG) 261 printf("res_search failed\n"); 262 #endif 263 if (errno == ECONNREFUSED) 264 return (_gethtbyname(name)); 265 else 266 return ((struct hostent *) NULL); 267 } 268 return (getanswer(&buf, n, 0)); 269 } 270 271 struct hostent * 272 gethostbyaddr(addr, len, type) 273 char *addr; 274 int len, type; 275 { 276 int n; 277 querybuf buf; 278 register struct hostent *hp; 279 char qbuf[MAXDNAME]; 280 extern struct hostent *_gethtbyaddr(); 281 282 if (type != AF_INET) 283 return ((struct hostent *) NULL); 284 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 285 ((unsigned)addr[3] & 0xff), 286 ((unsigned)addr[2] & 0xff), 287 ((unsigned)addr[1] & 0xff), 288 ((unsigned)addr[0] & 0xff)); 289 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 290 if (n < 0) { 291 #ifdef DEBUG 292 if (_res.options & RES_DEBUG) 293 printf("res_query failed\n"); 294 #endif 295 if (errno == ECONNREFUSED) 296 return (_gethtbyaddr(addr, len, type)); 297 return ((struct hostent *) NULL); 298 } 299 hp = getanswer(&buf, n, 1); 300 if (hp == NULL) 301 return ((struct hostent *) NULL); 302 hp->h_addrtype = type; 303 hp->h_length = len; 304 h_addr_ptrs[0] = (char *)&host_addr; 305 h_addr_ptrs[1] = (char *)0; 306 host_addr = *(struct in_addr *)addr; 307 #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ 308 hp->h_addr = h_addr_ptrs[0]; 309 #endif 310 return(hp); 311 } 312 313 _sethtent(f) 314 int f; 315 { 316 if (hostf == NULL) 317 hostf = fopen(_PATH_HOSTS, "r" ); 318 else 319 rewind(hostf); 320 stayopen |= f; 321 } 322 323 _endhtent() 324 { 325 if (hostf && !stayopen) { 326 (void) fclose(hostf); 327 hostf = NULL; 328 } 329 } 330 331 struct hostent * 332 _gethtent() 333 { 334 char *p; 335 register char *cp, **q; 336 337 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 338 return (NULL); 339 again: 340 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 341 return (NULL); 342 if (*p == '#') 343 goto again; 344 cp = strpbrk(p, "#\n"); 345 if (cp == NULL) 346 goto again; 347 *cp = '\0'; 348 cp = strpbrk(p, " \t"); 349 if (cp == NULL) 350 goto again; 351 *cp++ = '\0'; 352 /* THIS STUFF IS INTERNET SPECIFIC */ 353 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 354 host.h_addr_list = host_addrs; 355 #endif 356 host.h_addr = hostaddr; 357 *((u_long *)host.h_addr) = inet_addr(p); 358 host.h_length = sizeof (u_long); 359 host.h_addrtype = AF_INET; 360 while (*cp == ' ' || *cp == '\t') 361 cp++; 362 host.h_name = cp; 363 q = host.h_aliases = host_aliases; 364 cp = strpbrk(cp, " \t"); 365 if (cp != NULL) 366 *cp++ = '\0'; 367 while (cp && *cp) { 368 if (*cp == ' ' || *cp == '\t') { 369 cp++; 370 continue; 371 } 372 if (q < &host_aliases[MAXALIASES - 1]) 373 *q++ = cp; 374 cp = strpbrk(cp, " \t"); 375 if (cp != NULL) 376 *cp++ = '\0'; 377 } 378 *q = NULL; 379 return (&host); 380 } 381 382 struct hostent * 383 _gethtbyname(name) 384 char *name; 385 { 386 register struct hostent *p; 387 register char **cp; 388 389 _sethtent(0); 390 while (p = _gethtent()) { 391 if (strcasecmp(p->h_name, name) == 0) 392 break; 393 for (cp = p->h_aliases; *cp != 0; cp++) 394 if (strcasecmp(*cp, name) == 0) 395 goto found; 396 } 397 found: 398 _endhtent(); 399 return (p); 400 } 401 402 struct hostent * 403 _gethtbyaddr(addr, len, type) 404 char *addr; 405 int len, type; 406 { 407 register struct hostent *p; 408 409 _sethtent(0); 410 while (p = _gethtent()) 411 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 412 break; 413 _endhtent(); 414 return (p); 415 } 416