1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/*
Copyright (C) 2005-2025 Free Software Foundation, Inc.
This file is part of GNU Inetutils.
GNU Inetutils is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Inetutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see `http://www.gnu.org/licenses/'. */
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/icmp6.h>
#include <icmp.h>
#include <error.h>
#include <progname.h>
#include <stdbool.h>
#define MAXWAIT 10 /* Max seconds to wait for response. */
#define MAXPATTERN 16 /* Maximal length of pattern. */
#define OPT_FLOOD 0x001
#define OPT_INTERVAL 0x002
#define OPT_NUMERIC 0x004
#define OPT_QUIET 0x008
#define OPT_RROUTE 0x010
#define OPT_VERBOSE 0x020
#define OPT_IPTIMESTAMP 0x040
#define OPT_FLOWINFO 0x080
#define OPT_TCLASS 0x100
#define SOPT_TSONLY 0x001
#define SOPT_TSADDR 0x002
#define SOPT_TSPRESPEC 0x004
struct ping_stat
{
double tmin; /* minimum round trip time */
double tmax; /* maximum round trip time */
double tsum; /* sum of all times, for doing average */
double tsumsq; /* sum of all times squared, for std. dev. */
};
#define PEV_RESPONSE 0
#define PEV_DUPLICATE 1
#define PEV_NOECHO 2
#define PING_CKTABSIZE 128
/* The rationale for not exiting after a sending N packets is that we
want to follow the traditional behaviour of ping. */
#define DEFAULT_PING_COUNT 0
#define PING_HEADER_LEN (USE_IPV6 ? sizeof (struct icmp6_hdr) : ICMP_MINLEN)
#define PING_TIMING(s) ((s) >= sizeof (struct timeval))
#define PING_DATALEN (64 - PING_HEADER_LEN) /* default data length */
#define PING_DEFAULT_INTERVAL 1000 /* Milliseconds */
#define PING_PRECISION 1000 /* Millisecond precision */
#define PING_SET_INTERVAL(t,i) do {\
(t).tv_sec = (i)/PING_PRECISION;\
(t).tv_nsec = ((i)%PING_PRECISION)*(1e9/PING_PRECISION) ;\
} while (0)
#define PING_MIN_USER_INTERVAL (200000/PING_PRECISION)
/* FIXME: Adjust IPv6 case for options and their consumption. */
#define _PING_BUFLEN(p, u) ((u)? ((p)->ping_datalen + sizeof (struct icmp6_hdr)) : \
(MAXIPLEN + (p)->ping_datalen + ICMP_TSLEN))
typedef int (*ping_efp6) (int code, void *closure, struct sockaddr_in6 * dest,
struct sockaddr_in6 * from, struct icmp6_hdr * icmp,
int datalen);
typedef int (*ping_efp) (int code,
void *closure,
struct sockaddr_in * dest,
struct sockaddr_in * from,
struct ip * ip, icmphdr_t * icmp, int datalen);
union event
{
ping_efp6 handler6;
ping_efp handler;
};
union ping_address
{
struct sockaddr_in ping_sockaddr;
struct sockaddr_in6 ping_sockaddr6;
};
typedef struct ping_data PING;
struct ping_data
{
int ping_fd; /* Raw socket descriptor */
int ping_type; /* Type of packets to send */
size_t ping_count; /* Number of packets to send */
struct timespec ping_start_time; /* Start time */
size_t ping_interval; /* Number of seconds to wait between sending pkts */
union ping_address ping_dest; /* whom to ping */
char *ping_hostname; /* Printable hostname */
size_t ping_datalen; /* Length of data */
int ping_ident; /* Our identifier */
union event ping_event; /* User-defined handler */
void *ping_closure; /* User-defined data */
/* Runtime info */
int ping_cktab_size;
char *ping_cktab;
unsigned char *ping_buffer; /* I/O buffer */
union ping_address ping_from;
size_t ping_num_xmit; /* Number of packets transmitted */
size_t ping_num_recv; /* Number of packets received */
size_t ping_num_rept; /* Number of duplicates received */
};
#define _C_BIT(p,bit) (p)->ping_cktab[(bit)>>3] /* byte in ck array */
#define _C_MASK(bit) (1 << ((bit) & 0x07))
#define _C_IND(p,bit) ((bit) % (8 * (p)->ping_cktab_size))
#define _PING_SET(p,bit) \
do \
{ \
int n = _C_IND (p,bit); \
_C_BIT (p,n) |= _C_MASK (n); \
} \
while (0)
#define _PING_CLR(p,bit) \
do \
{ \
int n = _C_IND (p,bit); \
_C_BIT (p,n) &= ~_C_MASK (n); \
} \
while (0)
#define _PING_TST(p,bit) \
(_C_BIT (p, _C_IND (p,bit)) & _C_MASK (_C_IND (p,bit)))
double nabs (double a);
double nsqrt (double a, double prec);
size_t ping_cvt_number (const char *optarg, size_t maxval, int allow_zero);
int is_normed_time (n_time t);
const char *ping_cvt_time (char *buf, size_t buflen, n_time t);
void init_data_buffer (unsigned char *pat, size_t len);
void decode_pattern (const char *text, int *pattern_len,
unsigned char *pattern_data);
int _ping_setbuf (PING * p, bool use_ipv6);
int ping_set_data (PING * p, void *data, size_t off, size_t len,
bool use_ipv6);
void ping_set_count (PING * ping, size_t count);
void ping_set_sockopt (PING * ping, int opt, void *val, int valsize);
void ping_set_interval (PING * ping, size_t interval);
void ping_unset_data (PING * p);
bool ping_timeout_p (struct timespec *start_time, int timeout);
char *ipaddr2str (struct sockaddr *from, socklen_t fromlen);
char *sinaddr2str (struct in_addr ina);
|