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>