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