Commit | Line | Data |
---|---|---|
8ea4199d | 1 | /* |
5cfeec12 KB |
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 | |
f4f66d2c KB |
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. | |
8ea4199d DF |
16 | */ |
17 | ||
2ce81398 | 18 | #if defined(LIBC_SCCS) && !defined(lint) |
e714052f | 19 | static char sccsid[] = "@(#)gethostnamadr.c 6.36 (Berkeley) %G%"; |
5cfeec12 | 20 | #endif /* LIBC_SCCS and not lint */ |
b423e985 | 21 | |
7f2f8dda | 22 | #include <sys/param.h> |
f784656b RC |
23 | #include <sys/socket.h> |
24 | #include <netinet/in.h> | |
12379d92 | 25 | #include <ctype.h> |
337257b2 | 26 | #include <netdb.h> |
f784656b | 27 | #include <stdio.h> |
12379d92 | 28 | #include <errno.h> |
2795c575 | 29 | #include <arpa/inet.h> |
aa678832 | 30 | #include <arpa/nameser.h> |
f94b2f50 | 31 | #include <resolv.h> |
337257b2 RC |
32 | |
33 | #define MAXALIASES 35 | |
0e9a6a67 | 34 | #define MAXADDRS 35 |
337257b2 | 35 | |
412fa3e3 JB |
36 | static char *h_addr_ptrs[MAXADDRS + 1]; |
37 | ||
38 | static struct hostent host; | |
337257b2 | 39 | static char *host_aliases[MAXALIASES]; |
291cd39e | 40 | static char hostbuf[BUFSIZ+1]; |
4682c40f | 41 | static struct in_addr host_addr; |
12379d92 KD |
42 | static char HOSTDB[] = "/etc/hosts"; |
43 | static FILE *hostf = NULL; | |
12379d92 KD |
44 | static char hostaddr[MAXADDRS]; |
45 | static char *host_addrs[2]; | |
46 | static int stayopen = 0; | |
47 | static char *any(); | |
3a87f357 | 48 | |
b6a43c3e | 49 | #if PACKETSZ > 1024 |
0e9a6a67 | 50 | #define MAXPACKET PACKETSZ |
b6a43c3e | 51 | #else |
0e9a6a67 | 52 | #define MAXPACKET 1024 |
b6a43c3e MK |
53 | #endif |
54 | ||
c675dcaa | 55 | typedef union { |
0e9a6a67 KB |
56 | HEADER hdr; |
57 | u_char buf[MAXPACKET]; | |
c675dcaa KD |
58 | } querybuf; |
59 | ||
e714052f | 60 | typedef union { |
c675dcaa KD |
61 | long al; |
62 | char ac; | |
63 | } align; | |
64 | ||
6f4c7128 | 65 | |
fe8457be | 66 | int h_errno; |
12379d92 | 67 | extern errno; |
fe8457be | 68 | |
337257b2 | 69 | static struct hostent * |
0e9a6a67 KB |
70 | getanswer(answer, anslen, iquery) |
71 | querybuf *answer; | |
72 | int anslen; | |
73 | int iquery; | |
337257b2 | 74 | { |
f784656b | 75 | register HEADER *hp; |
0e9a6a67 | 76 | register u_char *cp; |
f784656b | 77 | register int n; |
0e9a6a67 KB |
78 | u_char *eom; |
79 | char *bp, **ap; | |
2795c575 KD |
80 | int type, class, buflen, ancount, qdcount; |
81 | int haveanswer, getclass = C_ANY; | |
412fa3e3 | 82 | char **hap; |
337257b2 | 83 | |
0e9a6a67 | 84 | eom = answer->buf + anslen; |
f784656b RC |
85 | /* |
86 | * find first satisfactory answer | |
87 | */ | |
0e9a6a67 | 88 | hp = &answer->hdr; |
f784656b | 89 | ancount = ntohs(hp->ancount); |
4682c40f | 90 | qdcount = ntohs(hp->qdcount); |
f784656b RC |
91 | bp = hostbuf; |
92 | buflen = sizeof(hostbuf); | |
0e9a6a67 | 93 | cp = answer->buf + sizeof(HEADER); |
4682c40f | 94 | if (qdcount) { |
f784656b | 95 | if (iquery) { |
0e9a6a67 | 96 | if ((n = dn_expand((char *)answer->buf, eom, |
91c656a0 | 97 | cp, bp, buflen)) < 0) { |
fe8457be | 98 | h_errno = NO_RECOVERY; |
e0313454 | 99 | return ((struct hostent *) NULL); |
fe8457be | 100 | } |
f784656b RC |
101 | cp += n + QFIXEDSZ; |
102 | host.h_name = bp; | |
103 | n = strlen(bp) + 1; | |
104 | bp += n; | |
105 | buflen -= n; | |
106 | } else | |
b6a43c3e | 107 | cp += dn_skipname(cp, eom) + QFIXEDSZ; |
4682c40f | 108 | while (--qdcount > 0) |
b6a43c3e | 109 | cp += dn_skipname(cp, eom) + QFIXEDSZ; |
fe8457be KD |
110 | } else if (iquery) { |
111 | if (hp->aa) | |
112 | h_errno = HOST_NOT_FOUND; | |
113 | else | |
114 | h_errno = TRY_AGAIN; | |
e0313454 | 115 | return ((struct hostent *) NULL); |
fe8457be | 116 | } |
412fa3e3 JB |
117 | ap = host_aliases; |
118 | host.h_aliases = host_aliases; | |
119 | hap = h_addr_ptrs; | |
15eda464 | 120 | #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ |
412fa3e3 | 121 | host.h_addr_list = h_addr_ptrs; |
da75bcd9 | 122 | #endif |
412fa3e3 | 123 | haveanswer = 0; |
f784656b | 124 | while (--ancount >= 0 && cp < eom) { |
0e9a6a67 | 125 | if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0) |
412fa3e3 | 126 | break; |
f784656b | 127 | cp += n; |
b1772b2c | 128 | type = _getshort(cp); |
f784656b | 129 | cp += sizeof(u_short); |
b1772b2c | 130 | class = _getshort(cp); |
f784656b | 131 | cp += sizeof(u_short) + sizeof(u_long); |
b1772b2c | 132 | n = _getshort(cp); |
f784656b RC |
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 | } | |
0e9a6a67 KB |
144 | if (iquery && type == T_PTR) { |
145 | if ((n = dn_expand((char *)answer->buf, eom, | |
2795c575 | 146 | cp, bp, buflen)) < 0) { |
4682c40f JB |
147 | cp += n; |
148 | continue; | |
149 | } | |
150 | cp += n; | |
151 | host.h_name = bp; | |
152 | return(&host); | |
153 | } | |
0e9a6a67 | 154 | if (iquery || type != T_A) { |
d1c1ab68 | 155 | #ifdef DEBUG |
f784656b RC |
156 | if (_res.options & RES_DEBUG) |
157 | printf("unexpected answer type %d, size %d\n", | |
158 | type, n); | |
d1c1ab68 | 159 | #endif |
412fa3e3 | 160 | cp += n; |
f784656b RC |
161 | continue; |
162 | } | |
412fa3e3 JB |
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; | |
82a65531 | 175 | host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; |
412fa3e3 JB |
176 | if (!iquery) { |
177 | host.h_name = bp; | |
178 | bp += strlen(bp) + 1; | |
179 | } | |
f784656b | 180 | } |
c675dcaa | 181 | |
8ad123ce | 182 | bp += sizeof(align) - ((u_long)bp % sizeof(align)); |
c675dcaa | 183 | |
f784656b | 184 | if (bp + n >= &hostbuf[sizeof(hostbuf)]) { |
d1c1ab68 | 185 | #ifdef DEBUG |
f784656b RC |
186 | if (_res.options & RES_DEBUG) |
187 | printf("size (%d) too big\n", n); | |
d1c1ab68 | 188 | #endif |
412fa3e3 | 189 | break; |
f784656b | 190 | } |
412fa3e3 JB |
191 | bcopy(cp, *hap++ = bp, n); |
192 | bp +=n; | |
193 | cp += n; | |
194 | haveanswer++; | |
f784656b | 195 | } |
412fa3e3 JB |
196 | if (haveanswer) { |
197 | *ap = NULL; | |
15eda464 | 198 | #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ |
412fa3e3 | 199 | *hap = NULL; |
8ad123ce MK |
200 | #else |
201 | host.h_addr = h_addr_ptrs[0]; | |
202 | #endif | |
412fa3e3 | 203 | return (&host); |
fe8457be KD |
204 | } else { |
205 | h_errno = TRY_AGAIN; | |
e0313454 | 206 | return ((struct hostent *) NULL); |
fe8457be | 207 | } |
337257b2 RC |
208 | } |
209 | ||
210 | struct hostent * | |
f784656b RC |
211 | gethostbyname(name) |
212 | char *name; | |
337257b2 | 213 | { |
0e9a6a67 KB |
214 | querybuf buf; |
215 | register char *cp; | |
f784656b | 216 | int n; |
12379d92 | 217 | extern struct hostent *_gethtbyname(); |
337257b2 | 218 | |
693999f7 KB |
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; | |
e0313454 | 229 | return ((struct hostent *) NULL); |
693999f7 KB |
230 | } |
231 | if (!isdigit(*cp) && *cp != '.') | |
232 | break; | |
233 | } | |
216ea7e1 | 234 | |
0e9a6a67 | 235 | if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { |
d1c1ab68 | 236 | #ifdef DEBUG |
f784656b | 237 | if (_res.options & RES_DEBUG) |
0e9a6a67 | 238 | printf("res_search failed\n"); |
d1c1ab68 | 239 | #endif |
0e9a6a67 KB |
240 | if (errno == ECONNREFUSED) |
241 | return (_gethtbyname(name)); | |
242 | else | |
243 | return ((struct hostent *) NULL); | |
3a87f357 | 244 | } |
0e9a6a67 | 245 | return (getanswer(&buf, n, 0)); |
337257b2 RC |
246 | } |
247 | ||
248 | struct hostent * | |
f784656b | 249 | gethostbyaddr(addr, len, type) |
337257b2 | 250 | char *addr; |
f784656b | 251 | int len, type; |
337257b2 | 252 | { |
f784656b | 253 | int n; |
c675dcaa | 254 | querybuf buf; |
4682c40f JB |
255 | register struct hostent *hp; |
256 | char qbuf[MAXDNAME]; | |
12379d92 KD |
257 | extern struct hostent *_gethtbyaddr(); |
258 | ||
f784656b | 259 | if (type != AF_INET) |
e0313454 | 260 | return ((struct hostent *) NULL); |
0d7830cc | 261 | (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", |
fe8457be KD |
262 | ((unsigned)addr[3] & 0xff), |
263 | ((unsigned)addr[2] & 0xff), | |
264 | ((unsigned)addr[1] & 0xff), | |
265 | ((unsigned)addr[0] & 0xff)); | |
0e9a6a67 | 266 | n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); |
f784656b | 267 | if (n < 0) { |
d1c1ab68 | 268 | #ifdef DEBUG |
f784656b | 269 | if (_res.options & RES_DEBUG) |
0e9a6a67 | 270 | printf("res_query failed\n"); |
d1c1ab68 | 271 | #endif |
0e9a6a67 | 272 | if (errno == ECONNREFUSED) |
6d1927cd | 273 | return (_gethtbyaddr(addr, len, type)); |
e0313454 | 274 | return ((struct hostent *) NULL); |
f268b9fa | 275 | } |
0e9a6a67 | 276 | hp = getanswer(&buf, n, 1); |
12379d92 | 277 | if (hp == NULL) |
e0313454 | 278 | return ((struct hostent *) NULL); |
4682c40f JB |
279 | hp->h_addrtype = type; |
280 | hp->h_length = len; | |
c7683dcd | 281 | h_addr_ptrs[0] = (char *)&host_addr; |
4682c40f JB |
282 | h_addr_ptrs[1] = (char *)0; |
283 | host_addr = *(struct in_addr *)addr; | |
284 | return(hp); | |
337257b2 | 285 | } |
c675dcaa | 286 | |
12379d92 KD |
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) { | |
2795c575 | 300 | (void) fclose(hostf); |
12379d92 KD |
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: | |
0e9a6a67 | 314 | if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) |
12379d92 KD |
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 */ | |
15eda464 | 327 | #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ |
12379d92 | 328 | host.h_addr_list = host_addrs; |
da75bcd9 | 329 | #endif |
12379d92 KD |
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; | |
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 | } |