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