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.34 (Berkeley) 06/27/88"; 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 static char *any(); 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 static 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 struct hostent *hp; 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 h_errno = HOST_NOT_FOUND; 230 return ((struct hostent *) NULL); 231 } 232 if (!isdigit(*cp) && *cp != '.') 233 break; 234 } 235 236 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 237 #ifdef DEBUG 238 if (_res.options & RES_DEBUG) 239 printf("res_search failed\n"); 240 #endif 241 if (errno == ECONNREFUSED) 242 return (_gethtbyname(name)); 243 else 244 return ((struct hostent *) NULL); 245 } 246 return (getanswer(&buf, n, 0)); 247 } 248 249 struct hostent * 250 gethostbyaddr(addr, len, type) 251 char *addr; 252 int len, type; 253 { 254 int n; 255 querybuf buf; 256 register struct hostent *hp; 257 char qbuf[MAXDNAME]; 258 extern struct hostent *_gethtbyaddr(); 259 260 if (type != AF_INET) 261 return ((struct hostent *) NULL); 262 (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 263 ((unsigned)addr[3] & 0xff), 264 ((unsigned)addr[2] & 0xff), 265 ((unsigned)addr[1] & 0xff), 266 ((unsigned)addr[0] & 0xff)); 267 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 268 if (n < 0) { 269 #ifdef DEBUG 270 if (_res.options & RES_DEBUG) 271 printf("res_query failed\n"); 272 #endif 273 if (errno == ECONNREFUSED) 274 return (_gethtbyaddr(addr, len, type)); 275 return ((struct hostent *) NULL); 276 } 277 hp = getanswer(&buf, n, 1); 278 if (hp == NULL) 279 return ((struct hostent *) NULL); 280 hp->h_addrtype = type; 281 hp->h_length = len; 282 h_addr_ptrs[0] = (char *)&host_addr; 283 h_addr_ptrs[1] = (char *)0; 284 host_addr = *(struct in_addr *)addr; 285 return(hp); 286 } 287 288 _sethtent(f) 289 int f; 290 { 291 if (hostf == NULL) 292 hostf = fopen(HOSTDB, "r" ); 293 else 294 rewind(hostf); 295 stayopen |= f; 296 } 297 298 _endhtent() 299 { 300 if (hostf && !stayopen) { 301 (void) fclose(hostf); 302 hostf = NULL; 303 } 304 } 305 306 struct hostent * 307 _gethtent() 308 { 309 char *p; 310 register char *cp, **q; 311 312 if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 313 return (NULL); 314 again: 315 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 316 return (NULL); 317 if (*p == '#') 318 goto again; 319 cp = any(p, "#\n"); 320 if (cp == NULL) 321 goto again; 322 *cp = '\0'; 323 cp = any(p, " \t"); 324 if (cp == NULL) 325 goto again; 326 *cp++ = '\0'; 327 /* THIS STUFF IS INTERNET SPECIFIC */ 328 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 329 host.h_addr_list = host_addrs; 330 #endif 331 host.h_addr = hostaddr; 332 *((u_long *)host.h_addr) = inet_addr(p); 333 host.h_length = sizeof (u_long); 334 host.h_addrtype = AF_INET; 335 while (*cp == ' ' || *cp == '\t') 336 cp++; 337 host.h_name = cp; 338 q = host.h_aliases = host_aliases; 339 cp = any(cp, " \t"); 340 if (cp != NULL) 341 *cp++ = '\0'; 342 while (cp && *cp) { 343 if (*cp == ' ' || *cp == '\t') { 344 cp++; 345 continue; 346 } 347 if (q < &host_aliases[MAXALIASES - 1]) 348 *q++ = cp; 349 cp = any(cp, " \t"); 350 if (cp != NULL) 351 *cp++ = '\0'; 352 } 353 *q = NULL; 354 return (&host); 355 } 356 357 static char * 358 any(cp, match) 359 register char *cp; 360 char *match; 361 { 362 register char *mp, c; 363 364 while (c = *cp) { 365 for (mp = match; *mp; mp++) 366 if (*mp == c) 367 return (cp); 368 cp++; 369 } 370 return ((char *)0); 371 } 372 373 struct hostent * 374 _gethtbyname(name) 375 char *name; 376 { 377 register struct hostent *p; 378 register char **cp; 379 380 _sethtent(0); 381 while (p = _gethtent()) { 382 if (strcasecmp(p->h_name, name) == 0) 383 break; 384 for (cp = p->h_aliases; *cp != 0; cp++) 385 if (strcasecmp(*cp, name) == 0) 386 goto found; 387 } 388 found: 389 _endhtent(); 390 return (p); 391 } 392 393 struct hostent * 394 _gethtbyaddr(addr, len, type) 395 char *addr; 396 int len, type; 397 { 398 register struct hostent *p; 399 400 _sethtent(0); 401 while (p = _gethtent()) 402 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 403 break; 404 _endhtent(); 405 return (p); 406 } 407