Annotation of embedaddon/mtr/ui/dns.c, revision 1.1.1.3

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
1.1.1.3 ! misho       6:     it under the terms of the GNU General Public License version 2 as
1.1       misho       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(
1.1.1.3 ! misho      55:     sa_family_t family,
1.1       misho      56:     ip_t * ip)
                     57: {
                     58: #ifdef ENABLE_IPV6
                     59:     static char addrstr[INET6_ADDRSTRLEN];
                     60: 
1.1.1.3 ! misho      61:     return (char *) inet_ntop(family, ip, addrstr, sizeof addrstr);
1.1       misho      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: static struct dns_results *findip(
                     91:     struct mtr_ctl *ctl,
                     92:     ip_t * ip)
                     93: {
                     94:     struct dns_results *t;
                     95: 
                     96:     for (t = results; t; t = t->next) {
1.1.1.2   misho      97:         if (addrcmp(ip, &t->ip, ctl->af) == 0)
1.1       misho      98:             return t;
                     99:     }
                    100: 
                    101:     return NULL;
                    102: }
                    103: 
                    104: static void set_sockaddr_ip(
1.1.1.3 ! misho     105:     sa_family_t family,
1.1       misho     106:     struct sockaddr_storage *sa,
                    107:     ip_t * ip)
                    108: {
                    109:     memset(sa, 0, sizeof(struct sockaddr_storage));
1.1.1.3 ! misho     110:     sa->ss_family = family;
1.1.1.2   misho     111:     memcpy(sockaddr_addr_offset(sa), ip, sockaddr_addr_size(sa));
1.1       misho     112: }
                    113: 
                    114: void dns_open(
1.1.1.3 ! misho     115:     void)
1.1       misho     116: {
                    117:     int pid;
                    118: 
                    119:     if (pipe(todns) < 0) {
                    120:         error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
                    121:     }
                    122: 
                    123:     if (pipe(fromdns) < 0) {
                    124:         error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
                    125:     }
                    126:     fflush(stdout);
                    127:     pid = fork();
                    128:     if (pid < 0) {
                    129:         error(EXIT_FAILURE, errno, "can't fork for DNS process");
                    130:     }
                    131:     if (pid == 0) {
                    132:         char buf[2048];
                    133:         int i;
                    134:         FILE *infp;
                    135: 
                    136:         /* Automatically reap children. */
                    137:         if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
                    138:             error(EXIT_FAILURE, errno, "signal");
                    139:         }
                    140: 
1.1.1.2   misho     141:         /* Close all unnecessary FDs.
1.1       misho     142:            for debugging and error reporting, keep std-in/out/err. */
                    143:         for (i = 3; i < fromdns[1]; i++) {
                    144:             if (i == todns[0])
                    145:                 continue;
                    146:             if (i == fromdns[1])
                    147:                 continue;
                    148:             close(i);
                    149:         }
                    150:         infp = fdopen(todns[0], "r");
                    151: 
                    152:         while (fgets(buf, sizeof(buf), infp)) {
                    153:             ip_t host;
                    154:             struct sockaddr_storage sa;
                    155:             socklen_t salen;
                    156:             char hostname[NI_MAXHOST];
                    157:             char result[INET6_ADDRSTRLEN + NI_MAXHOST + 2];
                    158: 
                    159:             if (!fork()) {
                    160:                 int rv;
                    161: 
                    162:                 buf[strlen(buf) - 1] = 0;       /* chomp newline. */
                    163: 
1.1.1.3 ! misho     164:                 sa_family_t family = (buf[0] == '4') ? AF_INET : AF_INET6;
        !           165:                 longipstr(buf +1, &host, family);
        !           166:                 set_sockaddr_ip(family, &sa, &host);
        !           167:                 salen = (family == AF_INET) ? sizeof(struct sockaddr_in) :
1.1       misho     168:                     sizeof(struct sockaddr_in6);
                    169: 
                    170:                 rv = getnameinfo((struct sockaddr *) &sa, salen,
                    171:                                  hostname, sizeof(hostname), NULL, 0, 0);
                    172:                 if (rv == 0) {
                    173:                     snprintf(result, sizeof(result),
1.1.1.3 ! misho     174:                              "%s %s\n", strlongip(family, &host), hostname);
1.1       misho     175: 
                    176:                     rv = write(fromdns[1], result, strlen(result));
                    177:                     if (rv < 0)
                    178:                         error(0, errno, "write DNS lookup result");
                    179:                 }
                    180: 
                    181:                 exit(EXIT_SUCCESS);
                    182:             }
                    183:         }
                    184:         exit(EXIT_SUCCESS);
                    185:     } else {
                    186:         int flags;
                    187: 
                    188:         /* the parent. */
                    189:         close(todns[0]);        /* close the pipe ends we don't need. */
                    190:         close(fromdns[1]);
                    191:         fromdnsfp = fdopen(fromdns[0], "r");
                    192:         flags = fcntl(fromdns[0], F_GETFL, 0);
                    193:         flags |= O_NONBLOCK;
                    194:         fcntl(fromdns[0], F_SETFL, flags);
                    195:     }
                    196: }
                    197: 
                    198: int dns_waitfd(
                    199:     void)
                    200: {
                    201:     return fromdns[0];
                    202: }
                    203: 
                    204: 
                    205: void dns_ack(
                    206:     struct mtr_ctl *ctl)
                    207: {
                    208:     char buf[2048], host[NI_MAXHOST], name[NI_MAXHOST];
                    209:     ip_t hostip;
                    210:     struct dns_results *r;
                    211: 
                    212:     while (fgets(buf, sizeof(buf), fromdnsfp)) {
                    213:         sscanf(buf, "%s %s", host, name);
                    214: 
                    215:         longipstr(host, &hostip, ctl->af);
                    216:         r = findip(ctl, &hostip);
                    217:         if (r)
                    218:             r->name = xstrdup(name);
                    219:         else
                    220:             error(0, 0, "dns_ack: Couldn't find host %s", host);
                    221:     }
                    222: }
                    223: 
                    224: 
                    225: 
                    226: #ifdef ENABLE_IPV6
                    227: 
                    228: int dns_waitfd6(
                    229:     void)
                    230: {
                    231:     return -1;
                    232: }
                    233: 
                    234: void dns_ack6(
                    235:     void)
                    236: {
                    237:     return;
                    238: }
                    239: 
                    240: #endif
                    241: 
                    242: 
                    243: char *dns_lookup2(
                    244:     struct mtr_ctl *ctl,
                    245:     ip_t * ip)
                    246: {
                    247:     struct dns_results *r;
1.1.1.3 ! misho     248:     char buf[INET6_ADDRSTRLEN + 2]; // af_byte + addr + null
1.1       misho     249:     int rv;
                    250: 
                    251:     r = findip(ctl, ip);
                    252:     if (r) {
                    253:         /* we've got a result. */
                    254:         if (r->name)
                    255:             return r->name;
                    256:     } else {
                    257:         r = xmalloc(sizeof(struct dns_results));
                    258:         memcpy(&r->ip, ip, sizeof(r->ip));
                    259:         r->name = NULL;
                    260:         r->next = results;
                    261:         results = r;
1.1.1.3 ! misho     262:         char ip4or6 = (ctl->af == AF_INET) ? '4' : '6';
        !           263:         snprintf(buf, sizeof(buf), "%c%s\n", ip4or6, strlongip(ctl->af, ip));
1.1       misho     264:         rv = write(todns[1], buf, strlen(buf));
                    265:         if (rv < 0)
                    266:             error(0, errno, "couldn't write to resolver process");
                    267:     }
1.1.1.2   misho     268:     return NULL;
1.1       misho     269: }
                    270: 
                    271: 
                    272: char *dns_lookup(
                    273:     struct mtr_ctl *ctl,
                    274:     ip_t * ip)
                    275: {
                    276:     char *t;
                    277: 
                    278:     if (!ctl->dns || !ctl->use_dns)
                    279:         return NULL;
                    280:     t = dns_lookup2(ctl, ip);
1.1.1.3 ! misho     281:     return t ? t : strlongip(ctl->af, ip);
1.1       misho     282: }
                    283: 
                    284: /* XXX check if necessary/exported. */
                    285: 
                    286: /* Resolve an IP address to a hostname. */
                    287: struct hostent *addr2host(
                    288:     const char *addr,
                    289:     int family)
                    290: {
                    291:     int len = 0;
                    292:     switch (family) {
                    293:     case AF_INET:
                    294:         len = sizeof(struct in_addr);
                    295:         break;
                    296: #ifdef ENABLE_IPV6
                    297:     case AF_INET6:
                    298:         len = sizeof(struct in6_addr);
                    299:         break;
                    300: #endif
                    301:     }
                    302:     return gethostbyaddr(addr, len, family);
                    303: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>