You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.2 KiB
C
125 lines
4.2 KiB
C
/*
|
|
* fping: fast-ping, file-ping, favorite-ping, funky-ping
|
|
*
|
|
* Ping a list of target hosts in a round robin fashion.
|
|
* A better ping overall.
|
|
*
|
|
* fping website: http://www.fping.org
|
|
*
|
|
* Current maintainer of fping: David Schweikert
|
|
* Please send suggestions and patches to: david@schweikert.ch
|
|
*
|
|
*
|
|
* Original author: Roland Schemers <schemers@stanford.edu>
|
|
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
|
|
* Improved main loop: David Schweikert <david@schweikert.ch>
|
|
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
|
|
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
|
|
*
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that the above copyright notice and this paragraph are
|
|
* duplicated in all such forms and that any documentation,
|
|
* advertising materials, and other materials related to such
|
|
* distribution and use acknowledge that the software was developed
|
|
* by Stanford University. The name of the University may not be used
|
|
* to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* seqmap.c: implementation of a mapping between sequence number and (host, ping_nr)
|
|
* we can't just use ping_nr*host_count + host_nr, because it can
|
|
* overflow the 16 bit of the icmp header field. See also:
|
|
* https://github.com/schweikert/fping/issues/48
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "seqmap.h"
|
|
#include "limits.h"
|
|
#include "options.h"
|
|
#include "fping.h"
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
/* description of the data structure used:
|
|
*
|
|
* - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in
|
|
* the timeout interval (SEQMAP_TIMEOUT_IN_NS)
|
|
* - we store the values in an array with SEQMAP_MAXSEQ elements
|
|
* - current sequence number % SEQMAP_MAXSEQ gives the current index
|
|
* - when entering a value, we check that the current entry is expired
|
|
*/
|
|
|
|
static SEQMAP_VALUE* seqmap_map = NULL;
|
|
static unsigned int seqmap_next_id = 0;
|
|
|
|
#define SEQMAP_TIMEOUT_IN_NS 10000000000
|
|
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
|
|
|
|
void seqmap_init()
|
|
{
|
|
seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE));
|
|
if (seqmap_map == NULL) {
|
|
perror("malloc error (can't allocate seqmap_map)");
|
|
}
|
|
}
|
|
|
|
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t timestamp)
|
|
{
|
|
unsigned int current_id;
|
|
SEQMAP_VALUE* next_value;
|
|
|
|
if (!seqmap_map) {
|
|
fprintf(stderr, "fping internal error: seqmap not initialized.\n");
|
|
exit(4);
|
|
}
|
|
|
|
/* check if expired (note that unused seqmap values will have fields set to
|
|
* 0, so will be seen as expired */
|
|
next_value = &seqmap_map[seqmap_next_id];
|
|
if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
|
|
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
|
|
SEQMAP_TIMEOUT_IN_NS, host_nr, ping_count, seqmap_next_id);
|
|
exit(4);
|
|
}
|
|
|
|
/* store the value */
|
|
next_value->host_nr = host_nr;
|
|
next_value->ping_count = ping_count;
|
|
next_value->ping_ts = timestamp;
|
|
|
|
/* increase next id */
|
|
current_id = seqmap_next_id;
|
|
seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ;
|
|
|
|
dbg_printf("seqmap_add(host: %d, index: %d) -> %d\n", host_nr, ping_count, current_id);
|
|
|
|
return current_id;
|
|
}
|
|
|
|
SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now)
|
|
{
|
|
SEQMAP_VALUE* value;
|
|
|
|
if (id > SEQMAP_MAXSEQ) {
|
|
return NULL;
|
|
}
|
|
|
|
value = &seqmap_map[id];
|
|
|
|
/* verify that value is not expired */
|
|
if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) {
|
|
dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count,
|
|
now - value->ping_ts);
|
|
return NULL;
|
|
}
|
|
|
|
dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d\n", id, value->host_nr, value->ping_count);
|
|
|
|
return value;
|
|
}
|