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