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

📄 ping_echo.c

📁 inetutils的源代码
💻 C
字号:
/* Copyright (C) 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 <math.h>#include <limits.h>#include "getopt.h"#include <icmp.h>#include <ping.h>#include <ping_impl.h>#define	NROUTES		9		/* number of record route slots */#ifndef MAX_IPOPTLEN# define MAX_IPOPTLEN 40#endifextern char *xstrdup (const char *);extern char *xmalloc (size_t);static int handler (int code, void *closure,		   struct sockaddr_in *dest, struct sockaddr_in *from,		   struct ip *ip, icmphdr_t *icmp, int datalen);int print_echo (int dup, struct ping_stat *stat,	      struct sockaddr_in *dest, struct sockaddr_in *from,	      struct ip *ip, icmphdr_t *icmp, int datalen);static int echo_finish (void);void print_icmp_header (struct sockaddr_in *from,			      struct ip *ip, icmphdr_t *icmp, int len);static void print_ip_data (struct ip *ip);static void print_ip_opt (struct ip *ip, int hlen);static void tvsub (struct timeval *out, struct timeval *in);intping_echo (int argc, char **argv){#ifdef IP_OPTIONS  char rspace[3 + 4 * NROUTES + 1];	/* record route space */#endif  struct ping_stat ping_stat;  if (options & OPT_FLOOD && options & OPT_INTERVAL)    {      fprintf (stderr,	      "ping: -f and -i incompatible options.\n");      return 2;    }  memset (&ping_stat, 0, sizeof (ping_stat));  ping_stat.tmin = 999999999.0;  ping_set_type (ping, ICMP_ECHO);  ping_set_packetsize (ping, data_length);  ping_set_event_handler (ping, handler, &ping_stat);  if (ping_set_dest (ping, *argv))    {      fprintf (stderr, "ping: unknown host\n");      exit (1);    }  if (options & OPT_RROUTE)    {#ifdef IP_OPTIONS      memset (rspace, 0, sizeof (rspace));      rspace[IPOPT_OPTVAL] = IPOPT_RR;      rspace[IPOPT_OLEN] = sizeof (rspace)-1;      rspace[IPOPT_OFFSET] = IPOPT_MINOFF;      if (setsockopt (ping->ping_fd, IPPROTO_IP,		     IP_OPTIONS, rspace, sizeof (rspace)) < 0)	{	  perror ("ping: record route");	  exit (2);	}#else      fprintf (stderr,	      "ping: record route not available in this implementation.\n");      exit (2);#endif /* IP_OPTIONS */    }  printf ("PING %s (%s): %d data bytes\n",	 ping->ping_hostname,	 inet_ntoa (ping->ping_dest.sin_addr),	 data_length);  return ping_run (ping, echo_finish);}inthandler (int code, void *closure,	struct sockaddr_in *dest, struct sockaddr_in *from,	struct ip *ip, icmphdr_t *icmp, int datalen){  switch (code)    {    case PEV_RESPONSE:    case PEV_DUPLICATE:      print_echo (code == PEV_DUPLICATE,		   (struct ping_stat*)closure, dest, from, ip, icmp, datalen);      break;    case PEV_NOECHO:;      print_icmp_header (from, ip, icmp, datalen);    }  return 0;}intprint_echo (int dupflag, struct ping_stat *ping_stat,	   struct sockaddr_in *dest, struct sockaddr_in *from,	   struct ip *ip, icmphdr_t *icmp, int datalen){  int hlen;  struct timeval tv;  int timing = 0;  double triptime = 0.0;  gettimeofday (&tv, NULL);  /* Length of IP header */  hlen = ip->ip_hl << 2;  /* Length of ICMP header+payload */  datalen -= hlen;  /* Do timing */  if (PING_TIMING (datalen-8))    {      struct timeval tv1, *tp;      timing++;      tp = (struct timeval *) icmp->icmp_data;      /* Avoid unaligned data: */      memcpy (&tv1, tp, sizeof (tv1));      tvsub (&tv, &tv1);      triptime = ((double)tv.tv_sec) * 1000.0 +	          ((double)tv.tv_usec) / 1000.0;      ping_stat->tsum += triptime;      ping_stat->tsumsq += triptime*triptime;      if (triptime < ping_stat->tmin)	ping_stat->tmin = triptime;      if (triptime > ping_stat->tmax)	ping_stat->tmax = triptime;    }  if (options & OPT_QUIET)    return 0;  if (options & OPT_FLOOD)    {      putchar ('\b');      return 0;    }  printf ("%d bytes from %s: icmp_seq=%u", datalen,	 inet_ntoa (*(struct in_addr *)&from->sin_addr.s_addr),	 icmp->icmp_seq);  printf (" ttl=%d", ip->ip_ttl);  if (timing)    printf (" time=%.3f ms", triptime);  if (dupflag)    printf (" (DUP!)");  print_ip_opt (ip, hlen);  printf ("\n");  return 0;}char *ipaddr2str (struct in_addr ina){  struct hostent *hp;  if (options & OPT_NUMERIC      || !(hp = gethostbyaddr ((char *)&ina, 4, AF_INET)))    return xstrdup (inet_ntoa (ina));  else    {      char *ipstr = inet_ntoa (ina);      int len = strlen (hp->h_name) + 1;      char *buf;            if (ipstr)	len += strlen (ipstr) + 3; /* a pair of parentheses and a space */      buf = xmalloc (len);      if (ipstr)	snprintf (buf, len, "%s (%s)", hp->h_name, ipstr);      else	snprintf (buf, len, "%s", hp->h_name);      return buf;    }}voidprint_icmp_header (struct sockaddr_in *from,		  struct ip *ip, icmphdr_t *icmp, int len){  int hlen;  struct ip *orig_ip;  char *s;    /* Length of the IP header */  hlen = ip->ip_hl << 2;  /* Original IP header */  orig_ip = &icmp->icmp_ip;  if (!(options & OPT_VERBOSE	|| orig_ip->ip_dst.s_addr == ping->ping_dest.sin_addr.s_addr))    return;  printf ("%d bytes from %s: ", len-hlen, s = ipaddr2str (from->sin_addr));  free (s);    switch (icmp->icmp_type)    {    case ICMP_ECHOREPLY:      printf ("Echo Reply\n");      break;    case ICMP_DEST_UNREACH:      switch (icmp->icmp_code)	{	case ICMP_NET_UNREACH:	  printf ("Destination Net Unreachable\n");	  break;	case ICMP_HOST_UNREACH:	  printf ("Destination Host Unreachable\n");	  break;	case ICMP_PROT_UNREACH:	  printf ("Destination Protocol Unreachable\n");	  break;	case ICMP_PORT_UNREACH:	  printf ("Destination Port Unreachable\n");	  break;	case ICMP_FRAG_NEEDED:	  printf ("frag needed and DF set\n");	  break;	case ICMP_SR_FAILED:	  printf ("Source Route Failed\n");	  break;	case ICMP_NET_UNKNOWN:	  printf ("Network Unknown\n");	  break;	case ICMP_HOST_UNKNOWN:	  printf ("Host Unknown\n");	  break;	case ICMP_HOST_ISOLATED:	  printf ("Host Isolated\n");	  break;	case ICMP_NET_UNR_TOS:	  printf ("Destination Network Unreachable At This TOS\n");	  break;	case ICMP_HOST_UNR_TOS:	  printf ("Destination Host Unreachable At This TOS\n");	  break;#ifdef ICMP_PKT_FILTERED	case ICMP_PKT_FILTERED:	  printf ("Packet Filtered\n");	  break;#endif#ifdef ICMP_PREC_VIOLATION	case ICMP_PREC_VIOLATION:	  printf ("Precedence Violation\n");	  break;#endif#ifdef ICMP_PREC_CUTOFF	case ICMP_PREC_CUTOFF:	  printf ("Precedence Cutoff\n");	  break;#endif	default:	  printf ("Dest Unreachable, Unknown Code: %d\n",		 icmp->icmp_code);	  break;	}      /* Print returned IP header information */      print_ip_data (ip);      break;    case ICMP_SOURCE_QUENCH:      printf ("Source Quench\n");      print_ip_data (ip);      break;    case ICMP_REDIRECT:      switch (icmp->icmp_code)	{	case ICMP_REDIR_NET:	  printf ("Redirect Network");	  break;	case ICMP_REDIR_HOST:	  printf ("Redirect Host");	  break;	case ICMP_REDIR_NETTOS:	  printf ("Redirect Type of Service and Network");	  break;	case ICMP_REDIR_HOSTTOS:	  printf ("Redirect Type of Service and Host");	  break;	default:	  printf ("Redirect, Bad Code: %d", icmp->icmp_code);	  break;	}      printf ("(New addr: %s)\n",	     inet_ntoa (icmp->icmp_gwaddr));      print_ip_data (ip);      break;    case ICMP_ECHO:      printf ("Echo Request\n");      /* XXX ID + Seq + Data */      break;    case ICMP_TIME_EXCEEDED:      switch (icmp->icmp_code)	{	case ICMP_EXC_TTL:	  printf ("Time to live exceeded\n");	  break;	case ICMP_EXC_FRAGTIME:	  printf ("Frag reassembly time exceeded\n");	  break;	default:	  printf ("Time exceeded, Bad Code: %d\n",		 icmp->icmp_code);	  break;	}      print_ip_data (ip);      break;    case ICMP_PARAMETERPROB:      printf ("Parameter problem: IP address = %s\n",	     inet_ntoa (icmp->icmp_gwaddr));      print_ip_data (ip);      break;    case ICMP_TIMESTAMP:      printf ("Timestamp\n");      /* XXX ID + Seq + 3 timestamps */      break;    case ICMP_TIMESTAMPREPLY:      printf ("Timestamp Reply\n");      /* XXX ID + Seq + 3 timestamps */      break;    case ICMP_INFO_REQUEST:      printf ("Information Request\n");      /* XXX ID + Seq */      break;    case ICMP_INFO_REPLY:      printf ("Information Reply\n");      /* XXX ID + Seq */      break;#ifdef ICMP_MASKREQ    case ICMP_MASKREQ:      printf ("Address Mask Request\n");      break;#endif#ifdef ICMP_MASKREPLY    case ICMP_MASKREPLY:      printf ("Address Mask Reply\n");      break;#endif    default:      printf ("Bad ICMP type: %d\n", icmp->icmp_type);    }}static voidprint_ip_header (struct ip *ip){  int hlen;  u_char *cp;  hlen = ip->ip_hl << 2;  cp = (u_char *)ip + 20;		/* point to options */  printf ("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");  printf (" %1x  %1x  %02x %04x %04x",	 ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);  printf ("   %1x %04x", ((ip->ip_off) & 0xe000) >> 13,	 (ip->ip_off) & 0x1fff);  printf ("  %02x  %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum);  printf (" %s ", inet_ntoa (*((struct in_addr *) &ip->ip_src)));  printf (" %s ", inet_ntoa (*((struct in_addr *) &ip->ip_dst)));  /* dump and option bytes */  while (hlen-- > 20) {    printf ("%02x", *cp++);  }  printf ("\n");}voidprint_ip_data (struct ip *ip){  int hlen;  u_char *cp;  print_ip_header (ip);  hlen = ip->ip_hl << 2;  cp = (u_char *)ip + hlen;  if (ip->ip_p == 6)    printf ("TCP: from port %u, to port %u (decimal)\n",	   (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));  else if (ip->ip_p == 17)    printf ("UDP: from port %u, to port %u (decimal)\n",	   (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));}voidprint_ip_opt (struct ip *ip, int hlen){  u_char *cp;  int i, j, l;  static int old_rrlen;  static char old_rr[MAX_IPOPTLEN];  cp = (u_char *)(ip + 1);  for (; hlen > (int)sizeof (struct ip); --hlen, ++cp)    switch (*cp)      {      case IPOPT_EOL:	hlen = 0;	break;      case IPOPT_LSRR:	printf ("\nLSRR: ");	hlen -= 2;	j = *++cp;	++cp;	if (j > IPOPT_MINOFF)	  for (;;)	    {	      l = *++cp;	      l = (l<<8) + *++cp;	      l = (l<<8) + *++cp;	      l = (l<<8) + *++cp;	      if (l == 0)		{		  printf ("\t0.0.0.0");		}	      else		{		  struct in_addr ina;		  char *s;		  		  ina.s_addr = ntohl (l);		  printf ("\t%s", s = ipaddr2str (ina));		  free (s);		}	      hlen -= 4;	      j -= 4;	      if (j <= IPOPT_MINOFF)		break;	      putchar ('\n');	    }	break;      case IPOPT_RR:	j = *++cp;		/* get length */	i = *++cp;		/* and pointer */	hlen -= 2;	if (i > j)	  i = j;	i -= IPOPT_MINOFF;	if (i <= 0)	  continue;	if (i == old_rrlen	    && cp == (u_char *)(ip + 1) + 2	    && !memcmp ((char *)cp, old_rr, i)	    && !(options & OPT_FLOOD))	  {	    printf ("\t (same route)");	    i = ((i + 3) / 4) * 4;	    hlen -= i;	    cp += i;	    break;	  }	if (i < MAX_IPOPTLEN)	  {	    old_rrlen = i;	    memmove (old_rr, cp, i);	  }	else	  old_rrlen = 0;	printf ("\nRR: ");	j = 0;	for (;;)	  {	    l = *++cp;	    l = (l<<8) + *++cp;	    l = (l<<8) + *++cp;	    l = (l<<8) + *++cp;	    if (l == 0)	      {		printf ("\t0.0.0.0");	      }	    else	      {		struct in_addr ina;		char *s;		  		ina.s_addr = ntohl (l);		printf ("\t%s", s = ipaddr2str (ina));		free (s);	      }	    hlen -= 4;	    i -= 4;	    j += 4;	    if (i <= 0)	      break;	    if (j >= MAX_IPOPTLEN)	      {		printf ("\t (truncated route)");		break;	      }	    putchar ('\n');	  }	break;      case IPOPT_NOP:	printf ("\nNOP");	break;      default:	printf ("\nunknown option %x", *cp);	break;      }}/* * tvsub -- *	Subtract 2 timeval structs:  out = out - in.  Out is assumed to * be >= in. */static voidtvsub (out, in)	register struct timeval *out, *in;{	if ((out->tv_usec -= in->tv_usec) < 0) {		--out->tv_sec;		out->tv_usec += 1000000;	}	out->tv_sec -= in->tv_sec;}intecho_finish (){  ping_finish ();  if (ping->ping_num_recv && PING_TIMING (data_length))    {      struct ping_stat *ping_stat = (struct ping_stat*)ping->ping_closure;      double total = ping->ping_num_recv + ping->ping_num_rept;      double avg = ping_stat->tsum/total;      double vari = ping_stat->tsumsq / total - avg * avg;      printf ("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",	     ping_stat->tmin,	     avg,	     ping_stat->tmax,	     sqrt (vari));    }  exit (ping->ping_num_recv == 0);}

⌨️ 快捷键说明

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