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