xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 24510)
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 #ifndef lint
8 static char sccsid[] = "@(#)gethostnamadr.c	5.4 (Berkeley) 09/03/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 
21 #define XX 2
22 static char h_addr_buf[sizeof(struct in_addr) * XX];
23 static char *h_addr_ptr[XX] = {
24 	&h_addr_buf[0],
25 	&h_addr_buf[sizeof(struct in_addr)]
26 };
27 static struct hostent host = {
28 	NULL,		/* official name of host */
29 	NULL,		/* alias list */
30 	0,		/* host address type */
31 	0,		/* length of address */
32 	h_addr_ptr	/* list of addresses from name server */
33 };
34 static char *host_aliases[MAXALIASES];
35 static char hostbuf[BUFSIZ+1];
36 
37 
38 static struct hostent *
39 getanswer(msg, msglen, iquery)
40 	char *msg;
41 	int msglen, iquery;
42 {
43 	register HEADER *hp;
44 	register char *cp;
45 	register int n;
46 	char answer[PACKETSZ];
47 	char *eom, *bp, **ap;
48 	int type, class, ancount, buflen;
49 
50 	n = res_send(msg, msglen, answer, sizeof(answer));
51 	if (n < 0) {
52 		if (_res.options & RES_DEBUG)
53 			printf("res_send failed\n");
54 		return (NULL);
55 	}
56 	eom = answer + n;
57 	/*
58 	 * find first satisfactory answer
59 	 */
60 	hp = (HEADER *) answer;
61 	ancount = ntohs(hp->ancount);
62 	if (hp->rcode != NOERROR || ancount == 0) {
63 		if (_res.options & RES_DEBUG)
64 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
65 		return (NULL);
66 	}
67 	bp = hostbuf;
68 	buflen = sizeof(hostbuf);
69 	ap = host_aliases;
70 	cp = answer + sizeof(HEADER);
71 	if (hp->qdcount) {
72 		if (iquery) {
73 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
74 				return (NULL);
75 			cp += n + QFIXEDSZ;
76 			host.h_name = bp;
77 			n = strlen(bp) + 1;
78 			bp += n;
79 			buflen -= n;
80 		} else
81 			cp += dn_skip(cp) + QFIXEDSZ;
82 	} else if (iquery)
83 		return (NULL);
84 	while (--ancount >= 0 && cp < eom) {
85 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
86 			return (NULL);
87 		cp += n;
88 		type = getshort(cp);
89  		cp += sizeof(u_short);
90 		class = getshort(cp);
91  		cp += sizeof(u_short) + sizeof(u_long);
92 		n = getshort(cp);
93 		cp += sizeof(u_short);
94 		if (type == T_CNAME) {
95 			cp += n;
96 			if (ap >= &host_aliases[MAXALIASES-1])
97 				continue;
98 			*ap++ = bp;
99 			n = strlen(bp) + 1;
100 			bp += n;
101 			buflen -= n;
102 			continue;
103 		}
104 		if (type != T_A || n != 4) {
105 			if (_res.options & RES_DEBUG)
106 				printf("unexpected answer type %d, size %d\n",
107 					type, n);
108 			continue;
109 		}
110 		if (!iquery) {
111 			host.h_name = bp;
112 			bp += strlen(bp) + 1;
113 		}
114 		*ap = NULL;
115 		host.h_aliases = host_aliases;
116 		host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
117 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
118 			if (_res.options & RES_DEBUG)
119 				printf("size (%d) too big\n", n);
120 			return (NULL);
121 		}
122 		bcopy(cp, host.h_addr = bp, host.h_length = n);
123 		return (&host);
124 	}
125 	return (NULL);
126 }
127 
128 struct hostent *
129 gethostbyname(name)
130 	char *name;
131 {
132 	int n;
133 
134 	n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL,
135 		hostbuf, sizeof(hostbuf));
136 	if (n < 0) {
137 		if (_res.options & RES_DEBUG)
138 			printf("res_mkquery failed\n");
139 		return (NULL);
140 	}
141 	return(getanswer(hostbuf, n, 0));
142 }
143 
144 struct hostent *
145 gethostbyaddr(addr, len, type)
146 	char *addr;
147 	int len, type;
148 {
149 	int n;
150 
151 	if (type != AF_INET)
152 		return (NULL);
153 	n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL,
154 		hostbuf, sizeof(hostbuf));
155 	if (n < 0) {
156 		if (_res.options & RES_DEBUG)
157 			printf("res_mkquery failed\n");
158 		return (NULL);
159 	}
160 	return (getanswer(hostbuf, n, 1));
161 }
162 
163 
164