Annotation of embedaddon/mtr/ui/dns.c, revision 1.1.1.2
1.1 misho 1: /*
2: mtr -- a network diagnostic tool
3: Copyright (C) 1997,1998 Matt Kimball
4:
5: This program is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License version 2 as
7: published by the Free Software Foundation.
8:
9: This program is distributed in the hope that it will be useful,
10: but WITHOUT ANY WARRANTY; without even the implied warranty of
11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: GNU General Public License for more details.
13:
1.1.1.2 ! misho 14: You should have received a copy of the GNU General Public License along
! 15: with this program; if not, write to the Free Software Foundation, Inc.,
! 16: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.1 misho 17: */
18:
19: /*
20: Non-blocking DNS portion --
21: Copyright (C) 1998 by Simon Kirby <sim@neato.org>
22: Released under GPL, as above.
23: */
24:
25: #include "config.h"
26:
27: #ifdef HAVE_ERROR_H
28: #include <error.h>
29: #else
30: #include "portability/error.h"
31: #endif
32: #include <errno.h>
33: #include <unistd.h>
34: #include <fcntl.h>
35: #include <string.h>
36: #include <stdio.h>
37: #include <stdlib.h>
38: #include <signal.h>
39:
40: #include "mtr.h"
41: #include "dns.h"
42: #include "net.h"
43: #include "utils.h"
1.1.1.2 ! misho 44: #include "packet/sockaddr.h"
1.1 misho 45:
46: struct dns_results {
47: ip_t ip;
48: char *name;
49: struct dns_results *next;
50: };
51:
52: static struct dns_results *results;
53:
54: char *strlongip(
55: struct mtr_ctl *ctl,
56: ip_t * ip)
57: {
58: #ifdef ENABLE_IPV6
59: static char addrstr[INET6_ADDRSTRLEN];
60:
61: return (char *) inet_ntop(ctl->af, ip, addrstr, sizeof addrstr);
62: #else
63: return inet_ntoa(*ip);
64: #endif
65: }
66:
67:
68: #ifdef ENABLE_IPV6
69: #define UNUSED_IF_NO_IPV6 /* empty */
70: #else
71: #define UNUSED_IF_NO_IPV6 ATTRIBUTE_UNUSED
72: #endif
73:
74: static int todns[2], fromdns[2];
75: static FILE *fromdnsfp;
76:
77: static int longipstr(
78: char *s,
79: ip_t * dst,
80: int family UNUSED_IF_NO_IPV6)
81: {
82: #ifdef ENABLE_IPV6
83: return inet_pton(family, s, dst);
84: #else
85: return inet_aton(s, dst);
86: #endif
87: }
88:
89:
90: struct hostent *dns_forward(
91: const char *name)
92: {
93: struct hostent *host;
94:
95: if ((host = gethostbyname(name)))
96: return host;
97: else
98: return NULL;
99: }
100:
101:
102: static struct dns_results *findip(
103: struct mtr_ctl *ctl,
104: ip_t * ip)
105: {
106: struct dns_results *t;
107:
108: for (t = results; t; t = t->next) {
1.1.1.2 ! misho 109: if (addrcmp(ip, &t->ip, ctl->af) == 0)
1.1 misho 110: return t;
111: }
112:
113: return NULL;
114: }
115:
116: static void set_sockaddr_ip(
117: struct mtr_ctl *ctl,
118: struct sockaddr_storage *sa,
119: ip_t * ip)
120: {
121: memset(sa, 0, sizeof(struct sockaddr_storage));
1.1.1.2 ! misho 122: sa->ss_family = ctl->af;
! 123: memcpy(sockaddr_addr_offset(sa), ip, sockaddr_addr_size(sa));
1.1 misho 124: }
125:
126: void dns_open(
127: struct mtr_ctl *ctl)
128: {
129: int pid;
130:
131: if (pipe(todns) < 0) {
132: error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
133: }
134:
135: if (pipe(fromdns) < 0) {
136: error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
137: }
138: fflush(stdout);
139: pid = fork();
140: if (pid < 0) {
141: error(EXIT_FAILURE, errno, "can't fork for DNS process");
142: }
143: if (pid == 0) {
144: char buf[2048];
145: int i;
146: FILE *infp;
147:
148: /* Automatically reap children. */
149: if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
150: error(EXIT_FAILURE, errno, "signal");
151: }
152:
1.1.1.2 ! misho 153: /* Close all unnecessary FDs.
1.1 misho 154: for debugging and error reporting, keep std-in/out/err. */
155: for (i = 3; i < fromdns[1]; i++) {
156: if (i == todns[0])
157: continue;
158: if (i == fromdns[1])
159: continue;
160: close(i);
161: }
162: infp = fdopen(todns[0], "r");
163:
164: while (fgets(buf, sizeof(buf), infp)) {
165: ip_t host;
166: struct sockaddr_storage sa;
167: socklen_t salen;
168: char hostname[NI_MAXHOST];
169: char result[INET6_ADDRSTRLEN + NI_MAXHOST + 2];
170:
171: if (!fork()) {
172: int rv;
173:
174: buf[strlen(buf) - 1] = 0; /* chomp newline. */
175:
176: longipstr(buf, &host, ctl->af);
177: set_sockaddr_ip(ctl, &sa, &host);
178: salen = (ctl->af == AF_INET) ? sizeof(struct sockaddr_in) :
179: sizeof(struct sockaddr_in6);
180:
181: rv = getnameinfo((struct sockaddr *) &sa, salen,
182: hostname, sizeof(hostname), NULL, 0, 0);
183: if (rv == 0) {
184: snprintf(result, sizeof(result),
185: "%s %s\n", strlongip(ctl, &host), hostname);
186:
187: rv = write(fromdns[1], result, strlen(result));
188: if (rv < 0)
189: error(0, errno, "write DNS lookup result");
190: }
191:
192: exit(EXIT_SUCCESS);
193: }
194: }
195: exit(EXIT_SUCCESS);
196: } else {
197: int flags;
198:
199: /* the parent. */
200: close(todns[0]); /* close the pipe ends we don't need. */
201: close(fromdns[1]);
202: fromdnsfp = fdopen(fromdns[0], "r");
203: flags = fcntl(fromdns[0], F_GETFL, 0);
204: flags |= O_NONBLOCK;
205: fcntl(fromdns[0], F_SETFL, flags);
206: }
207: }
208:
209: int dns_waitfd(
210: void)
211: {
212: return fromdns[0];
213: }
214:
215:
216: void dns_ack(
217: struct mtr_ctl *ctl)
218: {
219: char buf[2048], host[NI_MAXHOST], name[NI_MAXHOST];
220: ip_t hostip;
221: struct dns_results *r;
222:
223: while (fgets(buf, sizeof(buf), fromdnsfp)) {
224: sscanf(buf, "%s %s", host, name);
225:
226: longipstr(host, &hostip, ctl->af);
227: r = findip(ctl, &hostip);
228: if (r)
229: r->name = xstrdup(name);
230: else
231: error(0, 0, "dns_ack: Couldn't find host %s", host);
232: }
233: }
234:
235:
236:
237: #ifdef ENABLE_IPV6
238:
239: int dns_waitfd6(
240: void)
241: {
242: return -1;
243: }
244:
245: void dns_ack6(
246: void)
247: {
248: return;
249: }
250:
251: #endif
252:
253:
254: char *dns_lookup2(
255: struct mtr_ctl *ctl,
256: ip_t * ip)
257: {
258: struct dns_results *r;
259: char buf[INET6_ADDRSTRLEN + 1];
260: int rv;
261:
262: r = findip(ctl, ip);
263: if (r) {
264: /* we've got a result. */
265: if (r->name)
266: return r->name;
267: } else {
268: r = xmalloc(sizeof(struct dns_results));
269: memcpy(&r->ip, ip, sizeof(r->ip));
270: r->name = NULL;
271: r->next = results;
272: results = r;
273: snprintf(buf, sizeof(buf), "%s\n", strlongip(ctl, ip));
274: rv = write(todns[1], buf, strlen(buf));
275: if (rv < 0)
276: error(0, errno, "couldn't write to resolver process");
277: }
1.1.1.2 ! misho 278: return NULL;
1.1 misho 279: }
280:
281:
282: char *dns_lookup(
283: struct mtr_ctl *ctl,
284: ip_t * ip)
285: {
286: char *t;
287:
288: if (!ctl->dns || !ctl->use_dns)
289: return NULL;
290: t = dns_lookup2(ctl, ip);
1.1.1.2 ! misho 291: return t ? t : strlongip(ctl, ip);
1.1 misho 292: }
293:
294: /* XXX check if necessary/exported. */
295:
296: /* Resolve an IP address to a hostname. */
297: struct hostent *addr2host(
298: const char *addr,
299: int family)
300: {
301: int len = 0;
302: switch (family) {
303: case AF_INET:
304: len = sizeof(struct in_addr);
305: break;
306: #ifdef ENABLE_IPV6
307: case AF_INET6:
308: len = sizeof(struct in6_addr);
309: break;
310: #endif
311: }
312: return gethostbyaddr(addr, len, family);
313: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>