File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / ui / dns.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:07:30 2021 UTC (3 years, 3 months ago) by misho
Branches: mtr, MAIN
CVS tags: v0_94, HEAD
mtr 0.94

    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 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.
   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: #include "packet/sockaddr.h"
   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) {
  109:         if (addrcmp(ip, &t->ip, ctl->af) == 0)
  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));
  122:     sa->ss_family = ctl->af;
  123:     memcpy(sockaddr_addr_offset(sa), ip, sockaddr_addr_size(sa));
  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: 
  153:         /* Close all unnecessary FDs.
  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:     }
  278:     return NULL;
  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);
  291:     return t ? t : strlongip(ctl, ip);
  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>