File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / ui / net.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:18:58 2023 UTC (18 months, 1 week ago) by misho
Branches: mtr, MAIN
CVS tags: v0_95, HEAD
Version 0.95

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

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