Annotation of embedaddon/mtr/ui/net.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: #include "config.h"
        !            20: 
        !            21: #include <errno.h>
        !            22: #include <math.h>
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: #include <sys/select.h>
        !            26: #include <unistd.h>
        !            27: 
        !            28: #ifdef HAVE_ERROR_H
        !            29: #include <error.h>
        !            30: #else
        !            31: #include "portability/error.h"
        !            32: #endif
        !            33: 
        !            34: #include "mtr.h"
        !            35: #include "cmdpipe.h"
        !            36: #include "net.h"
        !            37: #include "display.h"
        !            38: #include "dns.h"
        !            39: #include "utils.h"
        !            40: 
        !            41: #define MinSequence 33000
        !            42: #define MaxSequence 65536
        !            43: 
        !            44: static int packetsize;          /* packet size used by ping */
        !            45: 
        !            46: static void sockaddrtop(
        !            47:     struct sockaddr *saddr,
        !            48:     char *strptr,
        !            49:     size_t len);
        !            50: 
        !            51: struct nethost {
        !            52:     ip_t addr;
        !            53:     ip_t addrs[MAXPATH];        /* for multi paths byMin */
        !            54:     int xmit;
        !            55:     int returned;
        !            56:     int sent;
        !            57:     int up;
        !            58:     long long ssd;              /* sum of squares of differences from the current average */
        !            59:     int last;
        !            60:     int best;
        !            61:     int worst;
        !            62:     int avg;                    /* average:  addByMin */
        !            63:     int gmean;                  /* geometric mean: addByMin */
        !            64:     int jitter;                 /* current jitter, defined as t1-t0 addByMin */
        !            65:     int javg;                   /* avg jitter */
        !            66:     int jworst;                 /* max jitter */
        !            67:     int jinta;                  /* estimated variance,? rfc1889's "Interarrival Jitter" */
        !            68:     int transit;
        !            69:     int saved[SAVED_PINGS];
        !            70:     int saved_seq_offset;
        !            71:     struct mplslen mpls;
        !            72:     struct mplslen mplss[MAXPATH];
        !            73: };
        !            74: 
        !            75: 
        !            76: struct sequence {
        !            77:     int index;
        !            78:     int transit;
        !            79:     int saved_seq;
        !            80:     struct timeval time;
        !            81: };
        !            82: 
        !            83: 
        !            84: static struct nethost host[MaxHost];
        !            85: static struct sequence sequence[MaxSequence];
        !            86: static struct packet_command_pipe_t packet_command_pipe;
        !            87: 
        !            88: #ifdef ENABLE_IPV6
        !            89: static struct sockaddr_storage sourcesockaddr_struct;
        !            90: static struct sockaddr_storage remotesockaddr_struct;
        !            91: static struct sockaddr_in6 *ssa6 =
        !            92:     (struct sockaddr_in6 *) &sourcesockaddr_struct;
        !            93: static struct sockaddr_in6 *rsa6 =
        !            94:     (struct sockaddr_in6 *) &remotesockaddr_struct;
        !            95: #else
        !            96: static struct sockaddr_in sourcesockaddr_struct;
        !            97: static struct sockaddr_in remotesockaddr_struct;
        !            98: #endif
        !            99: 
        !           100: static struct sockaddr *sourcesockaddr =
        !           101:     (struct sockaddr *) &sourcesockaddr_struct;
        !           102: static struct sockaddr *remotesockaddr =
        !           103:     (struct sockaddr *) &remotesockaddr_struct;
        !           104: static struct sockaddr_in *ssa4 =
        !           105:     (struct sockaddr_in *) &sourcesockaddr_struct;
        !           106: static struct sockaddr_in *rsa4 =
        !           107:     (struct sockaddr_in *) &remotesockaddr_struct;
        !           108: 
        !           109: static ip_t *sourceaddress;
        !           110: static ip_t *remoteaddress;
        !           111: 
        !           112: #ifdef ENABLE_IPV6
        !           113: static char localaddr[INET6_ADDRSTRLEN];
        !           114: #else
        !           115: #ifndef INET_ADDRSTRLEN
        !           116: #define INET_ADDRSTRLEN 16
        !           117: #endif
        !           118: static char localaddr[INET_ADDRSTRLEN];
        !           119: #endif
        !           120: 
        !           121: static int batch_at = 0;
        !           122: static int numhosts = 10;
        !           123: 
        !           124: /* return the number of microseconds to wait before sending the next
        !           125:    ping */
        !           126: int calc_deltatime(
        !           127:     float waittime)
        !           128: {
        !           129:     waittime /= numhosts;
        !           130:     return 1000000 * waittime;
        !           131: }
        !           132: 
        !           133: 
        !           134: static void save_sequence(
        !           135:     struct mtr_ctl *ctl,
        !           136:     int index,
        !           137:     int seq)
        !           138: {
        !           139:     display_rawxmit(ctl, index, seq);
        !           140: 
        !           141:     sequence[seq].index = index;
        !           142:     sequence[seq].transit = 1;
        !           143:     sequence[seq].saved_seq = ++host[index].xmit;
        !           144:     memset(&sequence[seq].time, 0, sizeof(sequence[seq].time));
        !           145: 
        !           146:     host[index].transit = 1;
        !           147: 
        !           148:     if (host[index].sent) {
        !           149:         host[index].up = 0;
        !           150:     }
        !           151: 
        !           152:     host[index].sent = 1;
        !           153:     net_save_xmit(index);
        !           154: }
        !           155: 
        !           156: static int new_sequence(
        !           157:     struct mtr_ctl *ctl,
        !           158:     int index)
        !           159: {
        !           160:     static int next_sequence = MinSequence;
        !           161:     int seq;
        !           162: 
        !           163:     seq = next_sequence++;
        !           164:     if (next_sequence >= MaxSequence) {
        !           165:         next_sequence = MinSequence;
        !           166:     }
        !           167: 
        !           168:     save_sequence(ctl, index, seq);
        !           169: 
        !           170:     return seq;
        !           171: }
        !           172: 
        !           173: 
        !           174: /*  Attempt to find the host at a particular number of hops away  */
        !           175: static void net_send_query(
        !           176:     struct mtr_ctl *ctl,
        !           177:     int index,
        !           178:     int packet_size)
        !           179: {
        !           180:     int seq = new_sequence(ctl, index);
        !           181:     int time_to_live = index + 1;
        !           182: 
        !           183:     send_probe_command(ctl, &packet_command_pipe, remoteaddress,
        !           184:                        sourceaddress, packetsize, seq, time_to_live);
        !           185: }
        !           186: 
        !           187: 
        !           188: /* We got a return on something we sent out.  Record the address and
        !           189:    time.  */
        !           190: static void net_process_ping(
        !           191:     struct mtr_ctl *ctl,
        !           192:     int seq,
        !           193:     struct mplslen *mpls,
        !           194:     ip_t * addr,
        !           195:     int totusec)
        !           196: {
        !           197:     int index;
        !           198:     int oldavg;                 /* usedByMin */
        !           199:     int oldjavg;                /* usedByMin */
        !           200:     int i;                      /* usedByMin */
        !           201: #ifdef ENABLE_IPV6
        !           202:     char addrcopy[sizeof(struct in6_addr)];
        !           203: #else
        !           204:     char addrcopy[sizeof(struct in_addr)];
        !           205: #endif
        !           206: 
        !           207:     addrcpy((void *) &addrcopy, (char *) addr, ctl->af);
        !           208: 
        !           209:     if ((seq < 0) || (seq >= MaxSequence)) {
        !           210:         return;
        !           211:     }
        !           212: 
        !           213:     if (!sequence[seq].transit) {
        !           214:         return;
        !           215:     }
        !           216:     sequence[seq].transit = 0;
        !           217: 
        !           218:     index = sequence[seq].index;
        !           219: 
        !           220:     if (addrcmp((void *) &(host[index].addr),
        !           221:                 (void *) &ctl->unspec_addr, ctl->af) == 0) {
        !           222:         /* should be out of if as addr can change */
        !           223:         addrcpy((void *) &(host[index].addr), addrcopy, ctl->af);
        !           224:         host[index].mpls = *mpls;
        !           225:         display_rawhost(ctl, index, (void *) &(host[index].addr));
        !           226: 
        !           227:         /* multi paths */
        !           228:         addrcpy((void *) &(host[index].addrs[0]), addrcopy, ctl->af);
        !           229:         host[index].mplss[0] = *mpls;
        !           230:     } else {
        !           231:         for (i = 0; i < MAXPATH;) {
        !           232:             if (addrcmp
        !           233:                 ((void *) &(host[index].addrs[i]), (void *) &addrcopy,
        !           234:                  ctl->af) == 0
        !           235:                 || addrcmp((void *) &(host[index].addrs[i]),
        !           236:                            (void *) &ctl->unspec_addr, ctl->af) == 0) {
        !           237:                 break;
        !           238:             }
        !           239:             i++;
        !           240:         }
        !           241: 
        !           242:         if (addrcmp((void *) &(host[index].addrs[i]), addrcopy, ctl->af) !=
        !           243:             0 && i < MAXPATH) {
        !           244:             addrcpy((void *) &(host[index].addrs[i]), addrcopy, ctl->af);
        !           245:             host[index].mplss[i] = *mpls;
        !           246:             display_rawhost(ctl, index, (void *) &(host[index].addrs[i]));
        !           247:         }
        !           248:     }
        !           249: 
        !           250:     host[index].jitter = totusec - host[index].last;
        !           251:     if (host[index].jitter < 0) {
        !           252:         host[index].jitter = -host[index].jitter;
        !           253:     }
        !           254: 
        !           255:     host[index].last = totusec;
        !           256: 
        !           257:     if (host[index].returned < 1) {
        !           258:         host[index].best = host[index].worst = host[index].gmean = totusec;
        !           259:         host[index].avg = host[index].ssd = 0;
        !           260: 
        !           261:         host[index].jitter = host[index].jworst = host[index].jinta = 0;
        !           262:     }
        !           263: 
        !           264:     if (totusec < host[index].best) {
        !           265:         host[index].best = totusec;
        !           266:     }
        !           267:     if (totusec > host[index].worst) {
        !           268:         host[index].worst = totusec;
        !           269:     }
        !           270: 
        !           271:     if (host[index].jitter > host[index].jworst) {
        !           272:         host[index].jworst = host[index].jitter;
        !           273:     }
        !           274: 
        !           275:     host[index].returned++;
        !           276:     oldavg = host[index].avg;
        !           277:     host[index].avg += (totusec - oldavg + .0) / host[index].returned;
        !           278:     host[index].ssd +=
        !           279:         (totusec - oldavg + .0) * (totusec - host[index].avg);
        !           280: 
        !           281:     oldjavg = host[index].javg;
        !           282:     host[index].javg +=
        !           283:         (host[index].jitter - oldjavg) / host[index].returned;
        !           284:     /* below algorithm is from rfc1889, A.8 */
        !           285:     host[index].jinta +=
        !           286:         host[index].jitter - ((host[index].jinta + 8) >> 4);
        !           287: 
        !           288:     if (host[index].returned > 1) {
        !           289:         host[index].gmean =
        !           290:             pow((double) host[index].gmean,
        !           291:                 (host[index].returned - 1.0) / host[index].returned)
        !           292:             * pow((double) totusec, 1.0 / host[index].returned);
        !           293:     }
        !           294: 
        !           295:     host[index].sent = 0;
        !           296:     host[index].up = 1;
        !           297:     host[index].transit = 0;
        !           298: 
        !           299:     net_save_return(index, sequence[seq].saved_seq, totusec);
        !           300:     display_rawping(ctl, index, totusec, seq);
        !           301: }
        !           302: 
        !           303: /*
        !           304:     Invoked when the read pipe from the mtr-packet subprocess is readable.
        !           305:     If we have received a complete reply, process it.
        !           306: */
        !           307: void net_process_return(
        !           308:     struct mtr_ctl *ctl)
        !           309: {
        !           310:     handle_command_replies(ctl, &packet_command_pipe, net_process_ping);
        !           311: }
        !           312: 
        !           313: 
        !           314: ip_t *net_addr(
        !           315:     int at)
        !           316: {
        !           317:     return (ip_t *) & (host[at].addr);
        !           318: }
        !           319: 
        !           320: 
        !           321: ip_t *net_addrs(
        !           322:     int at,
        !           323:     int i)
        !           324: {
        !           325:     return (ip_t *) & (host[at].addrs[i]);
        !           326: }
        !           327: 
        !           328: void *net_mpls(
        !           329:     int at)
        !           330: {
        !           331:     return (struct mplslen *) &(host[at].mplss);
        !           332: }
        !           333: 
        !           334: void *net_mplss(
        !           335:     int at,
        !           336:     int i)
        !           337: {
        !           338:     return (struct mplslen *) &(host[at].mplss[i]);
        !           339: }
        !           340: 
        !           341: int net_loss(
        !           342:     int at)
        !           343: {
        !           344:     if ((host[at].xmit - host[at].transit) == 0) {
        !           345:         return 0;
        !           346:     }
        !           347: 
        !           348:     /* times extra 1000 */
        !           349:     return 1000 * (100 -
        !           350:                    (100.0 * host[at].returned /
        !           351:                     (host[at].xmit - host[at].transit)));
        !           352: }
        !           353: 
        !           354: 
        !           355: int net_drop(
        !           356:     int at)
        !           357: {
        !           358:     return (host[at].xmit - host[at].transit) - host[at].returned;
        !           359: }
        !           360: 
        !           361: 
        !           362: int net_last(
        !           363:     int at)
        !           364: {
        !           365:     return (host[at].last);
        !           366: }
        !           367: 
        !           368: 
        !           369: int net_best(
        !           370:     int at)
        !           371: {
        !           372:     return (host[at].best);
        !           373: }
        !           374: 
        !           375: 
        !           376: int net_worst(
        !           377:     int at)
        !           378: {
        !           379:     return (host[at].worst);
        !           380: }
        !           381: 
        !           382: 
        !           383: int net_avg(
        !           384:     int at)
        !           385: {
        !           386:     return (host[at].avg);
        !           387: }
        !           388: 
        !           389: 
        !           390: int net_gmean(
        !           391:     int at)
        !           392: {
        !           393:     return (host[at].gmean);
        !           394: }
        !           395: 
        !           396: 
        !           397: int net_stdev(
        !           398:     int at)
        !           399: {
        !           400:     if (host[at].returned > 1) {
        !           401:         return (sqrt(host[at].ssd / (host[at].returned - 1.0)));
        !           402:     } else {
        !           403:         return (0);
        !           404:     }
        !           405: }
        !           406: 
        !           407: 
        !           408: int net_jitter(
        !           409:     int at)
        !           410: {
        !           411:     return (host[at].jitter);
        !           412: }
        !           413: 
        !           414: 
        !           415: int net_jworst(
        !           416:     int at)
        !           417: {
        !           418:     return (host[at].jworst);
        !           419: }
        !           420: 
        !           421: 
        !           422: int net_javg(
        !           423:     int at)
        !           424: {
        !           425:     return (host[at].javg);
        !           426: }
        !           427: 
        !           428: 
        !           429: int net_jinta(
        !           430:     int at)
        !           431: {
        !           432:     return (host[at].jinta);
        !           433: }
        !           434: 
        !           435: 
        !           436: int net_max(
        !           437:     struct mtr_ctl *ctl)
        !           438: {
        !           439:     int at;
        !           440:     int max;
        !           441: 
        !           442:     max = 0;
        !           443:     for (at = 0; at < ctl->maxTTL - 1; at++) {
        !           444:         if (addrcmp((void *) &(host[at].addr),
        !           445:                     (void *) remoteaddress, ctl->af) == 0) {
        !           446:             return at + 1;
        !           447:         } else if (addrcmp((void *) &(host[at].addr),
        !           448:                            (void *) &ctl->unspec_addr, ctl->af) != 0) {
        !           449:             max = at + 2;
        !           450:         }
        !           451:     }
        !           452: 
        !           453:     return max;
        !           454: }
        !           455: 
        !           456: 
        !           457: int net_min(
        !           458:     struct mtr_ctl *ctl)
        !           459: {
        !           460:     return (ctl->fstTTL - 1);
        !           461: }
        !           462: 
        !           463: 
        !           464: int net_returned(
        !           465:     int at)
        !           466: {
        !           467:     return host[at].returned;
        !           468: }
        !           469: 
        !           470: 
        !           471: int net_xmit(
        !           472:     int at)
        !           473: {
        !           474:     return host[at].xmit;
        !           475: }
        !           476: 
        !           477: 
        !           478: int net_up(
        !           479:     int at)
        !           480: {
        !           481:     return host[at].up;
        !           482: }
        !           483: 
        !           484: 
        !           485: char *net_localaddr(
        !           486:     void)
        !           487: {
        !           488:     return localaddr;
        !           489: }
        !           490: 
        !           491: 
        !           492: void net_end_transit(
        !           493:     void)
        !           494: {
        !           495:     int at;
        !           496: 
        !           497:     for (at = 0; at < MaxHost; at++) {
        !           498:         host[at].transit = 0;
        !           499:     }
        !           500: }
        !           501: 
        !           502: int net_send_batch(
        !           503:     struct mtr_ctl *ctl)
        !           504: {
        !           505:     int n_unknown = 0, i;
        !           506: 
        !           507:     /* randomized packet size and/or bit pattern if packetsize<0 and/or 
        !           508:        bitpattern<0.  abs(packetsize) and/or abs(bitpattern) will be used 
        !           509:      */
        !           510:     if (batch_at < ctl->fstTTL) {
        !           511:         if (ctl->cpacketsize < 0) {
        !           512:             /* Someone used a formula here that tried to correct for the 
        !           513:                "end-error" in "rand()". By "end-error" I mean that if you 
        !           514:                have a range for "rand()" that runs to 32768, and the 
        !           515:                destination range is 10000, you end up with 4 out of 32768 
        !           516:                0-2768's and only 3 out of 32768 for results 2769 .. 9999. 
        !           517:                As our detination range (in the example 10000) is much 
        !           518:                smaller (reasonable packet sizes), and our rand() range much 
        !           519:                larger, this effect is insignificant. Oh! That other formula
        !           520:                didn't work. */
        !           521:             packetsize =
        !           522:                 MINPACKET + rand() % (-ctl->cpacketsize - MINPACKET);
        !           523:         } else {
        !           524:             packetsize = ctl->cpacketsize;
        !           525:         }
        !           526:         if (ctl->bitpattern < 0) {
        !           527:             ctl->bitpattern =
        !           528:                 -(int) (256 + 255 * (rand() / (RAND_MAX + 0.1)));
        !           529:         }
        !           530:     }
        !           531: 
        !           532:     net_send_query(ctl, batch_at, abs(packetsize));
        !           533: 
        !           534:     for (i = ctl->fstTTL - 1; i < batch_at; i++) {
        !           535:         if (addrcmp
        !           536:             ((void *) &(host[i].addr), (void *) &ctl->unspec_addr,
        !           537:              ctl->af) == 0)
        !           538:             n_unknown++;
        !           539: 
        !           540:         /* The second condition in the next "if" statement was added in mtr-0.56, 
        !           541:            but I don't remember why. It makes mtr stop skipping sections of unknown
        !           542:            hosts. Removed in 0.65. 
        !           543:            If the line proves necessary, it should at least NOT trigger that line
        !           544:            when host[i].addr == 0 */
        !           545:         if ((addrcmp((void *) &(host[i].addr),
        !           546:                      (void *) remoteaddress, ctl->af) == 0))
        !           547:             n_unknown = MaxHost;        /* Make sure we drop into "we should restart" */
        !           548:     }
        !           549: 
        !           550:     if (                        /* success in reaching target */
        !           551:            (addrcmp((void *) &(host[batch_at].addr),
        !           552:                     (void *) remoteaddress, ctl->af) == 0) ||
        !           553:            /* fail in consecutive maxUnknown (firewall?) */
        !           554:            (n_unknown > ctl->maxUnknown) ||
        !           555:            /* or reach limit  */
        !           556:            (batch_at >= ctl->maxTTL - 1)) {
        !           557:         numhosts = batch_at + 1;
        !           558:         batch_at = ctl->fstTTL - 1;
        !           559:         return 1;
        !           560:     }
        !           561: 
        !           562:     batch_at++;
        !           563:     return 0;
        !           564: }
        !           565: 
        !           566: 
        !           567: /*  Ensure the interface address a valid address for our use  */
        !           568: static void net_validate_interface_address(
        !           569:     int address_family,
        !           570:     char *interface_address)
        !           571: {
        !           572:     if (inet_pton(address_family, interface_address, sourceaddress) != 1) {
        !           573:         error(EXIT_FAILURE, errno, "invalid local address");
        !           574:     }
        !           575: 
        !           576:     if (inet_ntop
        !           577:         (address_family, sourceaddress, localaddr,
        !           578:          sizeof(localaddr)) == NULL) {
        !           579:         error(EXIT_FAILURE, errno, "invalid local address");
        !           580:     }
        !           581: }
        !           582: 
        !           583: 
        !           584: /*
        !           585:   Find the local address we will use to sent to the remote
        !           586:   host by connecting a UDP socket and checking the address
        !           587:   the socket is bound to.
        !           588: */
        !           589: static void net_find_local_address(
        !           590:     void)
        !           591: {
        !           592:     int udp_socket;
        !           593:     int addr_length;
        !           594:     struct sockaddr_storage remote_sockaddr;
        !           595:     struct sockaddr_in *remote4;
        !           596:     struct sockaddr_in6 *remote6;
        !           597: 
        !           598:     udp_socket =
        !           599:         socket(remotesockaddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
        !           600:     if (udp_socket == -1) {
        !           601:         error(EXIT_FAILURE, errno, "udp socket creation failed");
        !           602:     }
        !           603: 
        !           604:     /*
        !           605:        We need to set the port to a non-zero value for the connect
        !           606:        to succeed.
        !           607:      */
        !           608:     if (remotesockaddr->sa_family == AF_INET6) {
        !           609: #ifdef ENABLE_IPV6
        !           610:         addr_length = sizeof(struct sockaddr_in6);
        !           611: 
        !           612:         memcpy(&remote_sockaddr, rsa6, addr_length);
        !           613:         remote6 = (struct sockaddr_in6 *) &remote_sockaddr;
        !           614:         remote6->sin6_port = htons(1);
        !           615: #endif
        !           616:     } else {
        !           617:         addr_length = sizeof(struct sockaddr_in);
        !           618: 
        !           619:         memcpy(&remote_sockaddr, rsa4, addr_length);
        !           620:         remote4 = (struct sockaddr_in *) &remote_sockaddr;
        !           621:         remote4->sin_port = htons(1);
        !           622:     }
        !           623: 
        !           624:     if (connect
        !           625:         (udp_socket, (struct sockaddr *) &remote_sockaddr, addr_length)) {
        !           626:         error(EXIT_FAILURE, errno, "udp socket connect failed");
        !           627:     }
        !           628: 
        !           629:     if (getsockname(udp_socket, sourcesockaddr, &addr_length)) {
        !           630: 
        !           631:         error(EXIT_FAILURE, errno, "local address determination failed");
        !           632:     }
        !           633: 
        !           634:     sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
        !           635: 
        !           636:     close(udp_socket);
        !           637: }
        !           638: 
        !           639: 
        !           640: int net_open(
        !           641:     struct mtr_ctl *ctl,
        !           642:     struct hostent *hostent)
        !           643: {
        !           644:     int err;
        !           645: 
        !           646:     /*  Spawn the mtr-packet child process  */
        !           647:     err = open_command_pipe(ctl, &packet_command_pipe);
        !           648:     if (err) {
        !           649:         return err;
        !           650:     }
        !           651: 
        !           652:     net_reset(ctl);
        !           653: 
        !           654:     remotesockaddr->sa_family = hostent->h_addrtype;
        !           655: 
        !           656:     switch (hostent->h_addrtype) {
        !           657:     case AF_INET:
        !           658:         addrcpy((void *) &(rsa4->sin_addr), hostent->h_addr, AF_INET);
        !           659:         sourceaddress = (ip_t *) & (ssa4->sin_addr);
        !           660:         remoteaddress = (ip_t *) & (rsa4->sin_addr);
        !           661:         break;
        !           662: #ifdef ENABLE_IPV6
        !           663:     case AF_INET6:
        !           664:         addrcpy((void *) &(rsa6->sin6_addr), hostent->h_addr, AF_INET6);
        !           665:         sourceaddress = (ip_t *) & (ssa6->sin6_addr);
        !           666:         remoteaddress = (ip_t *) & (rsa6->sin6_addr);
        !           667:         break;
        !           668: #endif
        !           669:     default:
        !           670:         error(EXIT_FAILURE, 0, "net_open bad address type");
        !           671:     }
        !           672: 
        !           673:     if (ctl->InterfaceAddress) {
        !           674:         net_validate_interface_address(ctl->af, ctl->InterfaceAddress);
        !           675:     } else {
        !           676:         net_find_local_address();
        !           677:     }
        !           678: 
        !           679:     return 0;
        !           680: }
        !           681: 
        !           682: 
        !           683: void net_reopen(
        !           684:     struct mtr_ctl *ctl,
        !           685:     struct hostent *addr)
        !           686: {
        !           687:     int at;
        !           688: 
        !           689:     for (at = 0; at < MaxHost; at++) {
        !           690:         memset(&host[at], 0, sizeof(host[at]));
        !           691:     }
        !           692: 
        !           693:     remotesockaddr->sa_family = addr->h_addrtype;
        !           694:     addrcpy((void *) remoteaddress, addr->h_addr, addr->h_addrtype);
        !           695: 
        !           696:     switch (addr->h_addrtype) {
        !           697:     case AF_INET:
        !           698:         addrcpy((void *) &(rsa4->sin_addr), addr->h_addr, AF_INET);
        !           699:         break;
        !           700: #ifdef ENABLE_IPV6
        !           701:     case AF_INET6:
        !           702:         addrcpy((void *) &(rsa6->sin6_addr), addr->h_addr, AF_INET6);
        !           703:         break;
        !           704: #endif
        !           705:     default:
        !           706:         error(EXIT_FAILURE, 0, "net_reopen bad address type");
        !           707:     }
        !           708: 
        !           709:     net_reset(ctl);
        !           710:     net_send_batch(ctl);
        !           711: }
        !           712: 
        !           713: 
        !           714: void net_reset(
        !           715:     struct mtr_ctl *ctl)
        !           716: {
        !           717:     static struct nethost template = {
        !           718:         .saved_seq_offset = 2 - SAVED_PINGS
        !           719:     };
        !           720: 
        !           721:     int at, i;
        !           722: 
        !           723:     batch_at = ctl->fstTTL - 1; /* above replacedByMin */
        !           724:     numhosts = 10;
        !           725: 
        !           726:     for (i = 0; i < SAVED_PINGS; i++)
        !           727:         template.saved[i] = -2;
        !           728: 
        !           729:     for (at = 0; at < MaxHost; at++) {
        !           730:         memcpy(&(host[at]), &template, sizeof(template));
        !           731:     }
        !           732: 
        !           733:     for (at = 0; at < MaxSequence; at++) {
        !           734:         sequence[at].transit = 0;
        !           735:     }
        !           736: 
        !           737: }
        !           738: 
        !           739: 
        !           740: /*  Close the pipe to the packet generator process, and kill the process  */
        !           741: void net_close(
        !           742:     void)
        !           743: {
        !           744:     close_command_pipe(&packet_command_pipe);
        !           745: }
        !           746: 
        !           747: 
        !           748: int net_waitfd(
        !           749:     void)
        !           750: {
        !           751:     return packet_command_pipe.read_fd;
        !           752: }
        !           753: 
        !           754: 
        !           755: int *net_saved_pings(
        !           756:     int at)
        !           757: {
        !           758:     return host[at].saved;
        !           759: }
        !           760: 
        !           761: 
        !           762: static void net_save_increment(
        !           763:     void)
        !           764: {
        !           765:     int at;
        !           766:     for (at = 0; at < MaxHost; at++) {
        !           767:         memmove(host[at].saved, host[at].saved + 1,
        !           768:                 (SAVED_PINGS - 1) * sizeof(int));
        !           769:         host[at].saved[SAVED_PINGS - 1] = -2;
        !           770:         host[at].saved_seq_offset += 1;
        !           771:     }
        !           772: }
        !           773: 
        !           774: 
        !           775: void net_save_xmit(
        !           776:     int at)
        !           777: {
        !           778:     if (host[at].saved[SAVED_PINGS - 1] != -2)
        !           779:         net_save_increment();
        !           780:     host[at].saved[SAVED_PINGS - 1] = -1;
        !           781: }
        !           782: 
        !           783: 
        !           784: void net_save_return(
        !           785:     int at,
        !           786:     int seq,
        !           787:     int ms)
        !           788: {
        !           789:     int idx;
        !           790:     idx = seq - host[at].saved_seq_offset;
        !           791:     if ((idx < 0) || (idx >= SAVED_PINGS)) {
        !           792:         return;
        !           793:     }
        !           794:     host[at].saved[idx] = ms;
        !           795: }
        !           796: 
        !           797: /* Similar to inet_ntop but uses a sockaddr as it's argument. */
        !           798: static void sockaddrtop(
        !           799:     struct sockaddr *saddr,
        !           800:     char *strptr,
        !           801:     size_t len)
        !           802: {
        !           803:     struct sockaddr_in *sa4;
        !           804: #ifdef ENABLE_IPV6
        !           805:     struct sockaddr_in6 *sa6;
        !           806: #endif
        !           807: 
        !           808:     switch (saddr->sa_family) {
        !           809:     case AF_INET:
        !           810:         sa4 = (struct sockaddr_in *) saddr;
        !           811:         xstrncpy(strptr, inet_ntoa(sa4->sin_addr), len - 1);
        !           812:         strptr[len - 1] = '\0';
        !           813:         return;
        !           814: #ifdef ENABLE_IPV6
        !           815:     case AF_INET6:
        !           816:         sa6 = (struct sockaddr_in6 *) saddr;
        !           817:         inet_ntop(sa6->sin6_family, &(sa6->sin6_addr), strptr, len);
        !           818:         return;
        !           819: #endif
        !           820:     default:
        !           821:         error(0, 0, "sockaddrtop unknown address type");
        !           822:         strptr[0] = '\0';
        !           823:         return;
        !           824:     }
        !           825: }
        !           826: 
        !           827: 
        !           828: /* Address comparison. */
        !           829: int addrcmp(
        !           830:     char *a,
        !           831:     char *b,
        !           832:     int family)
        !           833: {
        !           834:     int rc = -1;
        !           835: 
        !           836:     switch (family) {
        !           837:     case AF_INET:
        !           838:         rc = memcmp(a, b, sizeof(struct in_addr));
        !           839:         break;
        !           840: #ifdef ENABLE_IPV6
        !           841:     case AF_INET6:
        !           842:         rc = memcmp(a, b, sizeof(struct in6_addr));
        !           843:         break;
        !           844: #endif
        !           845:     }
        !           846: 
        !           847:     return rc;
        !           848: }
        !           849: 
        !           850: /* Address copy. */
        !           851: void addrcpy(
        !           852:     char *a,
        !           853:     char *b,
        !           854:     int family)
        !           855: {
        !           856: 
        !           857:     switch (family) {
        !           858:     case AF_INET:
        !           859:         memcpy(a, b, sizeof(struct in_addr));
        !           860:         break;
        !           861: #ifdef ENABLE_IPV6
        !           862:     case AF_INET6:
        !           863:         memcpy(a, b, sizeof(struct in6_addr));
        !           864:         break;
        !           865: #endif
        !           866:     }
        !           867: }
        !           868: 
        !           869: /* for GTK frontend */
        !           870: void net_harvest_fds(
        !           871:     struct mtr_ctl *ctl)
        !           872: {
        !           873:     fd_set writefd;
        !           874:     int maxfd = 0;
        !           875:     struct timeval tv;
        !           876: 
        !           877:     FD_ZERO(&writefd);
        !           878:     tv.tv_sec = 0;
        !           879:     tv.tv_usec = 0;
        !           880:     select(maxfd, NULL, &writefd, NULL, &tv);
        !           881: }

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