"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/fping.c" between
fping-5.0.tar.gz and fping-5.1.tar.gz

About: fping quickly ping N number of hosts to determine their reachability without flooding the network.

fping.c  (fping-5.0):fping.c  (fping-5.1)
skipping to change at line 63 skipping to change at line 63
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif /* HAVE_STDLIB_H */ #endif /* HAVE_STDLIB_H */
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#if HAVE_SYS_FILE_H #if HAVE_SYS_FILE_H
#include <sys/file.h> #include <sys/file.h>
#endif /* HAVE_SYS_FILE_H */ #endif /* HAVE_SYS_FILE_H */
#ifdef IPV6 #ifdef IPV6
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
skipping to change at line 125 skipping to change at line 123
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
/*** Constants ***/ /*** Constants ***/
#if HAVE_SO_TIMESTAMPNS #if HAVE_SO_TIMESTAMPNS
#define CLOCKID CLOCK_REALTIME #define CLOCKID CLOCK_REALTIME
#endif #endif
/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positiv
e point and can not be use
* see github PR #217
*/
#if !defined(CLOCKID) #if !defined(CLOCKID)
#if defined(CLOCK_MONOTONIC) #if defined(CLOCK_MONOTONIC) && !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
#define CLOCKID CLOCK_MONOTONIC #define CLOCKID CLOCK_MONOTONIC
#else #else
#define CLOCKID CLOCK_REALTIME #define CLOCKID CLOCK_REALTIME
#endif #endif
#endif #endif
/*** Ping packet defines ***/ /*** Ping packet defines ***/
#define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */ #define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */
#define SIZE_IP_HDR 40 #define SIZE_IP_HDR 40
skipping to change at line 400 skipping to change at line 401
void print_warning(char* fmt, ...); void print_warning(char* fmt, ...);
int addr_cmp(struct sockaddr* a, struct sockaddr* b); int addr_cmp(struct sockaddr* a, struct sockaddr* b);
void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time); void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time);
void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time); void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time);
struct event *host_get_timeout_event(HOST_ENTRY *h, int index); struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency); void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
void update_current_time(); void update_current_time();
/************************************************************ /************************************************************
Function: p_setsockopt
*************************************************************
Inputs: p_uid: privileged uid. Others as per setsockopt(2)
Description:
Elevates privileges to p_uid when required, calls
setsockopt, and drops privileges back.
************************************************************/
int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname,
const void *optval, socklen_t optlen)
{
const uid_t saved_uid = geteuid();
int res;
if (p_uid != saved_uid && seteuid(p_uid)) {
perror("cannot elevate privileges for setsockopt");
}
res = setsockopt(sockfd, level, optname, optval, optlen);
if (p_uid != saved_uid && seteuid(saved_uid)) {
perror("fatal error: could not drop privileges after setsockopt");
/* continuing would be a security hole */
exit(4);
}
return res;
}
/************************************************************
Function: main Function: main
************************************************************* *************************************************************
Inputs: int argc, char** argv Inputs: int argc, char** argv
Description: Description:
Main program entry point Main program entry point
************************************************************/ ************************************************************/
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int c; int c;
uid_t uid; const uid_t suid = geteuid();
int tos = 0; int tos = 0;
struct optparse optparse_state; struct optparse optparse_state;
#ifdef USE_SIGACTION #ifdef USE_SIGACTION
struct sigaction act; struct sigaction act;
#endif #endif
/* pre-parse -h/--help, so that we also can output help information /* pre-parse -h/--help, so that we also can output help information
* without trying to open the socket, which might fail */ * without trying to open the socket, which might fail */
prog = argv[0]; prog = argv[0];
if(argc == 2 && ( strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0 )) { if(argc == 2 && ( strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0 )) {
skipping to change at line 451 skipping to change at line 488
if (strstr(prog, "fping6")) { if (strstr(prog, "fping6")) {
hints_ai_family = AF_INET6; hints_ai_family = AF_INET6;
} }
#endif #endif
memset(&src_addr, 0, sizeof(src_addr)); memset(&src_addr, 0, sizeof(src_addr));
#ifdef IPV6 #ifdef IPV6
memset(&src_addr6, 0, sizeof(src_addr6)); memset(&src_addr6, 0, sizeof(src_addr6));
#endif #endif
if ((uid = getuid())) { if (!suid && suid != getuid()) {
/* drop privileges */ /* *temporarily* drop privileges */
if (setuid(getuid()) == -1) if (seteuid(getuid()) == -1)
perror("cannot setuid"); perror("cannot setuid");
} }
optparse_init(&optparse_state, argv); optparse_init(&optparse_state, argv);
ident4 = ident6 = htons(getpid() & 0xFFFF); ident4 = ident6 = htons(getpid() & 0xFFFF);
verbose_flag = 1; verbose_flag = 1;
backoff_flag = 1; backoff_flag = 1;
opterr = 1; opterr = 1;
/* get command line options */ /* get command line options */
skipping to change at line 513 skipping to change at line 550
{ NULL, 'z', OPTPARSE_REQUIRED }, { NULL, 'z', OPTPARSE_REQUIRED },
#endif #endif
{ 0, 0, 0 } { 0, 0, 0 }
}; };
float opt_value_float; float opt_value_float;
while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) { while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) {
switch (c) { switch (c) {
case '4': case '4':
#ifdef IPV6 #ifdef IPV6
if (hints_ai_family != AF_UNSPEC) { if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
fprintf(stderr, "%s: can't specify both -4 and -6\n", prog); fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
exit(1); exit(1);
} }
hints_ai_family = AF_INET; hints_ai_family = AF_INET;
#endif #endif
break; break;
case '6': case '6':
#ifdef IPV6 #ifdef IPV6
if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET6) { if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET6) {
fprintf(stderr, "%s: can't specify both -4 and -6\n", prog); fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
skipping to change at line 743 skipping to change at line 780
src_addr6_set = 1; src_addr6_set = 1;
break; break;
} }
#endif #endif
fprintf(stderr, "%s: can't parse source address: %s\n", prog, optpar se_state.optarg); fprintf(stderr, "%s: can't parse source address: %s\n", prog, optpar se_state.optarg);
exit(1); exit(1);
case 'I': case 'I':
#ifdef SO_BINDTODEVICE #ifdef SO_BINDTODEVICE
if (socket4 >= 0) { if (socket4 >= 0) {
if (setsockopt(socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_st ate.optarg, strlen(optparse_state.optarg))) { if (p_setsockopt(suid, socket4, SOL_SOCKET, SO_BINDTODEVICE, opt parse_state.optarg, strlen(optparse_state.optarg))) {
perror("binding to specific interface (SO_BINTODEVICE)"); perror("binding to specific interface (SO_BINTODEVICE)");
exit(1); exit(1);
} }
} }
#ifdef IPV6 #ifdef IPV6
if (socket6 >= 0) { if (socket6 >= 0) {
if (setsockopt(socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_st ate.optarg, strlen(optparse_state.optarg))) { if (p_setsockopt(suid, socket6, SOL_SOCKET, SO_BINDTODEVICE, opt parse_state.optarg, strlen(optparse_state.optarg))) {
perror("binding to specific interface (SO_BINTODEVICE), IPV6 "); perror("binding to specific interface (SO_BINTODEVICE), IPV6 ");
exit(1); exit(1);
} }
} }
#endif #endif
#else #else
printf("%s: cant bind to a particular net interface since SO_BINDTOD EVICE is not supported on your os.\n", prog); printf("%s: cant bind to a particular net interface since SO_BINDTOD EVICE is not supported on your os.\n", prog);
exit(3); exit(3);
; ;
#endif #endif
skipping to change at line 799 skipping to change at line 836
break; break;
case '?': case '?':
fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg); fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg);
fprintf(stderr, "see 'fping -h' for usage information\n"); fprintf(stderr, "see 'fping -h' for usage information\n");
exit(1); exit(1);
break; break;
} }
} }
/* permanently drop privileges */
if (suid != getuid() && setuid(getuid())) {
perror("fatal: failed to permanently drop privileges");
/* continuing would be a security hole */
exit(4);
}
/* validate various option settings */ /* validate various option settings */
#ifndef IPV6 #ifndef IPV6
if (socket4 < 0) { if (socket4 < 0) {
#else #else
if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) { if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) {
#endif #endif
crash_and_burn("can't create socket (must run as root?)"); crash_and_burn("can't create socket (must run as root?)");
} }
skipping to change at line 1063 skipping to change at line 1107
} }
} }
else { else {
usage(1); usage(1);
} }
if (!num_hosts) { if (!num_hosts) {
exit(num_noaddress ? 2 : 1); exit(num_noaddress ? 2 : 1);
} }
if (socket4 >= 0) { if (src_addr_set && socket4 >= 0) {
socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL); socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL);
} }
#ifdef IPV6 #ifdef IPV6
if (socket6 >= 0) { if (src_addr6_set && socket6 >= 0) {
socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL); socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL);
} }
#endif #endif
/* allocate and initialize array to map host nr to host_entry */ /* allocate and initialize array to map host nr to host_entry */
{ {
struct event *cursor = event_queue_ping.first; struct event *cursor = event_queue_ping.first;
int i= 0; int i= 0;
table = (HOST_ENTRY**)calloc(num_hosts, sizeof(HOST_ENTRY *)); table = (HOST_ENTRY**)calloc(num_hosts, sizeof(HOST_ENTRY *));
if (!table) if (!table)
skipping to change at line 1619 skipping to change at line 1663
static int sent_charts = 0; static int sent_charts = 0;
int i; int i;
int64_t avg; int64_t avg;
HOST_ENTRY* h; HOST_ENTRY* h;
for (i = 0; i < num_hosts; i++) { for (i = 0; i < num_hosts; i++) {
h = table[i]; h = table[i];
if (!sent_charts) { if (!sent_charts) {
printf("CHART fping.%s_packets '' 'FPing Packets for host %s' packet s '%s' fping.packets line 110020 %.0f\n", h->name, h->host, h->name, report_inte rval / 1e9); printf("CHART fping.%s_packets '' 'FPing Packets for host %s' packet s '%s' fping.packets line 110020 %.0f\n", h->name, h->host, h->host, report_inte rval / 1e9);
printf("DIMENSION xmt sent absolute 1 1\n"); printf("DIMENSION xmt sent absolute 1 1\n");
printf("DIMENSION rcv received absolute 1 1\n"); printf("DIMENSION rcv received absolute 1 1\n");
} }
printf("BEGIN fping.%s_packets\n", h->name); printf("BEGIN fping.%s_packets\n", h->name);
printf("SET xmt = %d\n", h->num_sent_i); printf("SET xmt = %d\n", h->num_sent_i);
printf("SET rcv = %d\n", h->num_recv_i); printf("SET rcv = %d\n", h->num_recv_i);
printf("END\n"); printf("END\n");
if (!sent_charts) { if (!sent_charts) {
printf("CHART fping.%s_quality '' 'FPing Quality for host %s' percen tage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, h->name, report_i nterval / 1e9); printf("CHART fping.%s_quality '' 'FPing Quality for host %s' percen tage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, h->host, report_i nterval / 1e9);
printf("DIMENSION returned '' absolute 1 1\n"); printf("DIMENSION returned '' absolute 1 1\n");
/* printf("DIMENSION lost '' absolute 1 1\n"); */ /* printf("DIMENSION lost '' absolute 1 1\n"); */
} }
printf("BEGIN fping.%s_quality\n", h->name); printf("BEGIN fping.%s_quality\n", h->name);
/* /*
if( h->num_recv_i <= h->num_sent_i ) if( h->num_recv_i <= h->num_sent_i )
printf("SET lost = %d\n", h->num_sent_i > 0 ? ( ( h->num_sent_i - h- >num_recv_i ) * 100 ) / h->num_sent_i : 0 ); printf("SET lost = %d\n", h->num_sent_i > 0 ? ( ( h->num_sent_i - h- >num_recv_i ) * 100 ) / h->num_sent_i : 0 );
else else
printf("SET lost = 0\n"); printf("SET lost = 0\n");
*/ */
printf("SET returned = %d\n", h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0); printf("SET returned = %d\n", h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0);
printf("END\n"); printf("END\n");
if (!sent_charts) { if (!sent_charts) {
printf("CHART fping.%s_latency '' 'FPing Latency for host %s' ms '%s ' fping.latency area 110000 %.0f\n", h->name, h->host, h->name, report_interval / 1e9); printf("CHART fping.%s_latency '' 'FPing Latency for host %s' ms '%s ' fping.latency area 110000 %.0f\n", h->name, h->host, h->host, report_interval / 1e9);
printf("DIMENSION min minimum absolute 1 1000000\n"); printf("DIMENSION min minimum absolute 1 1000000\n");
printf("DIMENSION max maximum absolute 1 1000000\n"); printf("DIMENSION max maximum absolute 1 1000000\n");
printf("DIMENSION avg average absolute 1 1000000\n"); printf("DIMENSION avg average absolute 1 1000000\n");
} }
printf("BEGIN fping.%s_latency\n", h->name); printf("BEGIN fping.%s_latency\n", h->name);
if (h->num_recv_i) { if (h->num_recv_i) {
avg = h->total_time_i / h->num_recv_i; avg = h->total_time_i / h->num_recv_i;
printf("SET min = %ld\n", h->min_reply_i); printf("SET min = %" PRId64 "\n", h->min_reply_i);
printf("SET avg = %ld\n", avg); printf("SET avg = %" PRId64 "\n", avg);
printf("SET max = %ld\n", h->max_reply_i); printf("SET max = %" PRId64 "\n", h->max_reply_i);
} }
printf("END\n"); printf("END\n");
h->num_sent_i = h->num_recv_i = h->max_reply_i = h->min_reply_i = h->tot al_time_i = 0; h->num_sent_i = h->num_recv_i = h->max_reply_i = h->min_reply_i = h->tot al_time_i = 0;
} }
sent_charts = 1; sent_charts = 1;
} }
/************************************************************ /************************************************************
skipping to change at line 2056 skipping to change at line 2100
hlen = (ip->ip_vhl & 0x0F) << 2; hlen = (ip->ip_vhl & 0x0F) << 2;
#else #else
hlen = ip->ip_hl << 2; hlen = ip->ip_hl << 2;
#endif #endif
} }
if (reply_buf_len < hlen + ICMP_MINLEN) { if (reply_buf_len < hlen + ICMP_MINLEN) {
/* too short */ /* too short */
if (verbose_flag) { if (verbose_flag) {
char buf[INET6_ADDRSTRLEN]; char buf[INET6_ADDRSTRLEN];
getnameinfo((struct sockaddr*)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); getnameinfo( response_addr, sizeof( struct sockaddr_in ), buf, INET6 _ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
printf("received packet too short for ICMP (%d bytes from %s)\n", (i nt)reply_buf_len, buf); printf("received packet too short for ICMP (%d bytes from %s)\n", (i nt)reply_buf_len, buf);
} }
return -1; return -1;
} }
icp = (struct icmp*)(reply_buf + hlen); icp = (struct icmp*)(reply_buf + hlen);
if (icp->icmp_type != ICMP_ECHOREPLY) { if (icp->icmp_type != ICMP_ECHOREPLY) {
/* Handle other ICMP packets */ /* Handle other ICMP packets */
struct icmp* sent_icmp; struct icmp* sent_icmp;
skipping to change at line 2089 skipping to change at line 2133
if (sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != ident4) { if (sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != ident4) {
/* not caused by us */ /* not caused by us */
return -1; return -1;
} }
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns) ; seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns) ;
if (seqmap_value == NULL) { if (seqmap_value == NULL) {
return -1; return -1;
} }
getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRL EN, NULL, 0, NI_NUMERICHOST); getnameinfo(response_addr, sizeof( struct sockaddr_in ), addr_ascii, INE T6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
switch (icp->icmp_type) { switch (icp->icmp_type) {
case ICMP_UNREACH: case ICMP_UNREACH:
h = table[seqmap_value->host_nr]; h = table[seqmap_value->host_nr];
if (icp->icmp_code > ICMP_UNREACH_MAXTYPE) { if (icp->icmp_code > ICMP_UNREACH_MAXTYPE) {
print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
addr_ascii, h->host); addr_ascii, h->host);
} }
else { else {
print_warning("%s from %s for ICMP Echo sent to %s", print_warning("%s from %s for ICMP Echo sent to %s",
skipping to change at line 2881 skipping to change at line 2925
fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFA ULT_RETRY); fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFA ULT_RETRY);
fprintf(out, " -R, --random random packet data (to foil link data co mpression)\n"); fprintf(out, " -R, --random random packet data (to foil link data co mpression)\n");
fprintf(out, " -S, --src=IP set source address\n"); fprintf(out, " -S, --src=IP set source address\n");
fprintf(out, " -t, --timeout=MSEC individual target initial timeout (defau lt: %.0f ms,\n", timeout / 1e6); fprintf(out, " -t, --timeout=MSEC individual target initial timeout (defau lt: %.0f ms,\n", timeout / 1e6);
fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n"); fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
fprintf(out, "\n"); fprintf(out, "\n");
fprintf(out, "Output options:\n"); fprintf(out, "Output options:\n");
fprintf(out, " -a, --alive show targets that are alive\n"); fprintf(out, " -a, --alive show targets that are alive\n");
fprintf(out, " -A, --addr show targets by address\n"); fprintf(out, " -A, --addr show targets by address\n");
fprintf(out, " -C, --vcount=N same as -c, report results in verbose fo rmat\n"); fprintf(out, " -C, --vcount=N same as -c, report results in verbose fo rmat\n");
fprintf(out, " -d, --rdns show targets by name (force reverse-DNS lookup)\n");
fprintf(out, " -D, --timestamp print timestamp before each output line\ n"); fprintf(out, " -D, --timestamp print timestamp before each output line\ n");
fprintf(out, " -e, --elapsed show elapsed time on return packets\n"); fprintf(out, " -e, --elapsed show elapsed time on return packets\n");
fprintf(out, " -i, --interval=MSEC interval between sending ping packets (default: %.0f ms)\n", interval / 1e6); fprintf(out, " -i, --interval=MSEC interval between sending ping packets (default: %.0f ms)\n", interval / 1e6);
fprintf(out, " -n, --name show targets by name (-d is equivalent)\ n"); fprintf(out, " -n, --name show targets by name (reverse-DNS lookup for target IPs)\n");
fprintf(out, " -N, --netdata output compatible for netdata (-l -Q are required)\n"); fprintf(out, " -N, --netdata output compatible for netdata (-l -Q are required)\n");
fprintf(out, " -o, --outage show the accumulated outage time (lost p ackets * packet interval)\n"); fprintf(out, " -o, --outage show the accumulated outage time (lost p ackets * packet interval)\n");
fprintf(out, " -q, --quiet quiet (don't show per-target/per-ping re sults)\n"); fprintf(out, " -q, --quiet quiet (don't show per-target/per-ping re sults)\n");
fprintf(out, " -Q, --squiet=SECS same as -q, but show summary every n sec onds\n"); fprintf(out, " -Q, --squiet=SECS same as -q, but add interval summary eve ry SECS seconds\n");
fprintf(out, " -s, --stats print final stats\n"); fprintf(out, " -s, --stats print final stats\n");
fprintf(out, " -u, --unreach show targets that are unreachable\n"); fprintf(out, " -u, --unreach show targets that are unreachable\n");
fprintf(out, " -v, --version show version\n"); fprintf(out, " -v, --version show version\n");
fprintf(out, " -x, --reachable=N shows if >=N hosts are reachable or not\ n"); fprintf(out, " -x, --reachable=N shows if >=N hosts are reachable or not\ n");
exit(is_error); exit(is_error);
} }
 End of changes. 21 change blocks. 
22 lines changed or deleted 68 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)