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