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