Deleted Added
full compact
yp_dnslookup.c (17925) yp_dnslookup.c (20818)
1/*
2 * Copyright (c) 1995
3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
1/*
2 * Copyright (c) 1995
3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: yp_dnslookup.c,v 1.2 1996/05/31 16:01:49 wpaul Exp $
32 * $Id: yp_dnslookup.c,v 1.5 1996/12/22 15:45:33 wpaul Exp $
33 */
34
35/*
36 * Do standard and reverse DNS lookups using the resolver library.
37 * Take care of all the dirty work here so the main program only has to
38 * pass us a pointer to an array of characters.
39 *
40 * We have to use direct resolver calls here otherwise the YP server
41 * could end up looping by calling itself over and over again until
42 * it disappeared up its own belly button.
43 */
44
33 */
34
35/*
36 * Do standard and reverse DNS lookups using the resolver library.
37 * Take care of all the dirty work here so the main program only has to
38 * pass us a pointer to an array of characters.
39 *
40 * We have to use direct resolver calls here otherwise the YP server
41 * could end up looping by calling itself over and over again until
42 * it disappeared up its own belly button.
43 */
44
45#include <sys/types.h>
46#include <stdio.h>
47#include <string.h>
48#include <stdlib.h>
49#include <sys/param.h>
45#include <sys/param.h>
50#include <netdb.h>
51#include <netinet/in.h>
52#include <sys/socket.h>
46#include <sys/socket.h>
47#include <sys/time.h>
48#include <sys/fcntl.h>
49#include <sys/queue.h>
50#include <netinet/in.h>
53#include <arpa/inet.h>
51#include <arpa/inet.h>
52#include <arpa/nameser.h>
53
54#include <stdio.h>
55#include <ctype.h>
56#include <resolv.h>
57#include <netdb.h>
58#include <unistd.h>
59#include <stdlib.h>
60#include <string.h>
61#include <errno.h>
62#include <err.h>
63
64#include <rpcsvc/yp.h>
54#include "yp_extern.h"
55
56#ifndef lint
65#include "yp_extern.h"
66
67#ifndef lint
57static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.2 1996/05/31 16:01:49 wpaul Exp $";
68static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.5 1996/12/22 15:45:33 wpaul Exp $";
58#endif
59
60static char *parse(hp)
61 struct hostent *hp;
62{
63 static char result[MAXHOSTNAMELEN * 2];
64 int len,i;
65 struct in_addr addr;
66
69#endif
70
71static char *parse(hp)
72 struct hostent *hp;
73{
74 static char result[MAXHOSTNAMELEN * 2];
75 int len,i;
76 struct in_addr addr;
77
78 if (hp == NULL)
79 return(NULL);
80
67 len = 16 + strlen(hp->h_name);
68 for (i = 0; hp->h_aliases[i]; i++)
69 len += strlen(hp->h_aliases[i]) + 1;
70
71 bzero(result, sizeof(result));
72
73 bcopy(hp->h_addr, &addr, sizeof(struct in_addr));
74 snprintf(result, sizeof(result), "%s %s", inet_ntoa(addr), hp->h_name);
75
76 for (i = 0; hp->h_aliases[i]; i++) {
77 strcat(result, " ");
78 strcat(result, hp->h_aliases[i]);
79 }
80
81 return ((char *)&result);
82}
83
81 len = 16 + strlen(hp->h_name);
82 for (i = 0; hp->h_aliases[i]; i++)
83 len += strlen(hp->h_aliases[i]) + 1;
84
85 bzero(result, sizeof(result));
86
87 bcopy(hp->h_addr, &addr, sizeof(struct in_addr));
88 snprintf(result, sizeof(result), "%s %s", inet_ntoa(addr), hp->h_name);
89
90 for (i = 0; hp->h_aliases[i]; i++) {
91 strcat(result, " ");
92 strcat(result, hp->h_aliases[i]);
93 }
94
95 return ((char *)&result);
96}
97
84char *yp_dnsname(address)
85 char *address;
98#define MAXPACKET 1024
99#define DEF_TTL 50
100
101extern struct hostent *__dns_getanswer __P((char *, int, char *, int));
102
103static CIRCLEQ_HEAD(dns_qhead, circleq_dnsentry) qhead;
104
105struct circleq_dnsentry {
106 SVCXPRT *xprt;
107 unsigned long xid;
108 struct sockaddr_in client_addr;
109 unsigned long id;
110 unsigned long ttl;
111 unsigned long sent;
112 unsigned long type;
113 char **domain;
114 char *name;
115 struct in_addr addr;
116 CIRCLEQ_ENTRY(circleq_dnsentry) links;
117};
118
119static int pending = 0;
120
121int yp_init_resolver()
86{
122{
87 struct hostent *hp;
123 CIRCLEQ_INIT(&qhead);
124 if (!(_res.options & RES_INIT) && res_init() == -1) {
125 yp_error("res_init failed");
126 return(1);
127 }
128 if ((resfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
129 yp_error("couldn't create socket");
130 return(1);
131 }
132 if (fcntl(resfd, F_SETFL, O_NONBLOCK) == -1) {
133 yp_error("couldn't make resolver socket non-blocking");
134 return(1);
135 }
136 return(0);
137}
88
138
89 if (strchr(address, '@'))
90 return (NULL);
91 if ((hp = (struct hostent *)_gethostbydnsname(address, AF_INET)) == NULL)
92 return (NULL);
139int yp_dnsq_pending()
140{
141 return(pending);
142}
93
143
94 return(parse(hp));
144static struct circleq_dnsentry *yp_malloc_dnsent()
145{
146 register struct circleq_dnsentry *q;
147
148 q = (struct circleq_dnsentry *)malloc(sizeof(struct circleq_dnsentry));
149
150 if (q == NULL) {
151 yp_error("failed to malloc() circleq dns entry: %s",
152 strerror(errno));
153 return(NULL);
154 }
155
156 return(q);
95}
96
157}
158
97char *yp_dnsaddr(address)
98 const char *address;
159/*
160 * Transmit a query.
161 */
162static unsigned long yp_send_dns_query(name, type)
163 char *name;
164 int type;
99{
165{
100 struct hostent *hp;
101 struct in_addr addr;
166 char buf[MAXPACKET];
167 int n;
168 HEADER *hptr;
169 int ns;
170 int rval;
171 unsigned long id;
102
172
103 if (strchr(address, '@'))
104 return (NULL);
105 if (!inet_aton(address, &addr))
106 return (NULL);
107 if ((hp = (struct hostent *)_gethostbydnsaddr((const char *)&addr,
108 sizeof(unsigned long), AF_INET)) == NULL)
109 return (NULL);
173 bzero(buf, sizeof(buf));
110
174
111 return(parse(hp));
175 n = res_mkquery(QUERY,name,C_IN,type,NULL,0,NULL,buf,sizeof(buf));
176
177 if (n <= 0) {
178 yp_error("res_mkquery failed");
179 return(0);
180 }
181
182 hptr = (HEADER *)&buf;
183 id = ntohs(hptr->id);
184
185 for (ns = 0; ns < _res.nscount; ns++) {
186 rval = sendto(resfd, buf, n, 0,
187 (struct sockaddr *)&_res.nsaddr_list[ns],
188 sizeof(struct sockaddr));
189 if (rval == -1) {
190 yp_error("sendto failed");
191 return(0);
192 }
193 }
194
195 return(id);
112}
196}
197
198static struct circleq_dnsentry *yp_find_dnsqent(id)
199 unsigned long id;
200{
201 register struct circleq_dnsentry *q;
202
203 for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) {
204 if (q->id == id)
205 return(q);
206 }
207 return (NULL);
208}
209
210static void yp_send_dns_reply(q, buf)
211 struct circleq_dnsentry *q;
212 char *buf;
213{
214 ypresp_val result;
215 unsigned long xid;
216 struct sockaddr_in client_addr;
217
218 bzero((char *)&result, sizeof(result));
219
220 if (buf == NULL)
221 result.stat = YP_NOKEY;
222 else {
223 result.val.valdat_len = strlen(buf);
224 result.val.valdat_val = buf;
225 result.stat = YP_TRUE;
226 }
227
228 if (debug)
229 yp_error("Sending dns reply to %s (%lu)",
230 inet_ntoa(q->client_addr.sin_addr),
231 q->id);
232
233 /*
234 * XXX This is disgusting. There's basically one transport
235 * handle for UDP, but we're holding off on replying to a
236 * client until we're ready, by which time we may have received
237 * several other queries from other clients with different
238 * transaction IDs. So to make the delayed response thing work,
239 * we have to save the transaction ID and client address of
240 * each request, then jam them into the transport handle when
241 * we're ready to send a reply. Then after we've send the reply,
242 * we put the old transaction ID and remote address back the
243 * way we found 'em. This is _INCREDIBLY_ non-portable; it's
244 * not even supported by the RPC library.
245 */
246 xid = svcudp_set_xid(q->xprt, q->xid);
247 client_addr = q->xprt->xp_raddr;
248 q->xprt->xp_raddr = q->client_addr;
249 if (!svc_sendreply(q->xprt, xdr_ypresp_val, (char *)&result))
250 yp_error("svc_sendreply failed");
251 svcudp_set_xid(q->xprt, xid);
252 q->xprt->xp_raddr = client_addr;
253 return;
254}
255
256void yp_prune_dnsq()
257{
258 register struct circleq_dnsentry *q;
259
260 for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) {
261 q->ttl--;
262 if (!q->ttl) {
263 CIRCLEQ_REMOVE(&qhead, q, links);
264 free(q->name);
265 free(q);
266 pending--;
267 }
268 }
269
270 if (pending < 0)
271 pending = 0;
272
273 return;
274}
275
276void yp_run_dnsq()
277{
278 register struct circleq_dnsentry *q;
279 char buf[sizeof(HEADER) + MAXPACKET];
280 struct sockaddr_in sin;
281 int rval;
282 int len;
283 HEADER *hptr;
284 struct hostent *hent;
285
286 if (debug)
287 yp_error("Running dns queue");
288
289 bzero(buf, sizeof(buf));
290
291 len = sizeof(struct sockaddr_in);
292 rval = recvfrom(resfd, buf, sizeof(buf), 0,
293 (struct sockaddr *)&sin, &len);
294
295 if (rval == -1) {
296 yp_error("recvfrom failed: %s", strerror(errno));
297 return;
298 }
299
300 hptr = (HEADER *)&buf;
301 if ((q = yp_find_dnsqent(ntohs(hptr->id))) == NULL) {
302 /* bogus id -- ignore */
303 return;
304 }
305
306 if (debug)
307 yp_error("Got dns reply from %s", inet_ntoa(sin.sin_addr));
308
309 hent = __dns_getanswer(buf, rval, q->name, q->type);
310
311 if (hent == NULL) {
312 char retrybuf[MAXHOSTNAMELEN];
313
314 if (q->domain && *q->domain) {
315 snprintf(retrybuf, sizeof(retrybuf), "%s.%s",
316 q->name, *q->domain);
317 if (debug)
318 yp_error("Retrying with: %s", retrybuf);
319 q->id = yp_send_dns_query(retrybuf, q->type);
320 q->ttl = DEF_TTL;
321 q->domain++;
322 return;
323 }
324 }
325
326 if (q->type == T_PTR) {
327 hent->h_addr = (char *)&q->addr.s_addr;
328 hent->h_length = sizeof(struct in_addr);
329 }
330 yp_send_dns_reply(q, parse(hent));
331
332 pending--;
333 CIRCLEQ_REMOVE(&qhead, q, links);
334 free(q->name);
335 free(q);
336
337 yp_prune_dnsq();
338
339 return;
340}
341
342ypstat yp_async_lookup_name(xprt, name)
343 SVCXPRT *xprt;
344 char *name;
345{
346 register struct circleq_dnsentry *q;
347
348 if ((q = yp_malloc_dnsent()) == NULL)
349 return(YP_YPERR);
350
351 q->type = T_A;
352 q->ttl = DEF_TTL;
353 q->sent = 1;
354 q->xprt = xprt;
355 q->xid = svcudp_get_xid(xprt);
356 q->client_addr = xprt->xp_raddr;
357 if (!strchr(name, '.'))
358 q->domain = _res.dnsrch;
359 else
360 q->domain = NULL;
361 q->id = yp_send_dns_query(name, q->type);
362
363 if (q->id == 0) {
364 yp_error("DNS query failed");
365 free(q);
366 return(YP_YPERR);
367 }
368
369 q->name = strdup(name);
370 CIRCLEQ_INSERT_HEAD(&qhead, q, links);
371 pending++;
372
373 if (debug)
374 yp_error("Queueing async DNS name lookup (%d)", q->id);
375
376 return(YP_TRUE);
377}
378
379ypstat yp_async_lookup_addr(xprt, addr)
380 SVCXPRT *xprt;
381 char *addr;
382{
383 register struct circleq_dnsentry *q;
384 char buf[MAXHOSTNAMELEN];
385 int a, b, c, d;
386
387 if ((q = yp_malloc_dnsent()) == NULL)
388 return(YP_YPERR);
389
390 if (sscanf(addr, "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
391 return(YP_NOKEY);
392
393 snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa",
394 d, c, b, a, addr);
395
396 if (debug)
397 yp_error("DNS address is: %s", buf);
398
399 q->type = T_PTR;
400 q->ttl = DEF_TTL;
401 q->sent = 1;
402 q->xprt = xprt;
403 q->domain = NULL;
404 q->xid = svcudp_get_xid(xprt);
405 q->client_addr = xprt->xp_raddr;
406 q->id = yp_send_dns_query(buf, q->type);
407
408 if (q->id == 0) {
409 yp_error("DNS query failed");
410 free(q);
411 return(YP_YPERR);
412 }
413
414 inet_aton(addr, &q->addr);
415 q->name = strdup(buf);
416 CIRCLEQ_INSERT_HEAD(&qhead, q, links);
417 pending++;
418
419 if (debug)
420 yp_error("Queueing async DNS address lookup (%d)", q->id);
421
422 return(YP_TRUE);
423}