ping_common.h revision 313379eb6b9da55f7371adef39a92153a0707d4a
1#include <stdio.h> 2#include <stdlib.h> 3#include <unistd.h> 4#include <time.h> 5#include <sys/param.h> 6#include <sys/socket.h> 7#include <linux/sockios.h> 8#include <sys/file.h> 9#include <sys/time.h> 10#include <sys/signal.h> 11#include <sys/ioctl.h> 12#include <net/if.h> 13#include <sys/uio.h> 14#include <sys/poll.h> 15#include <ctype.h> 16#include <errno.h> 17#include <string.h> 18#include <netdb.h> 19#include <setjmp.h> 20 21#ifdef CAPABILITIES 22#include <sys/prctl.h> 23#include <sys/capability.h> 24#endif 25 26#ifdef USE_IDN 27#include <locale.h> 28#include <idna.h> 29#endif 30 31#include <netinet/in.h> 32#include <arpa/inet.h> 33#include <linux/types.h> 34#include <linux/errqueue.h> 35 36#include "SNAPSHOT.h" 37 38#define DEFDATALEN (64 - 8) /* default data length */ 39 40#define MAXWAIT 10 /* max seconds to wait for response */ 41#define MININTERVAL 10 /* Minimal interpacket gap */ 42#define MINUSERINTERVAL 200 /* Minimal allowed interval for non-root */ 43 44#define SCHINT(a) (((a) <= MININTERVAL) ? MININTERVAL : (a)) 45 46/* various options */ 47extern int options; 48#define F_FLOOD 0x001 49#define F_INTERVAL 0x002 50#define F_NUMERIC 0x004 51#define F_PINGFILLED 0x008 52#define F_QUIET 0x010 53#define F_RROUTE 0x020 54#define F_SO_DEBUG 0x040 55#define F_SO_DONTROUTE 0x080 56#define F_VERBOSE 0x100 57#define F_TIMESTAMP 0x200 58#define F_FLOWINFO 0x200 59#define F_SOURCEROUTE 0x400 60#define F_TCLASS 0x400 61#define F_FLOOD_POLL 0x800 62#define F_LATENCY 0x1000 63#define F_AUDIBLE 0x2000 64#define F_ADAPTIVE 0x4000 65#define F_STRICTSOURCE 0x8000 66#define F_NOLOOP 0x10000 67#define F_TTL 0x20000 68#define F_MARK 0x40000 69#define F_PTIMEOFDAY 0x80000 70#define F_OUTSTANDING 0x100000 71 72/* 73 * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum 74 * number of received sequence numbers we can keep track of. 75 */ 76#define MAX_DUP_CHK 0x10000 77 78#if defined(__WORDSIZE) && __WORDSIZE == 64 79# define USE_BITMAP64 80#endif 81 82#ifdef USE_BITMAP64 83typedef __u64 bitmap_t; 84# define BITMAP_SHIFT 6 85#else 86typedef __u32 bitmap_t; 87# define BITMAP_SHIFT 5 88#endif 89 90#if ((MAX_DUP_CHK >> (BITMAP_SHIFT + 3)) << (BITMAP_SHIFT + 3)) != MAX_DUP_CHK 91# error Please MAX_DUP_CHK and/or BITMAP_SHIFT 92#endif 93 94struct rcvd_table { 95 bitmap_t bitmap[MAX_DUP_CHK / (sizeof(bitmap_t) * 8)]; 96}; 97 98extern struct rcvd_table rcvd_tbl; 99 100#define A(bit) (rcvd_tbl.bitmap[(bit) >> BITMAP_SHIFT]) /* identify word in array */ 101#define B(bit) (((bitmap_t)1) << ((bit) & ((1 << BITMAP_SHIFT) - 1))) /* identify bit in word */ 102 103static inline void rcvd_set(__u16 seq) 104{ 105 unsigned bit = seq % MAX_DUP_CHK; 106 A(bit) |= B(bit); 107} 108 109static inline void rcvd_clear(__u16 seq) 110{ 111 unsigned bit = seq % MAX_DUP_CHK; 112 A(bit) &= ~B(bit); 113} 114 115static inline bitmap_t rcvd_test(__u16 seq) 116{ 117 unsigned bit = seq % MAX_DUP_CHK; 118 return A(bit) & B(bit); 119} 120 121extern u_char outpack[]; 122extern int maxpacket; 123 124extern int datalen; 125extern char *hostname; 126extern int uid; 127extern int ident; /* process id to identify our packets */ 128 129extern int sndbuf; 130extern int ttl; 131 132extern long npackets; /* max packets to transmit */ 133extern long nreceived; /* # of packets we got back */ 134extern long nrepeats; /* number of duplicates */ 135extern long ntransmitted; /* sequence # for outbound packets = #sent */ 136extern long nchecksum; /* replies with bad checksum */ 137extern long nerrors; /* icmp errors */ 138extern int interval; /* interval between packets (msec) */ 139extern int preload; 140extern int deadline; /* time to die */ 141extern int lingertime; 142extern struct timeval start_time, cur_time; 143extern volatile int exiting; 144extern volatile int status_snapshot; 145extern int confirm; 146extern int confirm_flag; 147extern int working_recverr; 148 149extern volatile int in_pr_addr; /* pr_addr() is executing */ 150extern jmp_buf pr_addr_jmp; 151 152#ifndef MSG_CONFIRM 153#define MSG_CONFIRM 0 154#endif 155 156 157/* timing */ 158extern int timing; /* flag to do timing */ 159extern long tmin; /* minimum round trip time */ 160extern long tmax; /* maximum round trip time */ 161extern long long tsum; /* sum of all times, for doing average */ 162extern long long tsum2; 163extern int rtt; 164extern __u16 acked; 165extern int pipesize; 166 167#define COMMON_OPTIONS \ 168case 'a': case 'U': case 'c': case 'd': \ 169case 'f': case 'i': case 'w': case 'l': \ 170case 'S': case 'n': case 'p': case 'q': \ 171case 'r': case 's': case 'v': case 'L': \ 172case 't': case 'A': case 'W': case 'B': case 'm': \ 173case 'D': case 'O': 174 175#define COMMON_OPTSTR "h?VQ:I:M:aUc:dfi:w:l:S:np:qrs:vLt:AW:Bm:DO" 176 177/* 178 * Write to stdout 179 */ 180static inline void write_stdout(const char *str, size_t len) 181{ 182 size_t o = 0; 183 ssize_t cc; 184 do { 185 cc = write(STDOUT_FILENO, str + o, len - o); 186 o += cc; 187 } while (len > o || cc < 0); 188} 189 190/* 191 * tvsub -- 192 * Subtract 2 timeval structs: out = out - in. Out is assumed to 193 * be >= in. 194 */ 195static inline void tvsub(struct timeval *out, struct timeval *in) 196{ 197 if ((out->tv_usec -= in->tv_usec) < 0) { 198 --out->tv_sec; 199 out->tv_usec += 1000000; 200 } 201 out->tv_sec -= in->tv_sec; 202} 203 204static inline void set_signal(int signo, void (*handler)(int)) 205{ 206 struct sigaction sa; 207 208 memset(&sa, 0, sizeof(sa)); 209 210 sa.sa_handler = (void (*)(int))handler; 211#ifdef SA_INTERRUPT 212 sa.sa_flags = SA_INTERRUPT; 213#endif 214 sigaction(signo, &sa, NULL); 215} 216 217extern int __schedule_exit(int next); 218 219static inline int schedule_exit(int next) 220{ 221 if (npackets && ntransmitted >= npackets && !deadline) 222 next = __schedule_exit(next); 223 return next; 224} 225 226static inline int in_flight(void) 227{ 228 __u16 diff = (__u16)ntransmitted - acked; 229 return (diff<=0x7FFF) ? diff : ntransmitted-nreceived-nerrors; 230} 231 232static inline void acknowledge(__u16 seq) 233{ 234 __u16 diff = (__u16)ntransmitted - seq; 235 if (diff <= 0x7FFF) { 236 if ((int)diff+1 > pipesize) 237 pipesize = (int)diff+1; 238 if ((__s16)(seq - acked) > 0 || 239 (__u16)ntransmitted - acked > 0x7FFF) 240 acked = seq; 241 } 242} 243 244static inline void advance_ntransmitted(void) 245{ 246 ntransmitted++; 247 /* Invalidate acked, if 16 bit seq overflows. */ 248 if ((__u16)ntransmitted - acked > 0x7FFF) 249 acked = (__u16)ntransmitted + 1; 250} 251 252extern void limit_capabilities(void); 253static int enable_capability_raw(void); 254static int disable_capability_raw(void); 255static int enable_capability_admin(void); 256static int disable_capability_admin(void); 257#ifdef CAPABILITIES 258extern int modify_capability(cap_value_t, cap_flag_value_t); 259static inline int enable_capability_raw(void) { return modify_capability(CAP_NET_RAW, CAP_SET); }; 260static inline int disable_capability_raw(void) { return modify_capability(CAP_NET_RAW, CAP_CLEAR); }; 261static inline int enable_capability_admin(void) { return modify_capability(CAP_NET_ADMIN, CAP_SET); }; 262static inline int disable_capability_admin(void) { return modify_capability(CAP_NET_ADMIN, CAP_CLEAR); }; 263#else 264extern int modify_capability(int); 265static inline int enable_capability_raw(void) { return modify_capability(1); }; 266static inline int disable_capability_raw(void) { return modify_capability(0); }; 267static inline int enable_capability_admin(void) { return modify_capability(1); }; 268static inline int disable_capability_admin(void) { return modify_capability(0); }; 269#endif 270extern void drop_capabilities(void); 271 272extern int send_probe(void); 273extern int receive_error_msg(void); 274extern int parse_reply(struct msghdr *msg, int len, void *addr, struct timeval *); 275extern void install_filter(void); 276 277extern int pinger(void); 278extern void sock_setbufs(int icmp_sock, int alloc); 279extern void setup(int icmp_sock); 280extern void main_loop(int icmp_sock, __u8 *buf, int buflen) __attribute__((noreturn)); 281extern void finish(void) __attribute__((noreturn)); 282extern void status(void); 283extern void common_options(int ch); 284extern int gather_statistics(__u8 *ptr, int icmplen, 285 int cc, __u16 seq, int hops, 286 int csfailed, struct timeval *tv, char *from, 287 void (*pr_reply)(__u8 *ptr, int cc)); 288extern void print_timestamp(void); 289