xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 18505)
1 /*	gethostnamadr.c	4.9	85/03/25	*/
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 = sendquery(msg, msglen, answer, sizeof(answer));
30 	if (n < 0) {
31 		if (_res.options & RES_DEBUG)
32 			printf("sendquery 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 = mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL, hostbuf, sizeof(hostbuf));
114 	if (n < 0) {
115 		if (_res.options & RES_DEBUG)
116 			printf("mkquery failed\n");
117 		return (NULL);
118 	}
119 	return (getanswer(hostbuf, n, 0));
120 }
121 
122 struct hostent *
123 gethostbyaddr(addr, len, type)
124 	char *addr;
125 	int len, type;
126 {
127 	int n;
128 
129 	if (type != AF_INET)
130 		return (NULL);
131 	n = mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL, hostbuf, sizeof(hostbuf));
132 	if (n < 0) {
133 		if (_res.options & RES_DEBUG)
134 			printf("mkquery failed\n");
135 		return (NULL);
136 	}
137 	return (getanswer(hostbuf, n, 1));
138 }
139