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