Annotation of embedaddon/mtr/ui/dns.c, revision 1.1.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>