|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
mtr -- a network diagnostic tool
|
|
Packit |
b802ec |
Copyright (C) 1997,1998 Matt Kimball
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
b802ec |
it under the terms of the GNU General Public License version 2 as
|
|
Packit |
b802ec |
published by the Free Software Foundation.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is distributed in the hope that it will be useful,
|
|
Packit |
b802ec |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b802ec |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b802ec |
GNU General Public License for more details.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
You should have received a copy of the GNU General Public License
|
|
Packit |
b802ec |
along with this program; if not, write to the Free Software
|
|
Packit |
b802ec |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "config.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include <errno.h>
|
|
Packit |
b802ec |
#include <math.h>
|
|
Packit |
b802ec |
#include <stdlib.h>
|
|
Packit |
b802ec |
#include <string.h>
|
|
Packit |
b802ec |
#include <sys/select.h>
|
|
Packit |
b802ec |
#include <unistd.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef HAVE_ERROR_H
|
|
Packit |
b802ec |
#include <error.h>
|
|
Packit |
b802ec |
#else
|
|
Packit |
b802ec |
#include "portability/error.h"
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "mtr.h"
|
|
Packit |
b802ec |
#include "cmdpipe.h"
|
|
Packit |
b802ec |
#include "net.h"
|
|
Packit |
b802ec |
#include "display.h"
|
|
Packit |
b802ec |
#include "dns.h"
|
|
Packit |
b802ec |
#include "utils.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#define MinSequence 33000
|
|
Packit |
b802ec |
#define MaxSequence 65536
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static int packetsize; /* packet size used by ping */
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void sockaddrtop(
|
|
Packit |
b802ec |
struct sockaddr *saddr,
|
|
Packit |
b802ec |
char *strptr,
|
|
Packit |
b802ec |
size_t len);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
struct nethost {
|
|
Packit |
b802ec |
ip_t addr;
|
|
Packit |
b802ec |
ip_t addrs[MAXPATH]; /* for multi paths byMin */
|
|
Packit |
b802ec |
int xmit;
|
|
Packit |
b802ec |
int returned;
|
|
Packit |
b802ec |
int sent;
|
|
Packit |
b802ec |
int up;
|
|
Packit |
b802ec |
long long ssd; /* sum of squares of differences from the current average */
|
|
Packit |
b802ec |
int last;
|
|
Packit |
b802ec |
int best;
|
|
Packit |
b802ec |
int worst;
|
|
Packit |
b802ec |
int avg; /* average: addByMin */
|
|
Packit |
b802ec |
int gmean; /* geometric mean: addByMin */
|
|
Packit |
b802ec |
int jitter; /* current jitter, defined as t1-t0 addByMin */
|
|
Packit |
b802ec |
int javg; /* avg jitter */
|
|
Packit |
b802ec |
int jworst; /* max jitter */
|
|
Packit |
b802ec |
int jinta; /* estimated variance,? rfc1889's "Interarrival Jitter" */
|
|
Packit |
b802ec |
int transit;
|
|
Packit |
b802ec |
int saved[SAVED_PINGS];
|
|
Packit |
b802ec |
int saved_seq_offset;
|
|
Packit |
b802ec |
struct mplslen mpls;
|
|
Packit |
b802ec |
struct mplslen mplss[MAXPATH];
|
|
Packit |
b802ec |
};
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
struct sequence {
|
|
Packit |
b802ec |
int index;
|
|
Packit |
b802ec |
int transit;
|
|
Packit |
b802ec |
int saved_seq;
|
|
Packit |
b802ec |
struct timeval time;
|
|
Packit |
b802ec |
};
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static struct nethost host[MaxHost];
|
|
Packit |
b802ec |
static struct sequence sequence[MaxSequence];
|
|
Packit |
b802ec |
static struct packet_command_pipe_t packet_command_pipe;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
static struct sockaddr_storage sourcesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr_storage remotesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr_in6 *ssa6 =
|
|
Packit |
b802ec |
(struct sockaddr_in6 *) &sourcesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr_in6 *rsa6 =
|
|
Packit |
b802ec |
(struct sockaddr_in6 *) &remotesockaddr_struct;
|
|
Packit |
b802ec |
#else
|
|
Packit |
b802ec |
static struct sockaddr_in sourcesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr_in remotesockaddr_struct;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static struct sockaddr *sourcesockaddr =
|
|
Packit |
b802ec |
(struct sockaddr *) &sourcesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr *remotesockaddr =
|
|
Packit |
b802ec |
(struct sockaddr *) &remotesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr_in *ssa4 =
|
|
Packit |
b802ec |
(struct sockaddr_in *) &sourcesockaddr_struct;
|
|
Packit |
b802ec |
static struct sockaddr_in *rsa4 =
|
|
Packit |
b802ec |
(struct sockaddr_in *) &remotesockaddr_struct;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static ip_t *sourceaddress;
|
|
Packit |
b802ec |
static ip_t *remoteaddress;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
static char localaddr[INET6_ADDRSTRLEN];
|
|
Packit |
b802ec |
#else
|
|
Packit |
b802ec |
#ifndef INET_ADDRSTRLEN
|
|
Packit |
b802ec |
#define INET_ADDRSTRLEN 16
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
static char localaddr[INET_ADDRSTRLEN];
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static int batch_at = 0;
|
|
Packit |
b802ec |
static int numhosts = 10;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* return the number of microseconds to wait before sending the next
|
|
Packit |
b802ec |
ping */
|
|
Packit |
b802ec |
int calc_deltatime(
|
|
Packit |
b802ec |
float waittime)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
waittime /= numhosts;
|
|
Packit |
b802ec |
return 1000000 * waittime;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void save_sequence(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int index,
|
|
Packit |
b802ec |
int seq)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
display_rawxmit(ctl, index, seq);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
sequence[seq].index = index;
|
|
Packit |
b802ec |
sequence[seq].transit = 1;
|
|
Packit |
b802ec |
sequence[seq].saved_seq = ++host[index].xmit;
|
|
Packit |
b802ec |
memset(&sequence[seq].time, 0, sizeof(sequence[seq].time));
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].transit = 1;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (host[index].sent) {
|
|
Packit |
b802ec |
host[index].up = 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].sent = 1;
|
|
Packit |
b802ec |
net_save_xmit(index);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static int new_sequence(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int index)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
static int next_sequence = MinSequence;
|
|
Packit |
b802ec |
int seq;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
seq = next_sequence++;
|
|
Packit |
b802ec |
if (next_sequence >= MaxSequence) {
|
|
Packit |
b802ec |
next_sequence = MinSequence;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
save_sequence(ctl, index, seq);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return seq;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Attempt to find the host at a particular number of hops away */
|
|
Packit |
b802ec |
static void net_send_query(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int index,
|
|
Packit |
b802ec |
int packet_size)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int seq = new_sequence(ctl, index);
|
|
Packit |
b802ec |
int time_to_live = index + 1;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
send_probe_command(ctl, &packet_command_pipe, remoteaddress,
|
|
Packit |
b802ec |
sourceaddress, packetsize, seq, time_to_live);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* We got a return on something we sent out. Record the address and
|
|
Packit |
b802ec |
time. */
|
|
Packit |
b802ec |
static void net_process_ping(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int seq,
|
|
Packit |
b802ec |
struct mplslen *mpls,
|
|
Packit |
b802ec |
ip_t * addr,
|
|
Packit |
b802ec |
int totusec)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int index;
|
|
Packit |
b802ec |
int oldavg; /* usedByMin */
|
|
Packit |
b802ec |
int oldjavg; /* usedByMin */
|
|
Packit |
b802ec |
int i; /* usedByMin */
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
char addrcopy[sizeof(struct in6_addr)];
|
|
Packit |
b802ec |
#else
|
|
Packit |
b802ec |
char addrcopy[sizeof(struct in_addr)];
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
addrcpy((void *) &addrcopy, (char *) addr, ctl->af);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if ((seq < 0) || (seq >= MaxSequence)) {
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (!sequence[seq].transit) {
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
sequence[seq].transit = 0;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
index = sequence[seq].index;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (addrcmp((void *) &(host[index].addr),
|
|
Packit |
b802ec |
(void *) &ctl->unspec_addr, ctl->af) == 0) {
|
|
Packit |
b802ec |
/* should be out of if as addr can change */
|
|
Packit |
b802ec |
addrcpy((void *) &(host[index].addr), addrcopy, ctl->af);
|
|
Packit |
b802ec |
host[index].mpls = *mpls;
|
|
Packit |
b802ec |
display_rawhost(ctl, index, (void *) &(host[index].addr));
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* multi paths */
|
|
Packit |
b802ec |
addrcpy((void *) &(host[index].addrs[0]), addrcopy, ctl->af);
|
|
Packit |
b802ec |
host[index].mplss[0] = *mpls;
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
for (i = 0; i < MAXPATH;) {
|
|
Packit |
b802ec |
if (addrcmp
|
|
Packit |
b802ec |
((void *) &(host[index].addrs[i]), (void *) &addrcopy,
|
|
Packit |
b802ec |
ctl->af) == 0
|
|
Packit |
b802ec |
|| addrcmp((void *) &(host[index].addrs[i]),
|
|
Packit |
b802ec |
(void *) &ctl->unspec_addr, ctl->af) == 0) {
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
i++;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (addrcmp((void *) &(host[index].addrs[i]), addrcopy, ctl->af) !=
|
|
Packit |
b802ec |
0 && i < MAXPATH) {
|
|
Packit |
b802ec |
addrcpy((void *) &(host[index].addrs[i]), addrcopy, ctl->af);
|
|
Packit |
b802ec |
host[index].mplss[i] = *mpls;
|
|
Packit |
b802ec |
display_rawhost(ctl, index, (void *) &(host[index].addrs[i]));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].jitter = totusec - host[index].last;
|
|
Packit |
b802ec |
if (host[index].jitter < 0) {
|
|
Packit |
b802ec |
host[index].jitter = -host[index].jitter;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].last = totusec;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (host[index].returned < 1) {
|
|
Packit |
b802ec |
host[index].best = host[index].worst = host[index].gmean = totusec;
|
|
Packit |
b802ec |
host[index].avg = host[index].ssd = 0;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].jitter = host[index].jworst = host[index].jinta = 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (totusec < host[index].best) {
|
|
Packit |
b802ec |
host[index].best = totusec;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
if (totusec > host[index].worst) {
|
|
Packit |
b802ec |
host[index].worst = totusec;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (host[index].jitter > host[index].jworst) {
|
|
Packit |
b802ec |
host[index].jworst = host[index].jitter;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].returned++;
|
|
Packit |
b802ec |
oldavg = host[index].avg;
|
|
Packit |
b802ec |
host[index].avg += (totusec - oldavg + .0) / host[index].returned;
|
|
Packit |
b802ec |
host[index].ssd +=
|
|
Packit |
b802ec |
(totusec - oldavg + .0) * (totusec - host[index].avg);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
oldjavg = host[index].javg;
|
|
Packit |
b802ec |
host[index].javg +=
|
|
Packit |
b802ec |
(host[index].jitter - oldjavg) / host[index].returned;
|
|
Packit |
b802ec |
/* below algorithm is from rfc1889, A.8 */
|
|
Packit |
b802ec |
host[index].jinta +=
|
|
Packit |
b802ec |
host[index].jitter - ((host[index].jinta + 8) >> 4);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (host[index].returned > 1) {
|
|
Packit |
b802ec |
host[index].gmean =
|
|
Packit |
b802ec |
pow((double) host[index].gmean,
|
|
Packit |
b802ec |
(host[index].returned - 1.0) / host[index].returned)
|
|
Packit |
b802ec |
* pow((double) totusec, 1.0 / host[index].returned);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
host[index].sent = 0;
|
|
Packit |
b802ec |
host[index].up = 1;
|
|
Packit |
b802ec |
host[index].transit = 0;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_save_return(index, sequence[seq].saved_seq, totusec);
|
|
Packit |
b802ec |
display_rawping(ctl, index, totusec, seq);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
Invoked when the read pipe from the mtr-packet subprocess is readable.
|
|
Packit |
b802ec |
If we have received a complete reply, process it.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
void net_process_return(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
handle_command_replies(ctl, &packet_command_pipe, net_process_ping);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
ip_t *net_addr(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (ip_t *) & (host[at].addr);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
ip_t *net_addrs(
|
|
Packit |
b802ec |
int at,
|
|
Packit |
b802ec |
int i)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (ip_t *) & (host[at].addrs[i]);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void *net_mpls(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (struct mplslen *) &(host[at].mplss);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void *net_mplss(
|
|
Packit |
b802ec |
int at,
|
|
Packit |
b802ec |
int i)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (struct mplslen *) &(host[at].mplss[i]);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_loss(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if ((host[at].xmit - host[at].transit) == 0) {
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* times extra 1000 */
|
|
Packit |
b802ec |
return 1000 * (100 -
|
|
Packit |
b802ec |
(100.0 * host[at].returned /
|
|
Packit |
b802ec |
(host[at].xmit - host[at].transit)));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_drop(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].xmit - host[at].transit) - host[at].returned;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_last(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].last);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_best(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].best);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_worst(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].worst);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_avg(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].avg);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_gmean(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].gmean);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_stdev(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (host[at].returned > 1) {
|
|
Packit |
b802ec |
return (sqrt(host[at].ssd / (host[at].returned - 1.0)));
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
return (0);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_jitter(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].jitter);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_jworst(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].jworst);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_javg(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].javg);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_jinta(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (host[at].jinta);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_max(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int at;
|
|
Packit |
b802ec |
int max;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
max = 0;
|
|
Packit |
b802ec |
for (at = 0; at < ctl->maxTTL - 1; at++) {
|
|
Packit |
b802ec |
if (addrcmp((void *) &(host[at].addr),
|
|
Packit |
b802ec |
(void *) remoteaddress, ctl->af) == 0) {
|
|
Packit |
b802ec |
return at + 1;
|
|
Packit |
b802ec |
} else if (addrcmp((void *) &(host[at].addr),
|
|
Packit |
b802ec |
(void *) &ctl->unspec_addr, ctl->af) != 0) {
|
|
Packit |
b802ec |
max = at + 2;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return max;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_min(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return (ctl->fstTTL - 1);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_returned(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return host[at].returned;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_xmit(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return host[at].xmit;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_up(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return host[at].up;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
char *net_localaddr(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return localaddr;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void net_end_transit(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int at;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (at = 0; at < MaxHost; at++) {
|
|
Packit |
b802ec |
host[at].transit = 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_send_batch(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int n_unknown = 0, i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* randomized packet size and/or bit pattern if packetsize<0 and/or
|
|
Packit |
b802ec |
bitpattern<0. abs(packetsize) and/or abs(bitpattern) will be used
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
if (batch_at < ctl->fstTTL) {
|
|
Packit |
b802ec |
if (ctl->cpacketsize < 0) {
|
|
Packit |
b802ec |
/* Someone used a formula here that tried to correct for the
|
|
Packit |
b802ec |
"end-error" in "rand()". By "end-error" I mean that if you
|
|
Packit |
b802ec |
have a range for "rand()" that runs to 32768, and the
|
|
Packit |
b802ec |
destination range is 10000, you end up with 4 out of 32768
|
|
Packit |
b802ec |
0-2768's and only 3 out of 32768 for results 2769 .. 9999.
|
|
Packit |
b802ec |
As our detination range (in the example 10000) is much
|
|
Packit |
b802ec |
smaller (reasonable packet sizes), and our rand() range much
|
|
Packit |
b802ec |
larger, this effect is insignificant. Oh! That other formula
|
|
Packit |
b802ec |
didn't work. */
|
|
Packit |
b802ec |
packetsize =
|
|
Packit |
b802ec |
MINPACKET + rand() % (-ctl->cpacketsize - MINPACKET);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
packetsize = ctl->cpacketsize;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
if (ctl->bitpattern < 0) {
|
|
Packit |
b802ec |
ctl->bitpattern =
|
|
Packit |
b802ec |
-(int) (256 + 255 * (rand() / (RAND_MAX + 0.1)));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_send_query(ctl, batch_at, abs(packetsize));
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (i = ctl->fstTTL - 1; i < batch_at; i++) {
|
|
Packit |
b802ec |
if (addrcmp
|
|
Packit |
b802ec |
((void *) &(host[i].addr), (void *) &ctl->unspec_addr,
|
|
Packit |
b802ec |
ctl->af) == 0)
|
|
Packit |
b802ec |
n_unknown++;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* The second condition in the next "if" statement was added in mtr-0.56,
|
|
Packit |
b802ec |
but I don't remember why. It makes mtr stop skipping sections of unknown
|
|
Packit |
b802ec |
hosts. Removed in 0.65.
|
|
Packit |
b802ec |
If the line proves necessary, it should at least NOT trigger that line
|
|
Packit |
b802ec |
when host[i].addr == 0 */
|
|
Packit |
b802ec |
if ((addrcmp((void *) &(host[i].addr),
|
|
Packit |
b802ec |
(void *) remoteaddress, ctl->af) == 0))
|
|
Packit |
b802ec |
n_unknown = MaxHost; /* Make sure we drop into "we should restart" */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if ( /* success in reaching target */
|
|
Packit |
b802ec |
(addrcmp((void *) &(host[batch_at].addr),
|
|
Packit |
b802ec |
(void *) remoteaddress, ctl->af) == 0) ||
|
|
Packit |
b802ec |
/* fail in consecutive maxUnknown (firewall?) */
|
|
Packit |
b802ec |
(n_unknown > ctl->maxUnknown) ||
|
|
Packit |
b802ec |
/* or reach limit */
|
|
Packit |
b802ec |
(batch_at >= ctl->maxTTL - 1)) {
|
|
Packit |
b802ec |
numhosts = batch_at + 1;
|
|
Packit |
b802ec |
batch_at = ctl->fstTTL - 1;
|
|
Packit |
b802ec |
return 1;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
batch_at++;
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Ensure the interface address a valid address for our use */
|
|
Packit |
b802ec |
static void net_validate_interface_address(
|
|
Packit |
b802ec |
int address_family,
|
|
Packit |
b802ec |
char *interface_address)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (inet_pton(address_family, interface_address, sourceaddress) != 1) {
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "invalid local address");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (inet_ntop
|
|
Packit |
b802ec |
(address_family, sourceaddress, localaddr,
|
|
Packit |
b802ec |
sizeof(localaddr)) == NULL) {
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "invalid local address");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
Find the local address we will use to sent to the remote
|
|
Packit |
b802ec |
host by connecting a UDP socket and checking the address
|
|
Packit |
b802ec |
the socket is bound to.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
static void net_find_local_address(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int udp_socket;
|
|
Packit |
b802ec |
int addr_length;
|
|
Packit |
b802ec |
struct sockaddr_storage remote_sockaddr;
|
|
Packit |
b802ec |
struct sockaddr_in *remote4;
|
|
Packit |
b802ec |
struct sockaddr_in6 *remote6;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
udp_socket =
|
|
Packit |
b802ec |
socket(remotesockaddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
|
|
Packit |
b802ec |
if (udp_socket == -1) {
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "udp socket creation failed");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
We need to set the port to a non-zero value for the connect
|
|
Packit |
b802ec |
to succeed.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
if (remotesockaddr->sa_family == AF_INET6) {
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
addr_length = sizeof(struct sockaddr_in6);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
memcpy(&remote_sockaddr, rsa6, addr_length);
|
|
Packit |
b802ec |
remote6 = (struct sockaddr_in6 *) &remote_sockaddr;
|
|
Packit |
b802ec |
remote6->sin6_port = htons(1);
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
addr_length = sizeof(struct sockaddr_in);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
memcpy(&remote_sockaddr, rsa4, addr_length);
|
|
Packit |
b802ec |
remote4 = (struct sockaddr_in *) &remote_sockaddr;
|
|
Packit |
b802ec |
remote4->sin_port = htons(1);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (connect
|
|
Packit |
b802ec |
(udp_socket, (struct sockaddr *) &remote_sockaddr, addr_length)) {
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "udp socket connect failed");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (getsockname(udp_socket, sourcesockaddr, &addr_length)) {
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "local address determination failed");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
close(udp_socket);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_open(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
struct hostent *hostent)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int err;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Spawn the mtr-packet child process */
|
|
Packit |
b802ec |
err = open_command_pipe(ctl, &packet_command_pipe);
|
|
Packit |
b802ec |
if (err) {
|
|
Packit |
b802ec |
return err;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_reset(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
remotesockaddr->sa_family = hostent->h_addrtype;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
switch (hostent->h_addrtype) {
|
|
Packit |
b802ec |
case AF_INET:
|
|
Packit |
b802ec |
addrcpy((void *) &(rsa4->sin_addr), hostent->h_addr, AF_INET);
|
|
Packit |
b802ec |
sourceaddress = (ip_t *) & (ssa4->sin_addr);
|
|
Packit |
b802ec |
remoteaddress = (ip_t *) & (rsa4->sin_addr);
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
case AF_INET6:
|
|
Packit |
b802ec |
addrcpy((void *) &(rsa6->sin6_addr), hostent->h_addr, AF_INET6);
|
|
Packit |
b802ec |
sourceaddress = (ip_t *) & (ssa6->sin6_addr);
|
|
Packit |
b802ec |
remoteaddress = (ip_t *) & (rsa6->sin6_addr);
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
default:
|
|
Packit |
b802ec |
error(EXIT_FAILURE, 0, "net_open bad address type");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (ctl->InterfaceAddress) {
|
|
Packit |
b802ec |
net_validate_interface_address(ctl->af, ctl->InterfaceAddress);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
net_find_local_address();
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void net_reopen(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
struct hostent *addr)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int at;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (at = 0; at < MaxHost; at++) {
|
|
Packit |
b802ec |
memset(&host[at], 0, sizeof(host[at]));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
remotesockaddr->sa_family = addr->h_addrtype;
|
|
Packit |
b802ec |
addrcpy((void *) remoteaddress, addr->h_addr, addr->h_addrtype);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
switch (addr->h_addrtype) {
|
|
Packit |
b802ec |
case AF_INET:
|
|
Packit |
b802ec |
addrcpy((void *) &(rsa4->sin_addr), addr->h_addr, AF_INET);
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
case AF_INET6:
|
|
Packit |
b802ec |
addrcpy((void *) &(rsa6->sin6_addr), addr->h_addr, AF_INET6);
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
default:
|
|
Packit |
b802ec |
error(EXIT_FAILURE, 0, "net_reopen bad address type");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_reset(ctl);
|
|
Packit |
b802ec |
net_send_batch(ctl);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void net_reset(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
static struct nethost template = {
|
|
Packit |
b802ec |
.saved_seq_offset = 2 - SAVED_PINGS
|
|
Packit |
b802ec |
};
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int at, i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
batch_at = ctl->fstTTL - 1; /* above replacedByMin */
|
|
Packit |
b802ec |
numhosts = 10;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (i = 0; i < SAVED_PINGS; i++)
|
|
Packit |
b802ec |
template.saved[i] = -2;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (at = 0; at < MaxHost; at++) {
|
|
Packit |
b802ec |
memcpy(&(host[at]), &template, sizeof(template));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (at = 0; at < MaxSequence; at++) {
|
|
Packit |
b802ec |
sequence[at].transit = 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Close the pipe to the packet generator process, and kill the process */
|
|
Packit |
b802ec |
void net_close(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
close_command_pipe(&packet_command_pipe);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int net_waitfd(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return packet_command_pipe.read_fd;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int *net_saved_pings(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return host[at].saved;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void net_save_increment(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int at;
|
|
Packit |
b802ec |
for (at = 0; at < MaxHost; at++) {
|
|
Packit |
b802ec |
memmove(host[at].saved, host[at].saved + 1,
|
|
Packit |
b802ec |
(SAVED_PINGS - 1) * sizeof(int));
|
|
Packit |
b802ec |
host[at].saved[SAVED_PINGS - 1] = -2;
|
|
Packit |
b802ec |
host[at].saved_seq_offset += 1;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void net_save_xmit(
|
|
Packit |
b802ec |
int at)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (host[at].saved[SAVED_PINGS - 1] != -2)
|
|
Packit |
b802ec |
net_save_increment();
|
|
Packit |
b802ec |
host[at].saved[SAVED_PINGS - 1] = -1;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void net_save_return(
|
|
Packit |
b802ec |
int at,
|
|
Packit |
b802ec |
int seq,
|
|
Packit |
b802ec |
int ms)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int idx;
|
|
Packit |
b802ec |
idx = seq - host[at].saved_seq_offset;
|
|
Packit |
b802ec |
if ((idx < 0) || (idx >= SAVED_PINGS)) {
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
host[at].saved[idx] = ms;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Similar to inet_ntop but uses a sockaddr as it's argument. */
|
|
Packit |
b802ec |
static void sockaddrtop(
|
|
Packit |
b802ec |
struct sockaddr *saddr,
|
|
Packit |
b802ec |
char *strptr,
|
|
Packit |
b802ec |
size_t len)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct sockaddr_in *sa4;
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
struct sockaddr_in6 *sa6;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
switch (saddr->sa_family) {
|
|
Packit |
b802ec |
case AF_INET:
|
|
Packit |
b802ec |
sa4 = (struct sockaddr_in *) saddr;
|
|
Packit |
b802ec |
xstrncpy(strptr, inet_ntoa(sa4->sin_addr), len - 1);
|
|
Packit |
b802ec |
strptr[len - 1] = '\0';
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
case AF_INET6:
|
|
Packit |
b802ec |
sa6 = (struct sockaddr_in6 *) saddr;
|
|
Packit |
b802ec |
inet_ntop(sa6->sin6_family, &(sa6->sin6_addr), strptr, len);
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
default:
|
|
Packit |
b802ec |
error(0, 0, "sockaddrtop unknown address type");
|
|
Packit |
b802ec |
strptr[0] = '\0';
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Address comparison. */
|
|
Packit |
b802ec |
int addrcmp(
|
|
Packit |
b802ec |
char *a,
|
|
Packit |
b802ec |
char *b,
|
|
Packit |
b802ec |
int family)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int rc = -1;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
switch (family) {
|
|
Packit |
b802ec |
case AF_INET:
|
|
Packit |
b802ec |
rc = memcmp(a, b, sizeof(struct in_addr));
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
case AF_INET6:
|
|
Packit |
b802ec |
rc = memcmp(a, b, sizeof(struct in6_addr));
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return rc;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Address copy. */
|
|
Packit |
b802ec |
void addrcpy(
|
|
Packit |
b802ec |
char *a,
|
|
Packit |
b802ec |
char *b,
|
|
Packit |
b802ec |
int family)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
switch (family) {
|
|
Packit |
b802ec |
case AF_INET:
|
|
Packit |
b802ec |
memcpy(a, b, sizeof(struct in_addr));
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
case AF_INET6:
|
|
Packit |
b802ec |
memcpy(a, b, sizeof(struct in6_addr));
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* for GTK frontend */
|
|
Packit |
b802ec |
void net_harvest_fds(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
fd_set writefd;
|
|
Packit |
b802ec |
int maxfd = 0;
|
|
Packit |
b802ec |
struct timeval tv;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
FD_ZERO(&writefd);
|
|
Packit |
b802ec |
tv.tv_sec = 0;
|
|
Packit |
b802ec |
tv.tv_usec = 0;
|
|
Packit |
b802ec |
select(maxfd, NULL, &writefd, NULL, &tv;;
|
|
Packit |
b802ec |
}
|