1
0
mirror of https://github.com/dennypage/dpinger.git synced 2024-05-19 06:50:01 +00:00

16 Commits
v1.0 ... v1.5

Author SHA1 Message Date
Denny Page
4a57f2584c Add -d option to allow setting data payload length 2016-01-30 21:18:44 -08:00
Denny Page
afbde05bcb Make the standard deviation calculation a little easier on the eyes 2016-01-30 20:44:10 -08:00
Denny Page
85d345f47f Fix defective parsing of time values with 's' suffix 2016-01-14 20:56:46 -08:00
dennypage
e0a0ae14f9 Merge pull request #19 from pfsense/ignore_files
Ignore dpinger.full, dpinger.debug and vim swap files
2016-01-04 10:09:13 -08:00
Renato Botelho
87cd4b6e3b Ignore dpinger.full, dpinger.debug and vim swap files 2016-01-04 10:16:50 -02:00
Denny Page
919fad77a2 Change default time period to 30s and relax default loss interval to 5x send interval to address nagging low level loss reports
Add usage note about loss percentage reporting and calculation
2015-12-30 12:06:54 -08:00
dennypage
2e0430edea Merge pull request #18 from pfsense/fix_build_9
Initialize pidfile_fd to silence FreeBSD 9 warning
2015-12-30 10:39:29 -08:00
Renato Botelho
31432284dc Initialize pidfile_fd to silence FreeBSD 9 warning 2015-12-30 09:15:39 -02:00
Denny Page
e1d00b4210 Set close on exec for all file descriptors 2015-12-29 14:20:06 -08:00
Denny Page
1ec615486b Temporary to allow building on old systems (FreeBSD 9.3, Linux 2.6.26) 2015-12-29 11:28:14 -08:00
Denny Page
6789e90a38 Set close on exec flag if report file is explicit 2015-12-29 10:57:28 -08:00
Denny Page
1b2e8e784b Merge branch 'master' of https://github.com/dennypage/dpinger 2015-12-28 12:50:39 -08:00
Denny Page
00229f717d Enable support for IPv6 scope ids
Relax default loss interval to 4x send interval
2015-12-28 12:47:25 -08:00
dennypage
4b82af813b Add identifier usage example 2015-12-23 23:03:33 -08:00
dennypage
feb01fa2d3 Add output and alert description 2015-12-21 14:25:27 -08:00
Denny Page
dcf1d22322 Include identifier and dest_str in all icmp packet related logging (from Phil Davis) 2015-12-20 21:27:52 -08:00
3 changed files with 234 additions and 132 deletions

3
.gitignore vendored
View File

@@ -1,2 +1,5 @@
/dpinger
/dpinger.debug
/dpinger.full
/dpinger.o
/.*.swp

View File

@@ -1,9 +1,26 @@
# dpinger
dpinger is a daemon for continous monitoring of latency and loss on a network connection. It is
dpinger is a daemon for continuous monitoring of latency and loss on a network connection. It is
intended for use by firewalls to monitor link health, as well as for providing information to
various monitoring systems such as Cacti, Nagios, Zabbix, etc.
The output of dpinger can either be file or socket based, and consists of three numbers:
<Average Latency in μs> <Standard Deviation in μs> <Percentage of Loss>
dpinger also provides for invocation of a command based upon threshold values
for Average Latency or Percentage of Loss. Arguments to the command are:
<Target IP> <Alarm on/off> <Average Latency> <Standard Deviation> <Percentage of Loss>
In addition to command invocation, dpinger can also log alerts via syslog.
If several instances of dpinger are being used to monitor different targets, or the same target
with different source addresses, etc., an Identifier can be added to the output to identify
which instance of dpinger is the source. This is particularly useful with syslog.
<br>
Usage examples:
dpinger -t 300s -r 60s 192.168.0.1 >> /tmp/dpinger.out
@@ -38,3 +55,9 @@ Produce a report every 60 seconds and append it to /tmp/dpinger.out.
Monitor IP address fe80::1 for latency and loss. Send echo requests every 200 milliseconds.
Make current status available on demand via a Unix domain socket /tmp/igb1.status. Record
process id in /run/dpinger.
dpinger -S -i Comcast -s 5s -t 600s -r 0 -L 10% -p /run/dpinger 8.8.8.8
Monitor IP address 8.8.8.8 for latency and loss. Send echo requests every five seconds and
average results over 10 minutes. Log alerts via syslog including identifier string "Comcast"
if average loss exceeds 10 percent. Record process id in /run/dpinger.

