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

📄 ping6.c

📁 linux下常用的网络工具的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
      timing++;      tp = (struct timeval *) icmp6 + 1;      /* 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;    }  err = getnameinfo ((struct sockaddr *) from, sizeof (*from), buf,		     sizeof (buf), NULL, 0, 0);  if (err)    {      const char *errmsg;            if (err == EAI_SYSTEM)	errmsg = strerror (errno);      else	errmsg = gai_strerror (err);      fprintf (stderr, "ping: getnameinfo: %s\n", errmsg);      strcpy (buf, "unknown");    }  printf ("%d bytes from %s: icmp_seq=%u", datalen, buf, htons (icmp6->icmp6_seq));  if (hops >= 0)    printf (" ttl=%d", hops);  if (timing)    printf (" time=%.3f ms", triptime);  if (dupflag)    printf (" (DUP!)");  putchar ('\n');  return 0;}#define NITEMS(a) sizeof(a)/sizeof((a)[0])struct icmp_code_descr {  int code;  char *diag;};static struct icmp_code_descr icmp_dest_unreach_desc[] = {  { ICMP6_DST_UNREACH_NOROUTE, "No route to destination" },  { ICMP6_DST_UNREACH_ADMIN, "Destination administratively prohibited" },  { ICMP6_DST_UNREACH_BEYONDSCOPE, "Beyond scope of source address"  },  { ICMP6_DST_UNREACH_ADDR, "Address unreachable" },  { ICMP6_DST_UNREACH_NOPORT, "Port unreachable" },};static voidprint_dst_unreach (struct icmp6_hdr *icmp6){  struct icmp_code_descr *p;  printf ("Destination unreachable: ");  for (p = icmp_dest_unreach_desc;       p < icmp_dest_unreach_desc + NITEMS(icmp_dest_unreach_desc);       p++)    {      if (p->code == icmp6->icmp6_code)	{	  puts (p->diag);	  return;	}    }  printf ("Unknown code %d\n", icmp6->icmp6_code);}static voidprint_packet_too_big (struct icmp6_hdr *icmp6){  printf ("Packet too big, mtu=%d\n", icmp6->icmp6_mtu);}static struct icmp_code_descr icmp_time_exceeded_desc[] = {  { ICMP6_TIME_EXCEED_TRANSIT, "Hop limit exceeded"},  { ICMP6_TIME_EXCEED_REASSEMBLY, "Fragment reassembly timeout"},};static voidprint_time_exceeded (struct icmp6_hdr *icmp6){  struct icmp_code_descr *p;  printf ("Time exceeded: ");  for (p = icmp_time_exceeded_desc;       p < icmp_time_exceeded_desc + NITEMS(icmp_time_exceeded_desc);       p++)    {      if (p->code == icmp6->icmp6_code)	{	  puts (p->diag);	  return;	}    }  printf ("Unknown code %d\n", icmp6->icmp6_code);}static struct icmp_code_descr icmp_param_prob_desc[] = {  { ICMP6_PARAMPROB_HEADER, "Erroneous header field"},  { ICMP6_PARAMPROB_NEXTHEADER, "Unrecognized Next Header type"},  { ICMP6_PARAMPROB_OPTION, "Unrecognized IPv6 option"},};static voidprint_param_prob (struct icmp6_hdr *icmp6){  struct icmp_code_descr *p;  printf ("Parameter problem: ");  for (p = icmp_param_prob_desc;       p < icmp_param_prob_desc + NITEMS(icmp_param_prob_desc);       p++)    {      if (p->code == icmp6->icmp6_code)	{	  puts (p->diag);	  return;	}    }  printf ("Unknown code %d\n", icmp6->icmp6_code);}static struct icmp_diag {  int type;  void (*func) (struct icmp6_hdr *);} icmp_diag[] = {  { ICMP6_DST_UNREACH, print_dst_unreach },  { ICMP6_PACKET_TOO_BIG, print_packet_too_big },  { ICMP6_TIME_EXCEEDED, print_time_exceeded },  { ICMP6_PARAM_PROB, print_param_prob },};static voidprint_icmp_error (struct sockaddr_in6 *from,		  struct icmp6_hdr *icmp6, int len){  char *s;  struct icmp_diag *p;    s = ipaddr2str (from);  printf ("%d bytes from %s: ", len, s);  free (s);  for (p = icmp_diag; p < icmp_diag + NITEMS(icmp_diag); p++)    {      if (p->type == icmp6->icmp6_type)	{	  p->func (icmp6);	  return;	}    }  /* This should never happen because of the ICMP6_FILTER set in     ping_init(). */  printf ("Unknown ICMP type: %d\n", icmp6->icmp6_type);}static 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, nsqrt (vari, 0.0005));    }  exit (ping->ping_num_recv == 0);}static voidshow_usage (void){  printf ("\Usage: ping6 [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 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\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\  -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\");}static PING *ping_init (int type, int ident){  int fd, err;  const int on = 1;  PING *p;  struct icmp6_filter filter;  /* Initialize raw ICMPv6 socket */  fd = socket (PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);  if (fd < 0)     {      if (errno == EPERM) 	{	  fprintf (stderr, "ping: ping must run as root\n");	}      return NULL;    }  /* Tell which ICMPs we are interested in.  */  ICMP6_FILTER_SETBLOCKALL (&filter);  ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &filter);  ICMP6_FILTER_SETPASS (ICMP6_DST_UNREACH, &filter);  ICMP6_FILTER_SETPASS (ICMP6_PACKET_TOO_BIG, &filter);  ICMP6_FILTER_SETPASS (ICMP6_TIME_EXCEEDED, &filter);  ICMP6_FILTER_SETPASS (ICMP6_PARAM_PROB, &filter);  err = setsockopt (fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof (filter));  if (err)    {      close (fd);      return NULL;    }  err = setsockopt (fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof (on));  if (err)    {      close (fd);      return NULL;    }    /* Allocate PING structure and initialize it to default values */  p = malloc (sizeof (*p));  if (!p)    {      close (fd);      return NULL;    }  memset (p, 0, sizeof (*p));  p->ping_fd = fd;  p->ping_count = 0;  p->ping_interval = PING_INTERVAL;  p->ping_datalen = sizeof (struct icmp6_hdr);  /* Make sure we use only 16 bits in this field, id for icmp is a u_short.  */  p->ping_ident = ident & 0xFFFF;  p->ping_cktab_size = PING_CKTABSIZE;  return p;}static int_ping_setbuf (PING *p){  if (!p->ping_buffer)    {      p->ping_buffer = malloc (_PING_BUFLEN (p));      if (!p->ping_buffer)	return -1;    }  if (!p->ping_cktab)    {      p->ping_cktab = malloc (p->ping_cktab_size);      if (!p->ping_cktab)        return -1;      memset (p->ping_cktab, 0, p->ping_cktab_size);    }  return 0;}static intping_set_data (PING *p, void *data, size_t off, size_t len){  if (_ping_setbuf (p))    return -1;  if (p->ping_datalen < off + len)    return -1;  memcpy (p->ping_buffer + sizeof (struct icmp6_hdr) + off, data, len);  return 0;}static intping_xmit (PING *p){  int i, buflen;  struct icmp6_hdr *icmp6;  if (_ping_setbuf (p))    return -1;  buflen = p->ping_datalen + sizeof (struct icmp6_hdr);  /* Mark sequence number as sent */  _PING_CLR (p, p->ping_num_xmit % p->ping_cktab_size);  icmp6 = (struct icmp6_hdr *) p->ping_buffer;  icmp6->icmp6_type = ICMP6_ECHO_REQUEST;  icmp6->icmp6_code = 0;  /* The checksum will be calculated by the TCP/IP stack.  */  icmp6->icmp6_cksum = 0;   icmp6->icmp6_id = htons (p->ping_ident);  icmp6->icmp6_seq = htons (p->ping_num_xmit);  i = sendto (p->ping_fd, (char *)p->ping_buffer, buflen, 0,	      (struct sockaddr*) &p->ping_dest,	      sizeof (p->ping_dest));  if (i < 0)    perror ("ping: sendto");  else    {      p->ping_num_xmit++;      if (i != buflen)	printf ("ping: wrote %s %d chars, ret=%d\n",		p->ping_hostname, buflen, i);    }  return 0;}static intmy_echo_reply (PING *p, struct icmp6_hdr *icmp6){  struct ip6_hdr *orig_ip =     (struct ip6_hdr *) (icmp6 + 1);  struct icmp6_hdr *orig_icmp =     (struct icmp6_hdr *)(orig_ip + 1);  return IN6_ARE_ADDR_EQUAL (&orig_ip->ip6_dst, &ping->ping_dest.sin6_addr)    && orig_ip->ip6_nxt == IPPROTO_ICMPV6    && orig_icmp->icmp6_type == ICMP6_ECHO_REQUEST    && orig_icmp->icmp6_id == htons (p->ping_ident);}static intping_recv (PING *p){  int dupflag, n;  int hops = -1;  struct msghdr msg;  struct iovec iov;  struct icmp6_hdr *icmp6;  struct cmsghdr *cmsg;  char cmsg_data[1024];  iov.iov_base = p->ping_buffer;  iov.iov_len = _PING_BUFLEN (p);  msg.msg_name = &p->ping_from;  msg.msg_namelen = sizeof (p->ping_from);  msg.msg_iov = &iov;  msg.msg_iovlen = 1;  msg.msg_control = cmsg_data;  msg.msg_controllen = sizeof (cmsg_data);  msg.msg_flags = 0;    n = recvmsg (p->ping_fd, &msg, 0);  if (n < 0)    return -1;  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))    {      if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT)	{	  hops = *(int *)CMSG_DATA(cmsg);	  break;	}    }    icmp6 = (struct icmp6_hdr *) p->ping_buffer;  if (icmp6->icmp6_type == ICMP6_ECHO_REPLY)    {      /* We got an echo reply.  */      if (ntohs (icmp6->icmp6_id) != p->ping_ident)	return -1; /* It's not a response to us.  */      if (_PING_TST (p, ntohs (icmp6->icmp6_seq) % p->ping_cktab_size))	{	  /* We already got the reply for this echo request.  */	  p->ping_num_rept++;	  dupflag = 1;	}      else	{	  _PING_SET (p, ntohs (icmp6->icmp6_seq) % p->ping_cktab_size);	  p->ping_num_recv++;	  dupflag = 0;	}      print_echo (dupflag, hops, p->ping_closure, &p->ping_dest,		  &p->ping_from, icmp6, n);    }  else    {      /* We got an error reply.  */      if (!my_echo_reply (p, icmp6))	return -1; /* It's not for us.  */      print_icmp_error (&p->ping_from, icmp6, n);    }    return 0;}static intping_set_dest (PING *ping, char *host){  int err;  struct addrinfo *result, hints;    memset (&hints, 0, sizeof (hints));  hints.ai_family = AF_INET6;  err = getaddrinfo (host, NULL, &hints, &result);  if (err)    return 1;  memcpy (&ping->ping_dest, result->ai_addr, result->ai_addrlen);  freeaddrinfo (result);  ping->ping_hostname = strdup (host);  if (!ping->ping_hostname)    return 1;  return 0;}

⌨️ 快捷键说明

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