xref: /original-bsd/lib/libc/net/gethostnamadr.c (revision 3c8a896f)
1 /*	gethostnamadr.c	4.10	85/03/28	*/
2 
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <netdb.h>
7 #include <stdio.h>
8 #include <nameser.h>
9 #include <resolv.h>
10 
11 #define	MAXALIASES	35
12 
13 static struct hostent host;
14 static char *host_aliases[MAXALIASES];
15 static char hostbuf[BUFSIZ+1];
16 
17 static struct hostent *
18 getanswer(msg, msglen, iquery)
19 	char *msg;
20 	int msglen, iquery;
21 {
22 	register HEADER *hp;
23 	register char *cp;
24 	register int n;
25 	char answer[PACKETSZ];
26 	char *eom, *bp, **ap;
27 	int type, class, ancount, buflen;
28 
29 	n = res_send(msg, msglen, answer, sizeof(answer));
30 	if (n < 0) {
31 		if (_res.options & RES_DEBUG)
32 			printf("res_send failed\n");
33 		return (NULL);
34 	}
35 	eom = answer + n;
36 	/*
37 	 * find first satisfactory answer
38 	 */
39 	hp = (HEADER *) answer;
40 	ancount = ntohs(hp->ancount);
41 	if (hp->rcode != NOERROR || ancount == 0) {
42 		if (_res.options & RES_DEBUG)
43 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
44 		return (NULL);
45 	}
46 	bp = hostbuf;
47 	buflen = sizeof(hostbuf);
48 	ap = host_aliases;
49 	cp = answer + sizeof(HEADER);
50 	if (hp->qdcount) {
51 		if (iquery) {
52 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
53 				return (NULL);
54 			cp += n + QFIXEDSZ;
55 			host.h_name = bp;
56 			n = strlen(bp) + 1;
57 			bp += n;
58 			buflen -= n;
59 		} else
60 			cp += dn_skip(cp) + QFIXEDSZ;
61 	} else if (iquery)
62 		return (NULL);
63 	while (--ancount >= 0 && cp < eom) {
64 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
65 			return (NULL);
66 		cp += n;
67 		type = getshort(cp);
68  		cp += sizeof(u_short);
69 		class = getshort(cp);
70  		cp += sizeof(u_short) + sizeof(u_long);
71 		n = getshort(cp);
72 		cp += sizeof(u_short);
73 		if (type == T_CNAME) {
74 			cp += n;
75 			if (ap >= &host_aliases[MAXALIASES-1])
76 				continue;
77 			*ap++ = bp;
78 			n = strlen(bp) + 1;
79 			bp += n;
80 			buflen -= n;
81 			continue;
82 		}
83 		if (type != T_A || n != 4) {
84 			if (_res.options & RES_DEBUG)
85 				printf("unexpected answer type %d, size %d\n",
86 					type, n);
87 			continue;
88 		}
89 		if (!iquery) {
90 			host.h_name = bp;
91 			bp += strlen(bp) + 1;
92 		}
93 		*ap = NULL;
94 		host.h_aliases = host_aliases;
95 		host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
96 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
97 			if (_res.options & RES_DEBUG)
98 				printf("size (%d) too big\n", n);
99 			return (NULL);
100 		}
101 		bcopy(cp, host.h_addr = bp, host.h_length = n);
102 		return (&host);
103 	}
104 	return (NULL);
105 }
106 
107 struct hostent *
108 gethostbyname(name)
109 	char *name;
110 {
111 	int n;
112 
113 	n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL,
114 		hostbuf, sizeof(hostbuf));
115 	if (n < 0) {
116 		if (_res.options & RES_DEBUG)
117 			printf("res_mkquery failed\n");
118 		return (NULL);
119 	}
120 	return (getanswer(hostbuf, n, 0));
121 }
122 
123 struct hostent *
124 gethostbyaddr(addr, len, type)
125 	char *addr;
126 	int len, type;
127 {
128 	int n;
129 
130 	if (type != AF_INET)
131 		return (NULL);
132 	n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL,
133 		hostbuf, sizeof(hostbuf));
134 	if (n < 0) {
135 		if (_res.options & RES_DEBUG)
136 			printf("res_mkquery failed\n");
137 		return (NULL);
138 	}
139 	return (getanswer(hostbuf, n, 1));
140 }
141