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