File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / ui / net.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 14:25:31 2019 UTC (4 years, 9 months ago) by misho
Branches: mtr, MAIN
CVS tags: v0_92, HEAD
mtr ver 0.92

    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>