338
dpinger.c
View File

@@ -1,6 +1,6 @@
//
// Copyright (c) 2015, Denny Page
// Copyright (c) 2015-2016, Denny Page
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,8 @@
#include <fcntl.h>
#include <signal.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
@@ -50,6 +52,18 @@
#include <pthread.h>
#include <syslog.h>
// TODO:
//
// After December 31st, 2016, review use of fcntl() for setting non blocking
// and close on exec. It would be preferable to use accept4(), SOCK_CLOEXEC
// and SOCK_NONBLOCK. These are currently avoided to allow use on older
// systems such as FreeBSD 9.3, Linux 2.6.26.
// For Linux accept4() currently requires defining _GNU_SOURCE which we would
// like to avoid.
// For FreeBSD, these definitions were introduced with FreeBSD 10.0 and are
// not present in 9.3 which is supported through 2016.
// Who we are
static const char * progname;
@@ -62,10 +76,11 @@ static unsigned int flag_rewind = 0;
static unsigned int flag_syslog = 0;
// String representation of target
static char dest_str[INET6_ADDRSTRLEN];
#define ADDR_STR_MAX (INET6_ADDRSTRLEN + IF_NAMESIZE + 1)
static char dest_str[ADDR_STR_MAX];
// Time period over which we are averaging results in ms
static unsigned long time_period_msec = 25000;
static unsigned long time_period_msec = 30000;
// Interval between sends in ms
static unsigned long send_interval_msec = 250;
@@ -160,8 +175,16 @@ typedef struct
uint16_t sequence;
} icmphdr_t;
// Echo request header for sendto
static icmphdr_t echo_request;
// Echo request/reply packet buffers
#define IPV4_ICMP_DATA_MAX (IP_MAXPACKET - sizeof(struct ip) - sizeof(icmphdr_t))
#define IPV6_ICMP_DATA_MAX (IP_MAXPACKET - sizeof(icmphdr_t))
#define PACKET_BUFLEN (IP_MAXPACKET + 256)
unsigned long echo_data_len = 0;
static unsigned int echo_request_len = sizeof(icmphdr_t);
static unsigned int echo_reply_len = IP_MAXPACKET;
static icmphdr_t * echo_request;
static void * echo_reply;
// Echo id and Sequence information
static uint16_t echo_id;
@@ -304,9 +327,10 @@ send_thread(
int r;
// Set up our echo request packet
echo_request.type = echo_request_type;
echo_request.code = 0;
echo_request.id = echo_id;
memset(echo_request, 0, echo_request_len);
echo_request->type = echo_request_type;
echo_request->code = 0;
echo_request->id = echo_id;
// Set up the timespec for nanosleep
sleeptime.tv_sec = send_interval_msec / 1000;
@@ -321,20 +345,20 @@ send_thread(
}
// Set sequence number and checksum
echo_request.sequence = htons(next_sequence);
echo_request.cksum = 0;
echo_request.cksum = cksum((uint16_t *) &echo_request, sizeof(icmphdr_t));
echo_request->sequence = htons(next_sequence);
echo_request->cksum = 0;
echo_request->cksum = cksum((uint16_t *) echo_request, sizeof(icmphdr_t));
array[next_slot].status = PACKET_STATUS_EMPTY;
sched_yield();
clock_gettime(CLOCK_MONOTONIC, &array[next_slot].time_sent);
array[next_slot].status = PACKET_STATUS_SENT;
r = sendto(send_sock, &echo_request, sizeof(icmphdr_t), 0, (struct sockaddr *) &dest_addr, dest_addr_len);
r = sendto(send_sock, echo_request, echo_request_len, 0, (struct sockaddr *) &dest_addr, dest_addr_len);
if (r == -1)
{
logger("sendto error: %d\n", errno);
logger("%s%s: sendto error: %d\n", identifier, dest_str, errno);
}
array[next_slot].status = PACKET_STATUS_SENT;
next_slot = (next_slot + 1) % array_size;
next_sequence = (next_sequence + 1) % sequence_limit;
@@ -352,10 +376,9 @@ static void *
recv_thread(
void * arg)
{
char packet[1024];
unsigned int packet_len;
struct sockaddr_storage src_addr;
socklen_t src_addr_len;
unsigned int len;
icmphdr_t * icmp;
struct timespec now;
unsigned int array_slot;
@@ -363,10 +386,10 @@ recv_thread(
while (1)
{
src_addr_len = sizeof(src_addr);
packet_len = recvfrom(recv_sock, &packet, sizeof(packet), 0, (struct sockaddr *) &src_addr, &src_addr_len);
if (packet_len == (unsigned int) -1)
len = recvfrom(recv_sock, echo_reply, echo_reply_len, 0, (struct sockaddr *) &src_addr, &src_addr_len);
if (len == (unsigned int) -1)
{
logger("recvfrom error: %d\n", errno);
logger("%s%s: recvfrom error: %d\n", identifier, dest_str, errno);
continue;
}
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -377,27 +400,27 @@ recv_thread(
size_t ip_len;
// With IPv4, we get the entire IP packet
if (packet_len < sizeof(struct ip))
if (len < sizeof(struct ip))
{
logger("received packet too small for IP header\n");
logger("%s%s: received packet too small for IP header\n", identifier, dest_str);
continue;
}
ip = (void *) packet;
ip = echo_reply;
ip_len = ip->ip_hl << 2;
icmp = (void *) (packet + ip_len);
packet_len -= ip_len;
icmp = (void *) ip + ip_len;
len -= ip_len;
}
else
{
// With IPv6, we just get the ICMP payload
icmp = (void *) (packet);
icmp = echo_reply;
}
// This should never happen
if (packet_len < sizeof(icmphdr_t))
if (len < sizeof(icmphdr_t))
{
logger("received packet too small for ICMP header\n");
logger("%s%s: received packet too small for ICMP header\n", identifier, dest_str);
continue;
}
@@ -410,7 +433,7 @@ recv_thread(
array_slot = ntohs(icmp->sequence) % array_size;
if (array[array_slot].status == PACKET_STATUS_RECEIVED)
{
logger("duplicate echo reply received\n");
logger("%s%s: duplicate echo reply received\n", identifier, dest_str);
continue;
}
@@ -435,6 +458,7 @@ report(
struct timespec now;
unsigned long packets_received = 0;
unsigned long packets_lost = 0;
unsigned long latency_usec = 0;
unsigned long total_latency_usec = 0;
unsigned long long total_latency_usec2 = 0;
unsigned int slot;
@@ -448,8 +472,9 @@ report(
if (array[slot].status == PACKET_STATUS_RECEIVED)
{
packets_received++;
total_latency_usec += array[slot].latency_usec;
total_latency_usec2 += array[slot].latency_usec * array[slot].latency_usec;
latency_usec = array[slot].latency_usec;
total_latency_usec += latency_usec;
total_latency_usec2 += latency_usec * latency_usec;
}
else if (array[slot].status == PACKET_STATUS_SENT &&
ts_elapsed_usec(&array[slot].time_sent, &now) > loss_interval_usec)
@@ -462,10 +487,12 @@ report(
if (packets_received)
{
*average_latency_usec = total_latency_usec / packets_received;
unsigned long avg = total_latency_usec / packets_received;
unsigned long long avg2 = total_latency_usec2 / packets_received;
// sqrt( (sum(rtt^2) / packets) - (sum(rtt) / packets)^2)
*latency_deviation = llsqrt((total_latency_usec2 / packets_received) - (total_latency_usec / packets_received) * (total_latency_usec / packets_received));
// stddev = sqrt((sum(rtt^2) / packets) - (sum(rtt) / packets)^2)
*average_latency_usec = avg;
*latency_deviation = llsqrt(avg2 - (avg * avg));
}
else
{
@@ -662,6 +689,7 @@ usocket_thread(
while (1)
{
sock_fd = accept(usocket_fd, NULL, NULL);
(void) fcntl(sock_fd, F_SETFL, FD_CLOEXEC);
(void) fcntl(sock_fd, F_SETFL, fcntl(sock_fd, F_GETFL, 0) | O_NONBLOCK);
report(&average_latency_usec, &latency_deviation, &average_loss_percent);
@@ -715,7 +743,7 @@ get_time_arg_msec(
else if (*suffix == 's')
{
// Seconds
*value *= 1000;
t *= 1000;
suffix++;
}
@@ -758,6 +786,41 @@ get_percent_arg(
}
//
// Decode a byte length argument
//
static int
get_length_arg(
const char * arg,
unsigned long * value)
{
unsigned long t;
char * suffix;
t = strtoul(arg, &suffix, 10);
if (*suffix == 'b')
{
// Bytes
suffix++;
}
else if (*suffix == 'k')
{
// Kilobytes
t *= 1024;
suffix++;
}
// Garbage in the number?
if (*suffix != 0)
{
return 1;
}
*value = t;
return 0;
}
//
// Output usage
//
@@ -765,16 +828,17 @@ static void
usage(void)
{
fprintf(stderr, "Usage:\n");
fprintf(stderr, " %s [-f] [-R] [-S] [-B bind_addr] [-s send_interval] [-l loss_interval] [-t time_period] [-r report_interval] [-o output_file] [-A alert_interval] [-D latency_alarm] [-L loss_alarm] [-C alert_cmd] [-i identifier] [-u usocket] [-p pidfile] dest_addr\n\n", progname);
fprintf(stderr, " %s [-f] [-R] [-S] [-B bind_addr] [-s send_interval] [-l loss_interval] [-t time_period] [-r report_interval] [-d data_length] [-o output_file] [-A alert_interval] [-D latency_alarm] [-L loss_alarm] [-C alert_cmd] [-i identifier] [-u usocket] [-p pidfile] dest_addr\n\n", progname);
fprintf(stderr, " options:\n");
fprintf(stderr, " -f run in foreground\n");
fprintf(stderr, " -R rewind output file between reports\n");
fprintf(stderr, " -S log warnings via syslog\n");
fprintf(stderr, " -B bind (source) address\n");
fprintf(stderr, " -s time interval between echo requests (default 250ms)\n");
fprintf(stderr, " -l time interval before packets are treated as lost (default 2x send interval)\n");
fprintf(stderr, " -t time period over which results are averaged (default 25s)\n");
fprintf(stderr, " -l time interval before packets are treated as lost (default 5x send interval)\n");
fprintf(stderr, " -t time period over which results are averaged (default 30s)\n");
fprintf(stderr, " -r time interval between reports (default 1s)\n");
fprintf(stderr, " -d data length (default 0)\n");
fprintf(stderr, " -o output file for reports (default stdout)\n");
fprintf(stderr, " -A time interval between alerts (default 1s)\n");
fprintf(stderr, " -D time threshold for latency alarm (default none)\n");
@@ -784,11 +848,13 @@ usage(void)
fprintf(stderr, " -u unix socket name for polling\n");
fprintf(stderr, " -p process id file name\n\n");
fprintf(stderr, " notes:\n");
fprintf(stderr, " IP addresses can be in either IPv4 or IPv6 format\n\n");
fprintf(stderr, " time values can be expressed with a suffix of 'm' (milliseconds) or 's' (seconds)\n");
fprintf(stderr, " if no suffix is specified, milliseconds is the default\n\n");
fprintf(stderr, " IP addresses can be in either IPv4 or IPv6 format\n\n");
fprintf(stderr, " the output format is \"latency_avg latency_stddev loss_pct\"\n");
fprintf(stderr, " latency values are output in microseconds\n\n");
fprintf(stderr, " latency values are output in microseconds\n");
fprintf(stderr, " loss percentage is reported in whole numbers of 0-100\n");
fprintf(stderr, " resolution of loss calculation is: 100 * send_interval / (time_period - loss_interval)\n\n");
fprintf(stderr, " the alert_cmd is invoked as \"alert_cmd dest_addr alarm_flag latency_avg loss_avg\"\n");
fprintf(stderr, " alarm_flag is set to 1 if either latency or loss is in alarm state\n");
fprintf(stderr, " alarm_flag will return to 0 when both have have cleared alarm state\n\n");
@@ -824,8 +890,8 @@ parse_args(
int argc,
char * const argv[])
{
struct in_addr addr;
struct in6_addr addr6;
struct addrinfo hint;
struct addrinfo * addr_info;
const char * dest_arg;
const char * bind_arg = NULL;
size_t len;
@@ -834,7 +900,7 @@ parse_args(
progname = argv[0];
while((opt = getopt(argc, argv, "fRSB:s:l:t:r:o:A:D:L:C:i:u:p:")) != -1)
while((opt = getopt(argc, argv, "fRSB:s:l:t:r:d:o:A:D:L:C:i:u:p:")) != -1)
{
switch (opt)
{
@@ -886,6 +952,14 @@ parse_args(
}
break;
case 'd':
r = get_length_arg(optarg, &echo_data_len);
if (r)
{
fatal("invalid data length %s\n", optarg);
}
break;
case 'o':
report_name = optarg;
break;
@@ -904,6 +978,7 @@ parse_args(
{
fatal("invalid latency alarm threshold %s\n", optarg);
}
latency_alarm_threshold_usec = latency_alarm_threshold_msec * 1000;
break;
case 'L':
@@ -916,7 +991,7 @@ parse_args(
case 'C':
alert_cmd_offset = strlen(optarg);
alert_cmd = malloc (alert_cmd_offset + OUTPUT_MAX);
alert_cmd = malloc(alert_cmd_offset + OUTPUT_MAX);
if (alert_cmd == NULL)
{
fatal("malloc of alert command buffer failed\n");
@@ -956,6 +1031,7 @@ parse_args(
usage();
fatal(NULL);
}
dest_arg = argv[optind];
// Ensure we have something to do: at least one of alarm, report, socket
if (report_interval_msec == 0 && latency_alarm_threshold_msec == 0 && loss_alarm_threshold_percent == 0 && usocket_name == NULL)
@@ -963,9 +1039,6 @@ parse_args(
fatal("no activity enabled\n");
}
// Destination address
dest_arg = argv[optind];
// Ensure we have something to average over
if (time_period_msec < send_interval_msec)
{
@@ -979,61 +1052,71 @@ parse_args(
fatal("ratio of time period to send interval cannot exceed 65536:1\n");
}
// Check for an IPv4 address
r = inet_pton(AF_INET, dest_arg, &addr);
if (r)
// Check destination address
memset(&hint, 0, sizeof(struct addrinfo));
hint.ai_flags = AI_NUMERICHOST;
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_RAW;
r = getaddrinfo(dest_arg, NULL, &hint, &addr_info);
if (r != 0)
{
struct sockaddr_in * dest = (struct sockaddr_in *) &dest_addr;
dest->sin_family = AF_INET;
dest->sin_addr = addr;
dest_addr_len = sizeof(struct sockaddr_in);
if (bind_arg)
{
r = inet_pton(AF_INET, bind_arg, &addr);
if (r == 0)
{
fatal("Invalid bind IP address %s\n", bind_arg);
}
struct sockaddr_in * bind4 = (struct sockaddr_in *) &bind_addr;
bind4->sin_family = AF_INET;
bind4->sin_addr = addr;
bind_addr_len = sizeof(struct sockaddr_in);
}
fatal("invalid destination IP address %s\n", dest_arg);
}
else
if (addr_info->ai_family == AF_INET6)
{
// Perhaps it's an IPv6 address?
r = inet_pton(AF_INET6, dest_arg, &addr6);
if (r == 0)
{
fatal("Invalid destination IP address %s\n", dest_arg);
}
struct sockaddr_in6 * dest6 = (struct sockaddr_in6 *) &dest_addr;
dest6->sin6_family = AF_INET6;
dest6->sin6_addr = addr6;
dest_addr_len = sizeof(struct sockaddr_in6);
af_family = AF_INET6;
ip_proto = IPPROTO_ICMPV6;
echo_request_type = ICMP6_ECHO_REQUEST;
echo_reply_type = ICMP6_ECHO_REPLY;
}
else if (addr_info->ai_family != AF_INET)
{
fatal("invalid destination IP address %s\n", dest_arg);
}
if (bind_arg)
dest_addr_len = addr_info->ai_addrlen;
memcpy(&dest_addr, addr_info->ai_addr, dest_addr_len);
freeaddrinfo(addr_info);
// Check bind address
if (bind_arg)
{
// Address family must match
hint.ai_family = af_family;
r = getaddrinfo(bind_arg, NULL, &hint, &addr_info);
if (r != 0)
{
r = inet_pton(AF_INET6, bind_arg, &addr6);
if (r == 0)
{
fatal("Invalid source IP address %s\n", bind_arg);
}
struct sockaddr_in6 * bind6 = (struct sockaddr_in6 *) &bind_addr;
bind6->sin6_family = AF_INET6;
bind6->sin6_addr = addr6;
bind_addr_len = sizeof(struct sockaddr_in6);
fatal("invalid bind IP address %s\n", bind_arg);
}
bind_addr_len = addr_info->ai_addrlen;
memcpy(&bind_addr, addr_info->ai_addr, bind_addr_len);
freeaddrinfo(addr_info);
}
// Check requested data length
if (echo_data_len)
{
if (af_family == AF_INET)
{
if (echo_data_len > IPV4_ICMP_DATA_MAX)
{
fatal("data length too large for IPv4 - maximum is %u bytes\n", IPV4_ICMP_DATA_MAX);
}
}
else
{
if (echo_data_len > IPV6_ICMP_DATA_MAX)
{
fatal("data length too large for IPv6 - maximum is %u bytes\n", IPV6_ICMP_DATA_MAX);
}
}
echo_request_len += echo_data_len;
}
}
@@ -1046,12 +1129,11 @@ main(
int argc,
char *argv[])
{
char bind_str[INET6_ADDRSTRLEN] = "(none)";
const void * addr;
const char * p;
int pidfile_fd;
char bind_str[ADDR_STR_MAX] = "(none)";
int pidfile_fd = -1;
pthread_t thread;
struct sigaction act;
int buflen = PACKET_BUFLEN;
int r;
// Handle command line args
@@ -1064,12 +1146,17 @@ main(
perror("socket");
fatal("cannot create send socket\n");
}
(void) fcntl(send_sock, F_SETFL, FD_CLOEXEC);
(void) setsockopt(send_sock, SOL_SOCKET, SO_SNDBUF, &buflen, sizeof(buflen));
recv_sock = socket(af_family, SOCK_RAW, ip_proto);
if (recv_sock == -1)
{
perror("socket");
fatal("cannot create recv socket\n");
}
(void) fcntl(recv_sock, F_SETFL, FD_CLOEXEC);
(void) setsockopt(recv_sock, SOL_SOCKET, SO_RCVBUF, &buflen, sizeof(buflen));
// Bind our sockets to an address if requested
if (bind_addr_len)
@@ -1095,7 +1182,7 @@ main(
// Create report file
if (report_name)
{
report_fd = open(report_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
report_fd = open(report_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
if (report_fd == -1)
{
perror("open");
@@ -1117,12 +1204,13 @@ main(
fatal("socket name too large\n");
}
usocket_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
usocket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (usocket_fd == -1)
{
perror("socket");
fatal("cannot create unix domain socket\n");
}
(void) fcntl(usocket_fd, F_SETFL, FD_CLOEXEC);
(void) unlink(usocket_name);
@@ -1154,7 +1242,7 @@ main(
// Create pid file
if (pidfile_name)
{
pidfile_fd = open(pidfile_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
pidfile_fd = open(pidfile_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
if (pidfile_fd == -1)
{
perror("open");
@@ -1190,7 +1278,7 @@ main(
sigaction(SIGINT, &act, NULL);
// Write pid file
if (pidfile_name)
if (pidfile_fd != -1)
{
char buf[64];
int len;
@@ -1208,7 +1296,7 @@ main(
fatal("error writing pidfile\n");
}
r= close(pidfile_fd);
r = close(pidfile_fd);
if (r == -1)
{
perror("close");
@@ -1224,54 +1312,42 @@ main(
fatal("calloc of packet array failed\n");
}
// Allocate the echo request/reply packet buffers
echo_request = (icmphdr_t *) malloc(echo_request_len);
echo_reply = malloc(echo_reply_len);
if (echo_request == NULL || echo_reply == NULL)
{
fatal("malloc of packet buffers failed\n");
}
// Set the default loss interval
if (loss_interval_msec == 0)
{
loss_interval_msec = send_interval_msec * 2;
loss_interval_msec = send_interval_msec * 5;
}
loss_interval_usec = loss_interval_msec * 1000;
// Log our parameters
if (af_family == AF_INET)
// Log our general parameters
r = getnameinfo((struct sockaddr *) &dest_addr, dest_addr_len, dest_str, sizeof(dest_str), NULL, 0, NI_NUMERICHOST);
if (r != 0)
{
addr = (const void *) &((struct sockaddr_in *) &dest_addr)->sin_addr;
}
else
{
addr = (const void *) &((struct sockaddr_in6 *) &dest_addr)->sin6_addr;
}
p = inet_ntop(af_family, addr, dest_str, sizeof(dest_str));
if (p == NULL)
{
fatal("inet_ntop of destination address failed\n");
fatal("getnameinfo of destination address failed\n");
}
if (bind_addr_len)
{
if (af_family == AF_INET)
r = getnameinfo((struct sockaddr *) &bind_addr, bind_addr_len, bind_str, sizeof(bind_str), NULL, 0, NI_NUMERICHOST);
if (r != 0)
{
addr = (const void *) &((struct sockaddr_in *) &bind_addr)->sin_addr;
}
else
{
addr = (const void *) &((struct sockaddr_in6 *) &bind_addr)->sin6_addr;
}
p = inet_ntop(af_family, addr, bind_str, sizeof(bind_str));
if (p == NULL)
{
fatal("inet_ntop of bind address failed\n");
fatal("getnameinfo of bind address failed\n");
}
}
// Log our general parameters
logger("send_interval %lums loss_interval %lums time_period %lums report_interval %lums alert_interval %lums latency_alarm %lums loss_alarm %lu%% dest_addr %s bind_addr %s identifier \"%s\"\n",
send_interval_msec, loss_interval_msec, time_period_msec, report_interval_msec,
logger("send_interval %lums loss_interval %lums time_period %lums report_interval %lums data_len %lu alert_interval %lums latency_alarm %lums loss_alarm %lu%% dest_addr %s bind_addr %s identifier \"%s\"\n",
send_interval_msec, loss_interval_msec, time_period_msec, report_interval_msec, echo_data_len,
alert_interval_msec, latency_alarm_threshold_msec, loss_alarm_threshold_percent,
dest_str, bind_str, identifier);
// Convert loss interval and alarm threshold to microseconds
loss_interval_usec = loss_interval_msec * 1000;
latency_alarm_threshold_usec = latency_alarm_threshold_msec * 1000;
// Set my echo id
echo_id = htons(getpid());