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