Annotation of embedaddon/mtr/ui/dns.c, revision 1.1
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:
! 14: You should have received a copy of the GNU General Public License
! 15: along with this program; if not, write to the Free Software
! 16: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
! 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"
! 44:
! 45: struct dns_results {
! 46: ip_t ip;
! 47: char *name;
! 48: struct dns_results *next;
! 49: };
! 50:
! 51: static struct dns_results *results;
! 52:
! 53: char *strlongip(
! 54: struct mtr_ctl *ctl,
! 55: ip_t * ip)
! 56: {
! 57: #ifdef ENABLE_IPV6
! 58: static char addrstr[INET6_ADDRSTRLEN];
! 59:
! 60: return (char *) inet_ntop(ctl->af, ip, addrstr, sizeof addrstr);
! 61: #else
! 62: return inet_ntoa(*ip);
! 63: #endif
! 64: }
! 65:
! 66:
! 67: #ifdef ENABLE_IPV6
! 68: #define UNUSED_IF_NO_IPV6 /* empty */
! 69: #else
! 70: #define UNUSED_IF_NO_IPV6 ATTRIBUTE_UNUSED
! 71: #endif
! 72:
! 73: static int todns[2], fromdns[2];
! 74: static FILE *fromdnsfp;
! 75:
! 76: static int longipstr(
! 77: char *s,
! 78: ip_t * dst,
! 79: int family UNUSED_IF_NO_IPV6)
! 80: {
! 81: #ifdef ENABLE_IPV6
! 82: return inet_pton(family, s, dst);
! 83: #else
! 84: return inet_aton(s, dst);
! 85: #endif
! 86: }
! 87:
! 88:
! 89: struct hostent *dns_forward(
! 90: const char *name)
! 91: {
! 92: struct hostent *host;
! 93:
! 94: if ((host = gethostbyname(name)))
! 95: return host;
! 96: else
! 97: return NULL;
! 98: }
! 99:
! 100:
! 101: static struct dns_results *findip(
! 102: struct mtr_ctl *ctl,
! 103: ip_t * ip)
! 104: {
! 105: struct dns_results *t;
! 106:
! 107: for (t = results; t; t = t->next) {
! 108: if (addrcmp((void *) ip, (void *) &t->ip, ctl->af) == 0)
! 109: return t;
! 110: }
! 111:
! 112: return NULL;
! 113: }
! 114:
! 115: static void set_sockaddr_ip(
! 116: struct mtr_ctl *ctl,
! 117: struct sockaddr_storage *sa,
! 118: ip_t * ip)
! 119: {
! 120: struct sockaddr_in *sa_in;
! 121: struct sockaddr_in6 *sa_in6;
! 122:
! 123: memset(sa, 0, sizeof(struct sockaddr_storage));
! 124: switch (ctl->af) {
! 125: case AF_INET:
! 126: sa_in = (struct sockaddr_in *) sa;
! 127: sa_in->sin_family = ctl->af;
! 128: addrcpy((void *) &sa_in->sin_addr, (void *) ip, ctl->af);
! 129: break;
! 130: case AF_INET6:
! 131: sa_in6 = (struct sockaddr_in6 *) sa;
! 132: sa_in6->sin6_family = ctl->af;
! 133: addrcpy((void *) &sa_in6->sin6_addr, (void *) ip, ctl->af);
! 134: break;
! 135: }
! 136: }
! 137:
! 138: void dns_open(
! 139: struct mtr_ctl *ctl)
! 140: {
! 141: int pid;
! 142:
! 143: if (pipe(todns) < 0) {
! 144: error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
! 145: }
! 146:
! 147: if (pipe(fromdns) < 0) {
! 148: error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
! 149: }
! 150: fflush(stdout);
! 151: pid = fork();
! 152: if (pid < 0) {
! 153: error(EXIT_FAILURE, errno, "can't fork for DNS process");
! 154: }
! 155: if (pid == 0) {
! 156: char buf[2048];
! 157: int i;
! 158: FILE *infp;
! 159:
! 160: /* Automatically reap children. */
! 161: if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
! 162: error(EXIT_FAILURE, errno, "signal");
! 163: }
! 164:
! 165: /* Close all unneccessary FDs.
! 166: for debugging and error reporting, keep std-in/out/err. */
! 167: for (i = 3; i < fromdns[1]; i++) {
! 168: if (i == todns[0])
! 169: continue;
! 170: if (i == fromdns[1])
! 171: continue;
! 172: close(i);
! 173: }
! 174: infp = fdopen(todns[0], "r");
! 175:
! 176: while (fgets(buf, sizeof(buf), infp)) {
! 177: ip_t host;
! 178: struct sockaddr_storage sa;
! 179: socklen_t salen;
! 180: char hostname[NI_MAXHOST];
! 181: char result[INET6_ADDRSTRLEN + NI_MAXHOST + 2];
! 182:
! 183: if (!fork()) {
! 184: int rv;
! 185:
! 186: buf[strlen(buf) - 1] = 0; /* chomp newline. */
! 187:
! 188: longipstr(buf, &host, ctl->af);
! 189: set_sockaddr_ip(ctl, &sa, &host);
! 190: salen = (ctl->af == AF_INET) ? sizeof(struct sockaddr_in) :
! 191: sizeof(struct sockaddr_in6);
! 192:
! 193: rv = getnameinfo((struct sockaddr *) &sa, salen,
! 194: hostname, sizeof(hostname), NULL, 0, 0);
! 195: if (rv == 0) {
! 196: snprintf(result, sizeof(result),
! 197: "%s %s\n", strlongip(ctl, &host), hostname);
! 198:
! 199: rv = write(fromdns[1], result, strlen(result));
! 200: if (rv < 0)
! 201: error(0, errno, "write DNS lookup result");
! 202: }
! 203:
! 204: exit(EXIT_SUCCESS);
! 205: }
! 206: }
! 207: exit(EXIT_SUCCESS);
! 208: } else {
! 209: int flags;
! 210:
! 211: /* the parent. */
! 212: close(todns[0]); /* close the pipe ends we don't need. */
! 213: close(fromdns[1]);
! 214: fromdnsfp = fdopen(fromdns[0], "r");
! 215: flags = fcntl(fromdns[0], F_GETFL, 0);
! 216: flags |= O_NONBLOCK;
! 217: fcntl(fromdns[0], F_SETFL, flags);
! 218: }
! 219: }
! 220:
! 221: int dns_waitfd(
! 222: void)
! 223: {
! 224: return fromdns[0];
! 225: }
! 226:
! 227:
! 228: void dns_ack(
! 229: struct mtr_ctl *ctl)
! 230: {
! 231: char buf[2048], host[NI_MAXHOST], name[NI_MAXHOST];
! 232: ip_t hostip;
! 233: struct dns_results *r;
! 234:
! 235: while (fgets(buf, sizeof(buf), fromdnsfp)) {
! 236: sscanf(buf, "%s %s", host, name);
! 237:
! 238: longipstr(host, &hostip, ctl->af);
! 239: r = findip(ctl, &hostip);
! 240: if (r)
! 241: r->name = xstrdup(name);
! 242: else
! 243: error(0, 0, "dns_ack: Couldn't find host %s", host);
! 244: }
! 245: }
! 246:
! 247:
! 248:
! 249: #ifdef ENABLE_IPV6
! 250:
! 251: int dns_waitfd6(
! 252: void)
! 253: {
! 254: return -1;
! 255: }
! 256:
! 257: void dns_ack6(
! 258: void)
! 259: {
! 260: return;
! 261: }
! 262:
! 263: #endif
! 264:
! 265:
! 266: char *dns_lookup2(
! 267: struct mtr_ctl *ctl,
! 268: ip_t * ip)
! 269: {
! 270: struct dns_results *r;
! 271: char buf[INET6_ADDRSTRLEN + 1];
! 272: int rv;
! 273:
! 274: r = findip(ctl, ip);
! 275: if (r) {
! 276: /* we've got a result. */
! 277: if (r->name)
! 278: return r->name;
! 279: else
! 280: return strlongip(ctl, ip);
! 281: } else {
! 282: r = xmalloc(sizeof(struct dns_results));
! 283: memcpy(&r->ip, ip, sizeof(r->ip));
! 284: r->name = NULL;
! 285: r->next = results;
! 286: results = r;
! 287: snprintf(buf, sizeof(buf), "%s\n", strlongip(ctl, ip));
! 288: rv = write(todns[1], buf, strlen(buf));
! 289: if (rv < 0)
! 290: error(0, errno, "couldn't write to resolver process");
! 291: }
! 292: return strlongip(ctl, ip);
! 293: }
! 294:
! 295:
! 296: char *dns_lookup(
! 297: struct mtr_ctl *ctl,
! 298: ip_t * ip)
! 299: {
! 300: char *t;
! 301:
! 302: if (!ctl->dns || !ctl->use_dns)
! 303: return NULL;
! 304: t = dns_lookup2(ctl, ip);
! 305: return t;
! 306: }
! 307:
! 308: /* XXX check if necessary/exported. */
! 309:
! 310: /* Resolve an IP address to a hostname. */
! 311: struct hostent *addr2host(
! 312: const char *addr,
! 313: int family)
! 314: {
! 315: int len = 0;
! 316: switch (family) {
! 317: case AF_INET:
! 318: len = sizeof(struct in_addr);
! 319: break;
! 320: #ifdef ENABLE_IPV6
! 321: case AF_INET6:
! 322: len = sizeof(struct in6_addr);
! 323: break;
! 324: #endif
! 325: }
! 326: return gethostbyaddr(addr, len, family);
! 327: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>