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