xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 24713)
1 /*
2  * Copyright (c) 1983 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 #ifndef lint
8 static char sccsid[] = "@(#)gethostnamadr.c	5.6 (Berkeley) 09/12/85";
9 #endif not lint
10 
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <netdb.h>
15 #include <stdio.h>
16 #include <arpa/nameser.h>
17 #include <arpa/resolv.h>
18 
19 #define	MAXALIASES	35
20 #define MAXADDRS	35
21 
22 static char *h_addr_ptrs[MAXADDRS + 1];
23 
24 static struct hostent host;
25 static char *host_aliases[MAXALIASES];
26 static char hostbuf[BUFSIZ+1];
27 
28 
29 static struct hostent *
30 getanswer(msg, msglen, iquery)
31 	char *msg;
32 	int msglen, iquery;
33 {
34 	register HEADER *hp;
35 	register char *cp;
36 	register int n;
37 	char answer[PACKETSZ];
38 	char *eom, *bp, **ap;
39 	int type, class, ancount, buflen;
40 	int haveanswer, getclass;
41 	char **hap;
42 
43 	n = res_send(msg, msglen, answer, sizeof(answer));
44 	if (n < 0) {
45 		if (_res.options & RES_DEBUG)
46 			printf("res_send failed\n");
47 		return (NULL);
48 	}
49 	eom = answer + n;
50 	/*
51 	 * find first satisfactory answer
52 	 */
53 	hp = (HEADER *) answer;
54 	ancount = ntohs(hp->ancount);
55 	if (hp->rcode != NOERROR || ancount == 0) {
56 		if (_res.options & RES_DEBUG)
57 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
58 		return (NULL);
59 	}
60 	bp = hostbuf;
61 	buflen = sizeof(hostbuf);
62 	cp = answer + sizeof(HEADER);
63 	if (hp->qdcount) {
64 		if (iquery) {
65 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
66 				return (NULL);
67 			cp += n + QFIXEDSZ;
68 			host.h_name = bp;
69 			n = strlen(bp) + 1;
70 			bp += n;
71 			buflen -= n;
72 		} else
73 			cp += dn_skip(cp) + QFIXEDSZ;
74 	} else if (iquery)
75 		return (NULL);
76 	ap = host_aliases;
77 	host.h_aliases = host_aliases;
78 	hap = h_addr_ptrs;
79 	host.h_addr_list = h_addr_ptrs;
80 	haveanswer = 0;
81 	while (--ancount >= 0 && cp < eom) {
82 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
83 			break;
84 		cp += n;
85 		type = getshort(cp);
86  		cp += sizeof(u_short);
87 		class = getshort(cp);
88  		cp += sizeof(u_short) + sizeof(u_long);
89 		n = getshort(cp);
90 		cp += sizeof(u_short);
91 		if (type == T_CNAME) {
92 			cp += n;
93 			if (ap >= &host_aliases[MAXALIASES-1])
94 				continue;
95 			*ap++ = bp;
96 			n = strlen(bp) + 1;
97 			bp += n;
98 			buflen -= n;
99 			continue;
100 		}
101 		if (type != T_A)  {
102 			if (_res.options & RES_DEBUG)
103 				printf("unexpected answer type %d, size %d\n",
104 					type, n);
105 			cp += n;
106 			continue;
107 		}
108 		if (haveanswer) {
109 			if (n != host.h_length) {
110 				cp += n;
111 				continue;
112 			}
113 			if (class != getclass) {
114 				cp += n;
115 				continue;
116 			}
117 		} else {
118 			host.h_length = n;
119 			getclass = class;
120 			host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC;
121 			if (!iquery) {
122 				host.h_name = bp;
123 				bp += strlen(bp) + 1;
124 			}
125 		}
126 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
127 			if (_res.options & RES_DEBUG)
128 				printf("size (%d) too big\n", n);
129 			break;
130 		}
131 		bcopy(cp, *hap++ = bp, n);
132 		bp +=n;
133 		cp += n;
134 		haveanswer++;
135 	}
136 	if (haveanswer) {
137 		*ap = NULL;
138 		*hap = NULL;
139 		return (&host);
140 	} else
141 		return (NULL);
142 }
143 
144 struct hostent *
145 gethostbyname(name)
146 	char *name;
147 {
148 	int n;
149 	char buf[BUFSIZ+1];
150 
151 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
152 		buf, sizeof(buf));
153 	if (n < 0) {
154 		if (_res.options & RES_DEBUG)
155 			printf("res_mkquery failed\n");
156 		return (NULL);
157 	}
158 	return(getanswer(buf, n, 0));
159 }
160 
161 struct hostent *
162 gethostbyaddr(addr, len, type)
163 	char *addr;
164 	int len, type;
165 {
166 	int n;
167 	char buf[BUFSIZ+1];
168 
169 	if (type != AF_INET)
170 		return (NULL);
171 	n = res_mkquery(IQUERY, (char *)NULL, C_IN, T_A, addr, len, NULL,
172 		buf, sizeof(buf));
173 	if (n < 0) {
174 		if (_res.options & RES_DEBUG)
175 			printf("res_mkquery failed\n");
176 		return (NULL);
177 	}
178 	return(getanswer(buf, n, 1));
179 }
180 
181 
182