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

📄 ping.c

📁 inetutils的源代码
💻 C
字号:
/* Copyright (C) 1998,2001, 2002 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 2, 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 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 GNU Inetutils; see the file COPYING.  If not, write to   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <sys/param.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/time.h>#include <signal.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>/*#include <netinet/ip_icmp.h>  -- deliberately not including this */#ifdef HAVE_NETINET_IP_VAR_H# include <netinet/ip_var.h>#endif#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include "getopt.h"#include <icmp.h>#include <ping.h>#include <ping_impl.h>static char short_options[] = "VLhc:dfi:l:np:qRrs:t:v";static struct option long_options[] = {  /* Help options */  {"version", no_argument, NULL, 'V'},  {"license", no_argument, NULL, 'L'},  {"help",    no_argument, NULL, 'h'},  /* Common options */  {"count",   required_argument, NULL, 'c'},  {"debug",   no_argument, NULL, 'd'},  {"ignore-routing", no_argument, NULL, 'r'},  {"size",    required_argument, NULL, 's'},  {"interval",required_argument, NULL, 'i'},  {"numeric", no_argument, NULL, 'n'},  {"verbose", no_argument, NULL, 'v'},  /* Packet types */  {"type",    required_argument, NULL, 't'},  {"echo",    no_argument, NULL, ICMP_ECHO},  {"timestamp",no_argument, NULL, ICMP_TIMESTAMP},  {"address", no_argument, NULL, ICMP_ADDRESS},  {"router",  no_argument, NULL, ICMP_ROUTERDISCOVERY},  /* echo-specific options */  {"flood",   no_argument, NULL, 'f'},  {"preload", required_argument, NULL, 'l'},  {"pattern", required_argument, NULL, 'p'},  {"quiet",   no_argument, NULL, 'q'},  {"route",   no_argument, NULL, 'R'},  {NULL,      no_argument, NULL, 0}};extern int ping_echo __P ((int argc, char **argv));extern int ping_timestamp __P ((int argc, char **argv));extern int ping_address __P ((int argc, char **argv));extern int ping_router __P ((int argc, char **argv));PING *ping;u_char *data_buffer;size_t data_length = PING_DATALEN;unsigned options;unsigned long preload = 0;int (*ping_type) __P ((int argc, char **argv)) = ping_echo;static void show_usage (void);static void show_license (void);static void decode_pattern (const char *text, int *pattern_len, 		           u_char *pattern_data);static void decode_type (const char *optarg);static void init_data_buffer (u_char *pat, int len);static int send_echo (PING *ping);intmain (int argc, char **argv){  int c;  char *p;  int one = 1;  u_char pattern[16];  int pattern_len = 16;  u_char *patptr = NULL;  int is_root = getuid () == 0;  if ((ping = ping_init (ICMP_ECHO, getpid ())) == NULL)    {      fprintf (stderr, "can't init ping: %s\n", strerror (errno));      exit (1);    }  ping_set_sockopt (ping, SO_BROADCAST, (char *)&one, sizeof (one));  /* Reset root privileges */  setuid (getuid ());  /* Parse command line */  while ((c = getopt_long (argc, argv, short_options, long_options, NULL))	 != EOF)    {      switch (c)	{	case 'V':	  printf ("ping - %s %s\n", PACKAGE_NAME, PACKAGE_VERSION);	  printf ("Copyright (C) 1998,2001 Free Software Foundation, Inc.\n");	  printf ("%s comes with ABSOLUTELY NO WARRANTY.\n", PACKAGE_NAME);	  printf ("You may redistribute copies of %s\n", PACKAGE_NAME);	  printf ("under the terms of the GNU General Public License.\n");	  printf ("For more information about these matters, ");	  printf ("see the files named COPYING.\n");	  exit (0);	  break;	  	case 'L':	  show_license ();	  exit (0);	  	case 'h':	  show_usage ();	  exit (0);	  break;	  	case 'c':	  ping_set_count (ping, atoi (optarg));	  break;	  	case 'd':	  ping_set_sockopt (ping, SO_DEBUG, &one, sizeof (one));	  break;	  	case 'r':	  ping_set_sockopt (ping, SO_DONTROUTE, &one, sizeof (one));	  break;	  	case 'i':	  options |= OPT_INTERVAL;	  ping_set_interval (ping, atoi (optarg));	  break;	  	case 'p':	  decode_pattern (optarg, &pattern_len, pattern);	  patptr = pattern;	  break;	   	case 's':	  data_length = atoi (optarg); 	  break;	  	case 'n':	  options |= OPT_NUMERIC;	  break;	  	case 'q':	  options |= OPT_QUIET;	  break;	  	case 'R':	  options |= OPT_RROUTE;	  break;	          case 'v':	  options |= OPT_VERBOSE;	  break;	  	case 'l':	  if (!is_root)	    {	      fprintf (stderr, "ping: option not allowed: --preload\n");	      exit (1);	    }	  preload = strtoul (optarg, &p, 0);	  if (*p || preload > INT_MAX)	    {	      fprintf (stderr, "ping: invalid preload value (%s)\n", optarg);	      exit (1);	    }	  break;	case 'f':	  if (!is_root)	    {	      fprintf (stderr, "ping: option not allowed: --flood\n");	      exit (1);	    }	  options |= OPT_FLOOD;	  setbuf (stdout, (char *)NULL);	  break;	case 't':	  decode_type (optarg);	  break;	case ICMP_ECHO:	  decode_type ("echo");	  break;	  	case ICMP_TIMESTAMP:	  decode_type ("timestamp");	  break;	  	case ICMP_ADDRESS:	  decode_type ("address");	  break;	  	case ICMP_ROUTERDISCOVERY:	  decode_type ("router");	  break;	  	default:	  fprintf (stderr, "%c: not implemented\n", c);	  exit (1);	}    }  argc -= optind;  argv += optind;  if (argc == 0)     {      show_usage ();      exit (0);    }  init_data_buffer (patptr, pattern_len);  return (*ping_type)(argc, argv);}voidinit_data_buffer (u_char *pat, int len){  int i = 0;  u_char *p;  if (data_length == 0)    return;  data_buffer = malloc (data_length);  if (!data_buffer)    {      fprintf (stderr, "ping: out of memory\n");      exit (1);    }  if (pat)    {      for (p = data_buffer; p < data_buffer + data_length; p++)	{	  *p = pat[i];	  if (i++ >= len)	    i = 0;	}    }  else    {      for (i = 0; i < data_length; i++)	data_buffer[i] = i;    }}  voiddecode_type (const char *optarg){  if (strcasecmp (optarg, "echo") == 0)    ping_type = ping_echo;  else if (strcasecmp (optarg, "timestamp") == 0)    ping_type = ping_timestamp;  else if (strcasecmp (optarg, "address") == 0)    ping_type = ping_address;#if 0    else if (strcasecmp (optarg, "router") == 0)    ping_type = ping_router;#endif    else    {      fprintf (stderr, "unsupported packet type: %s\n", optarg);      exit (1);    }}voiddecode_pattern (const char *text, int *pattern_len, u_char *pattern_data){  int i, c, off;  for (i = 0; *text && i < *pattern_len; i++)    {      if (sscanf (text, "%2x%n", &c, &off) != 1)	{	  fprintf (stderr, "ping: error in pattern near %s\n", text);	  exit (1);	}      text += off;    }  *pattern_len = i;}int volatile stop = 0;RETSIGTYPEsig_int (int signal){  stop = 1;}intping_run (PING *ping, int (*finish)()){  fd_set fdset;  int fdmax;  struct timeval timeout;  struct timeval last, intvl, now;  struct timeval *t = NULL;  int finishing = 0;    signal (SIGINT, sig_int);    fdmax = ping->ping_fd+1;  while (preload--)          send_echo (ping);  if (options & OPT_FLOOD)    {      intvl.tv_sec = 0;      intvl.tv_usec = 10000;    }  else    {      intvl.tv_sec = ping->ping_interval;      intvl.tv_usec = 0;    }    gettimeofday (&last, NULL);  send_echo (ping);  while (!stop)    {      int n, len;            FD_ZERO (&fdset);      FD_SET (ping->ping_fd, &fdset);      gettimeofday (&now, NULL);      timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;      timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;      while (timeout.tv_usec < 0)	{	  timeout.tv_usec += 1000000;	  timeout.tv_sec--;	}      while (timeout.tv_usec >= 1000000)	{	  timeout.tv_usec -= 1000000;	  timeout.tv_sec++;	}      if (timeout.tv_sec < 0)	timeout.tv_sec = timeout.tv_usec = 0;            if ((n = select (fdmax, &fdset, NULL, NULL, &timeout)) < 0)	{	  if (errno != EINTR)	    perror ("ping: select");	  continue;	}      else if (n == 1)	{	  len = ping_recv (ping);	  if (t == 0)	    {	      gettimeofday (&now, NULL);	      t = &now;	    }	  if (ping->ping_count && ping->ping_num_recv >= ping->ping_count)	    break;	}      else	{	  if (!ping->ping_count || ping->ping_num_recv < ping->ping_count)	    {	      send_echo (ping);	      if (!(options & OPT_QUIET) && options & OPT_FLOOD)		{		  putchar ('.');		}	    }	  else if (finishing)	    break;	  else	    {	      finishing = 1;	      intvl.tv_sec = MAXWAIT;	    }	  gettimeofday (&last, NULL);	}    }  if (finish)    return (*finish)();  return 0;}intsend_echo (PING *ping){  int off = 0;    if (PING_TIMING (data_length))    {      struct timeval tv;      gettimeofday (&tv, NULL);      ping_set_data (ping, &tv, 0, sizeof (tv));      off += sizeof (tv);    }  if (data_buffer)    ping_set_data (ping, data_buffer, off,		  data_length > PING_HEADER_LEN ?		    data_length-PING_HEADER_LEN : data_length);  return ping_xmit (ping);}intping_finish (){  fflush (stdout);  printf ("--- %s ping statistics ---\n", ping->ping_hostname);  printf ("%ld packets transmitted, ", ping->ping_num_xmit);  printf ("%ld packets received, ", ping->ping_num_recv);  if (ping->ping_num_rept)    printf ("+%ld duplicates, ", ping->ping_num_rept);    if (ping->ping_num_xmit)    {      if (ping->ping_num_recv > ping->ping_num_xmit)	printf ("-- somebody's printing up packets!");      else	printf ("%d%% packet loss",	       (int) (((ping->ping_num_xmit - ping->ping_num_recv) * 100) /		      ping->ping_num_xmit));    }  printf ("\n");  return 0;}voidshow_usage (void){  printf ("\Usage: ping [OPTION]... [ADDRESS]...\n\\n\Informational options:\n\  -h, --help         display this help and exit\n\  -L, --license      display license and exit\n\  -V, --version      output version information and exit\n\Options controlling ICMP request types:\n\  --echo             Send ICMP_ECHO requests (default)\n\  --address          Send ICMP_ADDRESS packets\n\  --timestamp        Send ICMP_TIMESTAMP packets\n\  --router           Send ICMP_ROUTERDISCOVERY packets\n\Options valid for all request types:\n\  -c, --count N      stop after sending N packets\n\  -d, --debug        set the SO_DEBUG option\n\  -i, --interval N   wait N seconds between sending each packet\n\  -n, --numeric      do not resolve host addresses\n\  -r, --ignore-routing  send directly to a host on an attached network\n\  -v, --verbose      verbose output\n\Options valid for --echo requests:\n\* -f, --flood        flood ping \n\* -l, --preload N    send N packets as fast as possible before falling into\n\                     normal mode of behavior\n\  -p, --pattern PAT  fill ICMP packet with given pattern (hex)\n\  -q, --quiet        quiet output\n\  -R, --route        record route\n\  -s, --size N       set number of data octets to send\n\\n\Options marked with an * are available only to super-user\n\\n\report bugs to " PACKAGE_BUGREPORT ".\n\");}voidshow_license (void){  static char license_text[] ="   This program is free software; you can redistribute it and/or modify\n""   it under the terms of the GNU General Public License as published by\n""   the Free Software Foundation; either version 2, or (at your option)\n""   any later version.\n""\n""   This program is distributed in the hope that it will be useful,\n""   but WITHOUT ANY WARRANTY; without even the implied warranty of\n""   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n""   GNU General Public License for more details.\n""\n""   You should have received a copy of the GNU General Public License\n""   along with this program; if not, write to the Free Software\n""   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n";  printf ("%s", license_text);}

⌨️ 快捷键说明

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