📄 ping6.c
字号:
/* Copyright (C) 1998, 2001, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <sys/socket.h>#include <sys/time.h>#include <signal.h>#include <netinet/in.h>#include <netinet/ip6.h>#include <netinet/icmp6.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 <xalloc.h>#include "ping_common.h"#include "ping6.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'}, /* echo-specific options */ {"flood", no_argument, NULL, 'f'}, {"preload", required_argument, NULL, 'l'}, {"pattern", required_argument, NULL, 'p'}, {"quiet", no_argument, NULL, 'q'}, {NULL, no_argument, NULL, 0}};static PING *ping;unsigned char *data_buffer;size_t data_length = PING_DATALEN;static unsigned int options;static unsigned long preload = 0;static int ping_echo (int argc, char **argv);static void show_usage (void);static int send_echo (PING *ping);char *program_name;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; program_name = argv[0]; if ((ping = ping_init (0, getpid ())) == NULL) { fprintf (stderr, "can't init ping: %s\n", strerror (errno)); exit (1); } setsockopt (ping->ping_fd, SOL_SOCKET, 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) 2005 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->ping_count = ping_cvt_number (optarg, 0, 0); break; case 'd': setsockopt (ping->ping_fd, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)); break; case 'r': setsockopt (ping->ping_fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof (one)); break; case 'i': options |= OPT_INTERVAL; ping->ping_interval = ping_cvt_number (optarg, 0, 0); break; case 'p': decode_pattern (optarg, &pattern_len, pattern); patptr = pattern; break; case 's': data_length = ping_cvt_number (optarg, PING_MAX_DATALEN, 1); break; case 'n': options |= OPT_NUMERIC; break; case 'q': options |= OPT_QUIET; 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; 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_echo (argc, argv);}static char *ipaddr2str (struct sockaddr_in6 *from){ int err; size_t len; char *buf, ipstr[256], hoststr[256]; err = getnameinfo ((struct sockaddr *) from, sizeof (*from), ipstr, sizeof (ipstr), NULL, 0, NI_NUMERICHOST); if (err) { const char *errmsg; if (err == EAI_SYSTEM) errmsg = strerror (errno); else errmsg = gai_strerror (err); fprintf (stderr, "ping: getnameinfo: %s\n", errmsg); return xstrdup ("unknown"); } if (options & OPT_NUMERIC) return xstrdup (ipstr); err = getnameinfo ((struct sockaddr *) from, sizeof (*from), hoststr, sizeof (hoststr), NULL, 0, NI_NAMEREQD); if (err) return xstrdup (ipstr); len = strlen (ipstr) + strlen (hoststr) + 4; /* Pair of parentheses, a space and a NUL. */ buf = xmalloc (len); sprintf (buf, "%s (%s)", hoststr, ipstr); return buf;}static volatile int stop = 0;static RETSIGTYPEsig_int (int signal){ stop = 1;}static 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; int nresp = 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; 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; n = select (fdmax, &fdset, NULL, NULL, &timeout); if (n < 0) { if (errno != EINTR) perror ("select"); continue; } else if (n == 1) { if (ping_recv (ping) == 0) nresp++; if (t == 0) { gettimeofday (&now, NULL); t = &now; } if (ping->ping_count && nresp >= ping->ping_count) break; } else { if (!ping->ping_count || ping->ping_num_xmit < 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;}static 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);}static 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;}static int print_echo (int dup, int hops, struct ping_stat *stat, struct sockaddr_in6 *dest, struct sockaddr_in6 *from, struct icmp6_hdr *icmp6, int datalen);static void print_icmp_error (struct sockaddr_in6 *from, struct icmp6_hdr *icmp6, int len);static int echo_finish (void);static intping_echo (int argc, char **argv){ int err; char buffer[256]; 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->ping_datalen = data_length; ping->ping_closure = &ping_stat; if (ping_set_dest (ping, *argv)) { fprintf (stderr, "ping: unknown host\n"); exit (1); } err = getnameinfo ((struct sockaddr *) &ping->ping_dest, sizeof (ping->ping_dest), buffer, sizeof (buffer), NULL, 0, NI_NUMERICHOST); if (err) { const char *errmsg; if (err == EAI_SYSTEM) errmsg = strerror (errno); else errmsg = gai_strerror (err); fprintf (stderr, "ping: getnameinfo: %s\n", errmsg); exit (1); } printf ("PING %s (%s): %d data bytes\n", ping->ping_hostname, buffer, data_length); return ping_run (ping, echo_finish);}static intprint_echo (int dupflag, int hops, struct ping_stat *ping_stat, struct sockaddr_in6 *dest, struct sockaddr_in6 *from, struct icmp6_hdr *icmp6, int datalen){ int err; char buf[256]; struct timeval tv; int timing = 0; double triptime = 0.0; gettimeofday (&tv, NULL); /* Do timing */ if (PING_TIMING (datalen - sizeof (struct icmp6_hdr))) { struct timeval tv1, *tp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -