Commit | Line | Data |
---|---|---|
8ea4199d | 1 | /* |
412fa3e3 | 2 | * Copyright (c) 1983 Regents of the University of California. |
8ea4199d DF |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
22352302 | 8 | static char sccsid[] = "@(#)gethostnamadr.c 5.6 (Berkeley) %G%"; |
8ea4199d | 9 | #endif not lint |
b423e985 | 10 | |
f784656b RC |
11 | #include <sys/types.h> |
12 | #include <sys/socket.h> | |
13 | #include <netinet/in.h> | |
337257b2 | 14 | #include <netdb.h> |
f784656b | 15 | #include <stdio.h> |
aa678832 JB |
16 | #include <arpa/nameser.h> |
17 | #include <arpa/resolv.h> | |
337257b2 RC |
18 | |
19 | #define MAXALIASES 35 | |
412fa3e3 | 20 | #define MAXADDRS 35 |
337257b2 | 21 | |
412fa3e3 JB |
22 | static char *h_addr_ptrs[MAXADDRS + 1]; |
23 | ||
24 | static struct hostent host; | |
337257b2 | 25 | static char *host_aliases[MAXALIASES]; |
291cd39e | 26 | static char hostbuf[BUFSIZ+1]; |
3a87f357 | 27 | |
6f4c7128 | 28 | |
337257b2 | 29 | static struct hostent * |
f784656b RC |
30 | getanswer(msg, msglen, iquery) |
31 | char *msg; | |
32 | int msglen, iquery; | |
337257b2 | 33 | { |
f784656b RC |
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; | |
412fa3e3 JB |
40 | int haveanswer, getclass; |
41 | char **hap; | |
337257b2 | 42 | |
31f0ead0 | 43 | n = res_send(msg, msglen, answer, sizeof(answer)); |
f784656b RC |
44 | if (n < 0) { |
45 | if (_res.options & RES_DEBUG) | |
31f0ead0 | 46 | printf("res_send failed\n"); |
f784656b RC |
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); | |
337257b2 | 59 | } |
f784656b RC |
60 | bp = hostbuf; |
61 | buflen = sizeof(hostbuf); | |
f784656b RC |
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); | |
412fa3e3 JB |
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; | |
f784656b RC |
81 | while (--ancount >= 0 && cp < eom) { |
82 | if ((n = dn_expand(answer, cp, bp, buflen)) < 0) | |
412fa3e3 | 83 | break; |
f784656b RC |
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 | } | |
412fa3e3 | 101 | if (type != T_A) { |
f784656b RC |
102 | if (_res.options & RES_DEBUG) |
103 | printf("unexpected answer type %d, size %d\n", | |
104 | type, n); | |
412fa3e3 | 105 | cp += n; |
f784656b RC |
106 | continue; |
107 | } | |
412fa3e3 JB |
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 | } | |
f784656b | 125 | } |
f784656b RC |
126 | if (bp + n >= &hostbuf[sizeof(hostbuf)]) { |
127 | if (_res.options & RES_DEBUG) | |
128 | printf("size (%d) too big\n", n); | |
412fa3e3 | 129 | break; |
f784656b | 130 | } |
412fa3e3 JB |
131 | bcopy(cp, *hap++ = bp, n); |
132 | bp +=n; | |
133 | cp += n; | |
134 | haveanswer++; | |
f784656b | 135 | } |
412fa3e3 JB |
136 | if (haveanswer) { |
137 | *ap = NULL; | |
138 | *hap = NULL; | |
139 | return (&host); | |
140 | } else | |
141 | return (NULL); | |
337257b2 RC |
142 | } |
143 | ||
144 | struct hostent * | |
f784656b RC |
145 | gethostbyname(name) |
146 | char *name; | |
337257b2 | 147 | { |
f784656b | 148 | int n; |
412fa3e3 | 149 | char buf[BUFSIZ+1]; |
337257b2 | 150 | |
412fa3e3 | 151 | n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL, |
22352302 | 152 | buf, sizeof(buf)); |
f784656b RC |
153 | if (n < 0) { |
154 | if (_res.options & RES_DEBUG) | |
31f0ead0 | 155 | printf("res_mkquery failed\n"); |
f784656b | 156 | return (NULL); |
3a87f357 | 157 | } |
412fa3e3 | 158 | return(getanswer(buf, n, 0)); |
337257b2 RC |
159 | } |
160 | ||
161 | struct hostent * | |
f784656b | 162 | gethostbyaddr(addr, len, type) |
337257b2 | 163 | char *addr; |
f784656b | 164 | int len, type; |
337257b2 | 165 | { |
f784656b | 166 | int n; |
412fa3e3 | 167 | char buf[BUFSIZ+1]; |
337257b2 | 168 | |
f784656b RC |
169 | if (type != AF_INET) |
170 | return (NULL); | |
412fa3e3 | 171 | n = res_mkquery(IQUERY, (char *)NULL, C_IN, T_A, addr, len, NULL, |
22352302 | 172 | buf, sizeof(buf)); |
f784656b RC |
173 | if (n < 0) { |
174 | if (_res.options & RES_DEBUG) | |
31f0ead0 | 175 | printf("res_mkquery failed\n"); |
f784656b | 176 | return (NULL); |
f268b9fa | 177 | } |
412fa3e3 | 178 | return(getanswer(buf, n, 1)); |
337257b2 | 179 | } |
6f4c7128 | 180 | |
6f4c7128 | 181 |