|
|
1.1 root 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.12 (Berkeley) 5/19/86";
9: #endif LIBC_SCCS and not lint
10:
11: #include <sys/types.h>
12: #include <sys/socket.h>
13: #include <netinet/in.h>
14: #include <ctype.h>
15: #include <netdb.h>
16: #include <stdio.h>
17: #include <errno.h>
18: #include <arpa/inet.h>
19: #include <arpa/nameser.h>
20: #include <resolv.h>
21:
22: #define MAXALIASES 35
23: #define MAXADDRS 35
24:
25: static char *h_addr_ptrs[MAXADDRS + 1];
26:
27: static struct hostent host;
28: static char *host_aliases[MAXALIASES];
29: static char hostbuf[BUFSIZ+1];
30: static struct in_addr host_addr;
31: static char HOSTDB[] = "/etc/hosts";
32: static FILE *hostf = NULL;
33: static char line[BUFSIZ+1];
34: static char hostaddr[MAXADDRS];
35: static char *host_addrs[2];
36: static int stayopen = 0;
37: static char *any();
38:
39: typedef union {
40: HEADER qb1;
41: char qb2[PACKETSZ];
42: } querybuf;
43:
44: static union {
45: long al;
46: char ac;
47: } align;
48:
49:
50: int h_errno;
51: extern errno;
52:
53: static struct hostent *
54: getanswer(msg, msglen, iquery)
55: char *msg;
56: int msglen, iquery;
57: {
58: register HEADER *hp;
59: register char *cp;
60: register int n;
61: querybuf answer;
62: char *eom, *bp, **ap;
63: int type, class, buflen, ancount, qdcount;
64: int haveanswer, getclass = C_ANY;
65: char **hap;
66:
67: n = res_send(msg, msglen, (char *)&answer, sizeof(answer));
68: if (n < 0) {
69: #ifdef DEBUG
70: int terrno;
71: terrno = errno;
72: if (_res.options & RES_DEBUG)
73: printf("res_send failed\n");
74: errno = terrno;
75: #endif
76: h_errno = TRY_AGAIN;
77: return (NULL);
78: }
79: eom = (char *)&answer + n;
80: /*
81: * find first satisfactory answer
82: */
83: hp = (HEADER *) &answer;
84: ancount = ntohs(hp->ancount);
85: qdcount = ntohs(hp->qdcount);
86: if (hp->rcode != NOERROR || ancount == 0) {
87: #ifdef DEBUG
88: if (_res.options & RES_DEBUG)
89: printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
90: #endif
91: switch (hp->rcode) {
92: case NXDOMAIN:
93: /* Check if it's an authoritive answer */
94: if (hp->aa)
95: h_errno = HOST_NOT_FOUND;
96: else
97: h_errno = TRY_AGAIN;
98: break;
99: case SERVFAIL:
100: h_errno = TRY_AGAIN;
101: break;
102: case NOERROR:
103: h_errno = NO_ADDRESS;
104: break;
105: case FORMERR:
106: case NOTIMP:
107: case REFUSED:
108: h_errno = NO_RECOVERY;
109: }
110: return (NULL);
111: }
112: bp = hostbuf;
113: buflen = sizeof(hostbuf);
114: cp = (char *)&answer + sizeof(HEADER);
115: if (qdcount) {
116: if (iquery) {
117: if ((n = dn_expand((char *)&answer, eom,
118: cp, bp, buflen)) < 0) {
119: h_errno = NO_RECOVERY;
120: return (NULL);
121: }
122: cp += n + QFIXEDSZ;
123: host.h_name = bp;
124: n = strlen(bp) + 1;
125: bp += n;
126: buflen -= n;
127: } else
128: cp += dn_skip(cp) + QFIXEDSZ;
129: while (--qdcount > 0)
130: cp += dn_skip(cp) + QFIXEDSZ;
131: } else if (iquery) {
132: if (hp->aa)
133: h_errno = HOST_NOT_FOUND;
134: else
135: h_errno = TRY_AGAIN;
136: return (NULL);
137: }
138: ap = host_aliases;
139: host.h_aliases = host_aliases;
140: hap = h_addr_ptrs;
141: host.h_addr_list = h_addr_ptrs;
142: haveanswer = 0;
143: while (--ancount >= 0 && cp < eom) {
144: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
145: break;
146: cp += n;
147: type = getshort(cp);
148: cp += sizeof(u_short);
149: class = getshort(cp);
150: cp += sizeof(u_short) + sizeof(u_long);
151: n = getshort(cp);
152: cp += sizeof(u_short);
153: if (type == T_CNAME) {
154: cp += n;
155: if (ap >= &host_aliases[MAXALIASES-1])
156: continue;
157: *ap++ = bp;
158: n = strlen(bp) + 1;
159: bp += n;
160: buflen -= n;
161: continue;
162: }
163: if (type == T_PTR) {
164: if ((n = dn_expand((char *)&answer, eom,
165: cp, bp, buflen)) < 0) {
166: cp += n;
167: continue;
168: }
169: cp += n;
170: host.h_name = bp;
171: return(&host);
172: }
173: if (type != T_A) {
174: #ifdef DEBUG
175: if (_res.options & RES_DEBUG)
176: printf("unexpected answer type %d, size %d\n",
177: type, n);
178: #endif
179: cp += n;
180: continue;
181: }
182: if (haveanswer) {
183: if (n != host.h_length) {
184: cp += n;
185: continue;
186: }
187: if (class != getclass) {
188: cp += n;
189: continue;
190: }
191: } else {
192: host.h_length = n;
193: getclass = class;
194: host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
195: if (!iquery) {
196: host.h_name = bp;
197: bp += strlen(bp) + 1;
198: }
199: }
200:
201: bp += ((u_long)bp % sizeof(align));
202:
203: if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
204: #ifdef DEBUG
205: if (_res.options & RES_DEBUG)
206: printf("size (%d) too big\n", n);
207: #endif
208: break;
209: }
210: bcopy(cp, *hap++ = bp, n);
211: bp +=n;
212: cp += n;
213: haveanswer++;
214: }
215: if (haveanswer) {
216: *ap = NULL;
217: *hap = NULL;
218: return (&host);
219: } else {
220: h_errno = TRY_AGAIN;
221: return (NULL);
222: }
223: }
224:
225: struct hostent *
226: gethostbyname(name)
227: char *name;
228: {
229: int n;
230: querybuf buf;
231: register struct hostent *hp;
232: extern struct hostent *_gethtbyname();
233:
234: n = res_mkquery(QUERY, name, C_IN, T_A, (char *)NULL, 0, NULL,
235: (char *)&buf, sizeof(buf));
236: if (n < 0) {
237: #ifdef DEBUG
238: if (_res.options & RES_DEBUG)
239: printf("res_mkquery failed\n");
240: #endif
241: return (NULL);
242: }
243: hp = getanswer((char *)&buf, n, 0);
244: if (hp == NULL && errno == ECONNREFUSED)
245: hp = _gethtbyname(name);
246: return(hp);
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 (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_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL,
268: (char *)&buf, sizeof(buf));
269: if (n < 0) {
270: #ifdef DEBUG
271: if (_res.options & RES_DEBUG)
272: printf("res_mkquery failed\n");
273: #endif
274: return (NULL);
275: }
276: hp = getanswer((char *)&buf, n, 1);
277: if (hp == NULL && errno == ECONNREFUSED)
278: hp = _gethtbyaddr(addr, len, type);
279: if (hp == NULL)
280: return(NULL);
281: hp->h_addrtype = type;
282: hp->h_length = len;
283: h_addr_ptrs[0] = (char *)&host_addr;
284: h_addr_ptrs[1] = (char *)0;
285: host_addr = *(struct in_addr *)addr;
286: return(hp);
287: }
288:
289:
290: _sethtent(f)
291: int f;
292: {
293: if (hostf == NULL)
294: hostf = fopen(HOSTDB, "r" );
295: else
296: rewind(hostf);
297: stayopen |= f;
298: }
299:
300: _endhtent()
301: {
302: if (hostf && !stayopen) {
303: (void) fclose(hostf);
304: hostf = NULL;
305: }
306: }
307:
308: struct hostent *
309: _gethtent()
310: {
311: char *p;
312: register char *cp, **q;
313:
314: if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
315: return (NULL);
316: again:
317: if ((p = fgets(line, BUFSIZ, hostf)) == NULL)
318: return (NULL);
319: if (*p == '#')
320: goto again;
321: cp = any(p, "#\n");
322: if (cp == NULL)
323: goto again;
324: *cp = '\0';
325: cp = any(p, " \t");
326: if (cp == NULL)
327: goto again;
328: *cp++ = '\0';
329: /* THIS STUFF IS INTERNET SPECIFIC */
330: host.h_addr_list = host_addrs;
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: char lowname[128];
380: register char *lp = lowname;
381:
382: while (*name)
383: if (isupper(*name))
384: *lp++ = tolower(*name++);
385: else
386: *lp++ = *name++;
387: *lp = '\0';
388:
389: _sethtent(0);
390: while (p = _gethtent()) {
391: if (strcmp(p->h_name, lowname) == 0)
392: break;
393: for (cp = p->h_aliases; *cp != 0; cp++)
394: if (strcmp(*cp, lowname) == 0)
395: goto found;
396: }
397: found:
398: _endhtent();
399: return (p);
400: }
401:
402: struct hostent *
403: _gethtbyaddr(addr, len, type)
404: char *addr;
405: int len, type;
406: {
407: register struct hostent *p;
408:
409: _sethtent(0);
410: while (p = _gethtent())
411: if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
412: break;
413: _endhtent();
414: return (p);
415: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.