⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping.c

📁 This is a short linux ping program
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	$NetBSD: ping.c,v 1.76 2004/04/22 01:39:20 itojun Exp $	*//* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Muuss. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* *			P I N G . C * * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, * measure round-trip-delays and packet loss across network paths. * * Author - *	Mike Muuss *	U. S. Army Ballistic Research Laboratory *	December, 1983 * Modified at Uc Berkeley * Record Route and verbose headers - Phil Dykstra, BRL, March 1988. * Multicast options (ttl, if, loop) - Steve Deering, Stanford, August 1988. * ttl, duplicate detection - Cliff Frost, UCB, April 1989 * Pad pattern - Cliff Frost (from Tom Ferrin, UCSF), April 1989 * * Status - *	Public Domain.  Distribution Unlimited. * * Bugs - *	More statistics could always be gathered. *	This program has to run SUID to ROOT to access the ICMP socket. */#include <sys/cdefs.h>#ifndef lint__RCSID("$NetBSD: ping.c,v 1.76 2004/04/22 01:39:20 itojun Exp $");#endif#include <stdio.h>#include <stddef.h>#include <errno.h>#include <sys/time.h>#include <sys/types.h>#include <sys/signal.h>#include <sys/param.h>#include <sys/socket.h>#include <sys/file.h>#include <termios.h>#include <stdlib.h>#include <unistd.h>#include <poll.h>#include <limits.h>#include <math.h>#include <string.h>#include <err.h>#ifdef sgi#include <bstring.h>#include <getopt.h>#include <sys/prctl.h>#ifndef PRE_KUDZU#include <cap_net.h>#else#define cap_socket socket#endif#else#define cap_socket socket#include <err.h>#endif#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <netinet/ip_var.h>#include <arpa/inet.h>#include <ctype.h>#include <netdb.h>#ifdef IPSEC#include <netinet6/ipsec.h>#endif /*IPSEC*/#define FLOOD_INTVL	0.01		/* default flood output interval */#define	MAXPACKET	(IP_MAXPACKET-60-8)	/* max packet size */#define F_VERBOSE	0x0001#define F_QUIET		0x0002		/* minimize all output */#define F_SEMI_QUIET	0x0004		/* ignore our ICMP errors */#define F_FLOOD		0x0008		/* flood-ping */#define	F_RECORD_ROUTE	0x0010		/* record route */#define F_SOURCE_ROUTE	0x0020		/* loose source route */#define F_PING_FILLED	0x0040		/* is buffer filled with user data? */#define F_PING_RANDOM	0x0080		/* use random data */#define	F_NUMERIC	0x0100		/* do not do gethostbyaddr() calls */#define F_TIMING	0x0200		/* room for a timestamp */#define F_DF		0x0400		/* set IP DF bit */#define F_SOURCE_ADDR	0x0800		/* set source IP address/interface */#define F_ONCE		0x1000		/* exit(0) after receiving 1 reply */#define F_MCAST		0x2000		/* multicast target */#define F_MCAST_NOLOOP	0x4000		/* no multicast loopback */#define F_AUDIBLE	0x8000		/* audible output */#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC#define F_POLICY	0x10000#else#define	F_AUTHHDR	0x10000#define	F_ENCRYPT	0x20000#endif /*IPSEC_POLICY_IPSEC*/#endif /*IPSEC*//* MAX_DUP_CHK is the number of bits in received table, the *	maximum number of received sequence numbers we can track to check *	for duplicates. */#define MAX_DUP_CHK     (8 * 2048)u_char	rcvd_tbl[MAX_DUP_CHK/8];int     nrepeats = 0;#define A(seq)	rcvd_tbl[(seq/8)%sizeof(rcvd_tbl)]  /* byte in array */#define B(seq)	(1 << (seq & 0x07))	/* bit in byte */#define SET(seq) (A(seq) |= B(seq))#define CLR(seq) (A(seq) &= (~B(seq)))#define TST(seq) (A(seq) & B(seq))struct tv32 {	int32_t tv32_sec;	int32_t tv32_usec;};u_char	*packet;int	packlen;int	pingflags = 0, options;char	*fill_pat;int s;					/* Socket file descriptor */int sloop;				/* Socket file descriptor/loopback */#define PHDR_LEN sizeof(struct tv32)	/* size of timestamp header */struct sockaddr_in whereto, send_addr;	/* Who to ping */struct sockaddr_in src_addr;		/* from where */struct sockaddr_in loc_addr;		/* 127.1 */int datalen = 64 - PHDR_LEN;		/* How much data */#ifndef __NetBSD__static char *progname;#define	getprogname()		(progname)#define	setprogname(name)	((void)(progname = (name)))#endifchar hostname[MAXHOSTNAMELEN];static struct {	struct ip	o_ip;	char		o_opt[MAX_IPOPTLEN];	union {		u_char	    u_buf[MAXPACKET+offsetof(struct icmp, icmp_data)];		struct icmp u_icmp;	} o_u;} out_pack;#define	opack_icmp	out_pack.o_u.u_icmpstruct ip *opack_ip;char optspace[MAX_IPOPTLEN];		/* record route space */int optlen;int npackets;				/* total packets to send */int preload;				/* number of packets to "preload" */int ntransmitted;			/* output sequence # = #sent */int ident;				/* our ID, in network byte order */int nreceived;				/* # of packets we got back */double interval;			/* interval between packets */struct timeval interval_tv;double tmin = 999999999.0;double tmax = 0.0;double tsum = 0.0;			/* sum of all times */double tsumsq = 0.0;double maxwait = 0.0;#ifdef SIGINFOint reset_kerninfo;#endifint bufspace = IP_MAXPACKET;struct timeval now, clear_cache, last_tx, next_tx, first_tx;struct timeval last_rx, first_rx;int lastrcvd = 1;			/* last ping sent has been received */static struct timeval jiggle_time;static int jiggle_cnt, total_jiggled, jiggle_direction = -1;static void doit(void);static void prefinish(int);static void prtsig(int);static void finish(int);static void summary(int);static void pinger(void);static void fill(void);static void rnd_fill(void);static double diffsec(struct timeval *, struct timeval *);static void timevaladd(struct timeval *, struct timeval *);static void sec_to_timeval(const double, struct timeval *);static double timeval_to_sec(const struct timeval *);static void pr_pack(u_char *, int, struct sockaddr_in *);static u_int16_t in_cksum(u_int16_t *, u_int);static void pr_saddr(u_char *);static char *pr_addr(struct in_addr *);static void pr_iph(struct icmp *, int);static void pr_retip(struct icmp *, int);static int pr_icmph(struct icmp *, struct sockaddr_in *, int);static void jiggle(int), jiggle_flush(int);static void gethost(const char *, const char *,		    struct sockaddr_in *, char *, int);static void usage(void);intmain(int argc, char *argv[]){	int c, i, on = 1, hostind = 0;	long l;	u_char ttl = 0;	u_long tos = 0;	char *p;#ifdef SIGINFO	struct termios ts;#endif#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC	char *policy_in = NULL;	char *policy_out = NULL;#endif#endif  	setprogname(argv[0]);#ifndef IPSEC#define IPSECOPT#else#ifdef IPSEC_POLICY_IPSEC#define IPSECOPT	"E:"#else#define IPSECOPT	"AE"#endif /*IPSEC_POLICY_IPSEC*/#endif	while ((c = getopt(argc, argv,			   "ac:dDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT)) != -1) {#undef IPSECOPT		switch (c) {		case 'a':			pingflags |= F_AUDIBLE;			break;		case 'c':			npackets = strtol(optarg, &p, 0);			if (*p != '\0' || npackets <= 0)				errx(1, "Bad/invalid number of packets");			break;		case 'D':			pingflags |= F_DF;			break;		case 'd':			options |= SO_DEBUG;			break;		case 'f':			pingflags |= F_FLOOD;			break;		case 'h':			hostind = optind-1;			break;		case 'i':		/* wait between sending packets */			interval = strtod(optarg, &p);			if (*p != '\0' || interval <= 0)				errx(1, "Bad/invalid interval %s", optarg);			break;		case 'l':			preload = strtol(optarg, &p, 0);			if (*p != '\0' || preload < 0)				errx(1, "Bad/invalid preload value %s",				     optarg);			break;		case 'n':			pingflags |= F_NUMERIC;			break;		case 'o':			pingflags |= F_ONCE;			break;		case 'p':		/* fill buffer with user pattern */			if (pingflags & F_PING_RANDOM)				errx(1, "Only one of -P and -p allowed");			pingflags |= F_PING_FILLED;			fill_pat = optarg;			break;		case 'P':			if (pingflags & F_PING_FILLED)				errx(1, "Only one of -P and -p allowed");			pingflags |= F_PING_RANDOM;			break;		case 'q':			pingflags |= F_QUIET;			break;		case 'Q':			pingflags |= F_SEMI_QUIET;			break;		case 'r':			options |= SO_DONTROUTE;			break;		case 's':		/* size of packet to send */			datalen = strtol(optarg, &p, 0);			if (*p != '\0' || datalen < 0)				errx(1, "Bad/invalid packet size %s", optarg);			if (datalen > MAXPACKET)				errx(1, "packet size is too large");			break;		case 'v':			pingflags |= F_VERBOSE;			break;		case 'R':			pingflags |= F_RECORD_ROUTE;			break;		case 'L':			pingflags |= F_MCAST_NOLOOP;			break;		case 't':			tos = strtoul(optarg, &p, 0);			if (*p != '\0' ||  tos > 0xFF)				errx(1, "bad tos value: %s", optarg);			break;		case 'T':			l = strtol(optarg, &p, 0);			if (*p != '\0' || l > 255 || l <= 0)				errx(1, "ttl out of range");			ttl = (u_char)l;    /* cannot check >255 otherwise */			break;		case 'I':			pingflags |= F_SOURCE_ADDR;			gethost("-I", optarg, &src_addr, 0, 0);			break;		case 'g':			pingflags |= F_SOURCE_ROUTE;			gethost("-g", optarg, &send_addr, 0, 0);			break;		case 'w':			maxwait = strtod(optarg, &p);			if (*p != '\0' || maxwait <= 0)				errx(1, "Bad/invalid maxwait time %s", optarg);			break;#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC		case 'E':			pingflags |= F_POLICY;			if (!strncmp("in", optarg, 2)) {				policy_in = strdup(optarg);				if (!policy_in)					err(1, "strdup");			} else if (!strncmp("out", optarg, 3)) {				policy_out = strdup(optarg);				if (!policy_out)					err(1, "strdup");			} else				errx(1, "invalid security policy");			break;#else		case 'A':			pingflags |= F_AUTHHDR;			break;		case 'E':			pingflags |= F_ENCRYPT;			break;#endif /*IPSEC_POLICY_IPSEC*/#endif /*IPSEC*/		default:			usage();			break;		}	}	if (interval == 0)		interval = (pingflags & F_FLOOD) ? FLOOD_INTVL : 1.0;#ifndef sgi	if (pingflags & F_FLOOD && getuid())		errx(1, "Must be superuser to use -f");	if (interval < 1.0 && getuid())		errx(1, "Must be superuser to use < 1 sec ping interval");	if (preload > 0 && getuid())		errx(1, "Must be superuser to use -l");#endif	sec_to_timeval(interval, &interval_tv);	if ((pingflags & (F_AUDIBLE|F_FLOOD)) == (F_AUDIBLE|F_FLOOD))		warnx("Sorry, no audible output for flood pings");	if (npackets != 0) {		npackets += preload;	} else {		npackets = INT_MAX;	}	if (hostind == 0) {		if (optind != argc-1)			usage();		else			hostind = optind;	}	else if (hostind >= argc - 1)		usage();	gethost("", argv[hostind], &whereto, hostname, sizeof(hostname));	if (IN_MULTICAST(ntohl(whereto.sin_addr.s_addr)))		pingflags |= F_MCAST;	if (!(pingflags & F_SOURCE_ROUTE))		(void) memcpy(&send_addr, &whereto, sizeof(send_addr));	loc_addr.sin_family = AF_INET;	loc_addr.sin_len = sizeof(struct sockaddr_in);	loc_addr.sin_addr.s_addr = htonl((127<<24)+1);	if (datalen >= PHDR_LEN)	/* can we time them? */		pingflags |= F_TIMING;	packlen = datalen + 60 + 76;	/* MAXIP + MAXICMP */	if ((packet = (u_char *)malloc(packlen)) == NULL)		err(1, "Out of memory");	if (pingflags & F_PING_FILLED) {		fill();	} else if (pingflags & F_PING_RANDOM) {		rnd_fill();	} else {		for (i = PHDR_LEN; i < datalen; i++)			opack_icmp.icmp_data[i] = i;	}	ident = htons(arc4random() & 0xFFFF);	if ((s = cap_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)		err(1, "Cannot create socket");	if (options & SO_DEBUG) {		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,			       (char *)&on, sizeof(on)) == -1)			warn("Can't turn on socket debugging");	}	if (options & SO_DONTROUTE) {		if (setsockopt(s, SOL_SOCKET, SO_DONTROUTE,			       (char *)&on, sizeof(on)) == -1)			warn("SO_DONTROUTE");	}	if ((sloop = cap_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)		err(1, "Cannot create socket");	if (options & SO_DEBUG) {		if (setsockopt(sloop, SOL_SOCKET, SO_DEBUG,			       (char *)&on, sizeof(on)) == -1)			warn("Can't turn on socket debugging");	}	if (options & SO_DONTROUTE) {		if (setsockopt(sloop, SOL_SOCKET, SO_DONTROUTE,			       (char *)&on, sizeof(on)) == -1)			warn("SO_DONTROUTE");	}	if (pingflags & F_SOURCE_ROUTE) {		optspace[IPOPT_OPTVAL] = IPOPT_LSRR;		optspace[IPOPT_OLEN] = optlen = 7;		optspace[IPOPT_OFFSET] = IPOPT_MINOFF;		(void)memcpy(&optspace[IPOPT_MINOFF-1], &whereto.sin_addr,			     sizeof(whereto.sin_addr));		optspace[optlen++] = IPOPT_NOP;	}	if (pingflags & F_RECORD_ROUTE) {		optspace[optlen+IPOPT_OPTVAL] = IPOPT_RR;		optspace[optlen+IPOPT_OLEN] = (MAX_IPOPTLEN -1-optlen);		optspace[optlen+IPOPT_OFFSET] = IPOPT_MINOFF;		optlen = MAX_IPOPTLEN;	}	/* this leaves opack_ip 0(mod 4) aligned */	opack_ip = (struct ip *)((char *)&out_pack.o_ip				 + sizeof(out_pack.o_opt)				 - optlen);	(void) memcpy(opack_ip + 1, optspace, optlen);	if (setsockopt(s,IPPROTO_IP,IP_HDRINCL, (char *) &on, sizeof(on)) < 0)		err(1, "Can't set special IP header");	opack_ip->ip_v = IPVERSION;	opack_ip->ip_hl = (sizeof(struct ip)+optlen) >> 2;	opack_ip->ip_tos = tos;	opack_ip->ip_off = (pingflags & F_DF) ? IP_DF : 0;	opack_ip->ip_ttl = ttl ? ttl : MAXTTL;	opack_ip->ip_p = IPPROTO_ICMP;	opack_ip->ip_src = src_addr.sin_addr;	opack_ip->ip_dst = send_addr.sin_addr;	if (pingflags & F_MCAST) {		if (pingflags & F_MCAST_NOLOOP) {			u_char loop = 0;			if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,			    (char *) &loop, 1) < 0)				err(1, "Can't disable multicast loopback");		}		if (ttl != 0		    && setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,		    (char *) &ttl, 1) < 0)			err(1, "Can't set multicast time-to-live");		if ((pingflags & F_SOURCE_ADDR)		    && setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,				  (char *) &src_addr.sin_addr,				  sizeof(src_addr.sin_addr)) < 0)			err(1, "Can't set multicast source interface");	} else if (pingflags & F_SOURCE_ADDR) {		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,			       (char *) &src_addr.sin_addr,			       sizeof(src_addr.sin_addr)) < 0)			err(1, "Can't set source interface/address");	}#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC    {	char *buf;	if (pingflags & F_POLICY) {		if (policy_in != NULL) {			buf = ipsec_set_policy(policy_in, strlen(policy_in));			if (buf == NULL)				errx(1, "%s", ipsec_strerror());			if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,					buf, ipsec_get_policylen(buf)) < 0) {				err(1, "ipsec policy cannot be configured");			}			free(buf);		}		if (policy_out != NULL) {			buf = ipsec_set_policy(policy_out, strlen(policy_out));			if (buf == NULL)				errx(1, "%s", ipsec_strerror());			if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,					buf, ipsec_get_policylen(buf)) < 0) {				err(1, "ipsec policy cannot be configured");			}			free(buf);		}	}	buf = ipsec_set_policy("out bypass", strlen("out bypass"));	if (buf == NULL)		errx(1, "%s", ipsec_strerror());	if (setsockopt(sloop, IPPROTO_IP, IP_IPSEC_POLICY,			buf, ipsec_get_policylen(buf)) < 0) {#if 0		warnx("ipsec is not configured");#else		/* ignore it, should be okay */#endif	}	free(buf);    }#else    {	int optval;	if (pingflags & F_AUTHHDR) {		optval = IPSEC_LEVEL_REQUIRE;#ifdef IP_AUTH_TRANS_LEVEL		(void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL,			(char *)&optval, sizeof(optval));#else		(void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL,			(char *)&optval, sizeof(optval));#endif	}	if (pingflags & F_ENCRYPT) {		optval = IPSEC_LEVEL_REQUIRE;		(void)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL,			(char *)&optval, sizeof(optval));	}	optval = IPSEC_LEVEL_BYPASS;#ifdef IP_AUTH_TRANS_LEVEL	(void)setsockopt(sloop, IPPROTO_IP, IP_AUTH_TRANS_LEVEL,		(char *)&optval, sizeof(optval));#else	(void)setsockopt(sloop, IPPROTO_IP, IP_AUTH_LEVEL,		(char *)&optval, sizeof(optval));#endif	(void)setsockopt(sloop, IPPROTO_IP, IP_ESP_TRANS_LEVEL,		(char *)&optval, sizeof(optval));    }#endif /*IPSEC_POLICY_IPSEC*/#endif /*IPSEC*/	(void)printf("PING %s (%s): %d data bytes\n", hostname,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -