📄 ping.c
字号:
t1->tv_sec++; t1->tv_usec -= 1000000; }}static voidsec_to_timeval(const double sec, struct timeval *tp){ tp->tv_sec = sec; tp->tv_usec = (sec - tp->tv_sec) * 1000000.0;}static doubletimeval_to_sec(const struct timeval *tp){ return tp->tv_sec + tp->tv_usec / 1000000.0;}/* * Print statistics. * Heavily buffered STDIO is used here, so that all the statistics * will be written with 1 sys-write call. This is nice when more * than one copy of the program is running on a terminal; it prevents * the statistics output from becomming intermingled. */static voidsummary(int header){ jiggle_flush(1); if (header) (void)printf("\n----%s PING Statistics----\n", hostname); (void)printf("%d packets transmitted, ", ntransmitted); (void)printf("%d packets received, ", nreceived); if (nrepeats) (void)printf("+%d duplicates, ", nrepeats); if (ntransmitted) { if (nreceived > ntransmitted) (void)printf("-- somebody's duplicating packets!"); else (void)printf("%.1f%% packet loss", (((ntransmitted-nreceived)*100.0) / ntransmitted)); } (void)printf("\n"); if (nreceived && (pingflags & F_TIMING)) { double n = nreceived + nrepeats; double avg = (tsum / n); double variance = 0.0; if (n>1) variance = (tsumsq - n*avg*avg) /(n-1); printf("round-trip min/avg/max/stddev = " "%.3f/%.3f/%.3f/%.3f ms\n", tmin * 1000.0, avg * 1000.0, tmax * 1000.0, sqrt(variance) * 1000.0); if (pingflags & F_FLOOD) { double r = diffsec(&last_rx, &first_rx); double t = diffsec(&last_tx, &first_tx); if (r == 0) r = 0.0001; if (t == 0) t = 0.0001; (void)printf(" %.1f packets/sec sent, " " %.1f packets/sec received\n", ntransmitted/t, nreceived/r); } }}/* * Print statistics when SIGINFO is received. *//* ARGSUSED */static voidprtsig(int dummy){ summary(0);#ifdef SIGINFO (void)signal(SIGINFO, prtsig);#else (void)signal(SIGQUIT, prtsig);#endif}/* * On the first SIGINT, allow any outstanding packets to dribble in */static voidprefinish(int dummy){ if (lastrcvd /* quit now if caught up */ || nreceived == 0) /* or if remote is dead */ finish(0); (void)signal(dummy, finish); /* do this only the 1st time */ if (npackets > ntransmitted) /* let the normal limit work */ npackets = ntransmitted;}/* * Print statistics and give up. *//* ARGSUSED */static voidfinish(int dummy){#if defined(SIGINFO) && defined(NOKERNINFO) struct termios ts; if (reset_kerninfo && tcgetattr (0, &ts) != -1) { ts.c_lflag &= ~NOKERNINFO; tcsetattr (STDIN_FILENO, TCSANOW, &ts); } (void)signal(SIGINFO, SIG_IGN);#else (void)signal(SIGQUIT, SIG_DFL);#endif summary(1); exit(nreceived > 0 ? 0 : 2);}static int /* 0=do not print it */ck_pr_icmph(struct icmp *icp, struct sockaddr_in *from, int cc, int override) /* 1=override VERBOSE if interesting */{ int hlen; struct ip ipb, *ip = &ipb; struct icmp icp2b, *icp2 = &icp2b; int res; if (pingflags & F_VERBOSE) { res = 1; jiggle_flush(1); } else { res = 0; } (void) memcpy(ip, icp->icmp_data, sizeof(*ip)); hlen = ip->ip_hl << 2; if (ip->ip_p == IPPROTO_ICMP && hlen + 6 <= cc) { (void) memcpy(icp2, &icp->icmp_data[hlen], sizeof(*icp2)); if (icp2->icmp_id == ident) { /* remember to clear route cached in kernel * if this non-Echo-Reply ICMP message was for one * of our packets. */ clear_cache.tv_sec = 0; if (!res && override && (pingflags & (F_QUIET|F_SEMI_QUIET)) == 0) { jiggle_flush(1); (void)printf("%d bytes from %s: ", cc, pr_addr(&from->sin_addr)); res = 1; } } } return res;}/* * Print a descriptive string about an ICMP header other than an echo reply. */static int /* 0=printed nothing */pr_icmph(struct icmp *icp, struct sockaddr_in *from, int cc){ switch (icp->icmp_type ) { case ICMP_UNREACH: if (!ck_pr_icmph(icp, from, cc, 1)) return 0; switch (icp->icmp_code) { case ICMP_UNREACH_NET: (void)printf("Destination Net Unreachable"); break; case ICMP_UNREACH_HOST: (void)printf("Destination Host Unreachable"); break; case ICMP_UNREACH_PROTOCOL: (void)printf("Destination Protocol Unreachable"); break; case ICMP_UNREACH_PORT: (void)printf("Destination Port Unreachable"); break; case ICMP_UNREACH_NEEDFRAG: (void)printf("frag needed and DF set. Next MTU=%d", ntohs(icp->icmp_nextmtu)); break; case ICMP_UNREACH_SRCFAIL: (void)printf("Source Route Failed"); break; case ICMP_UNREACH_NET_UNKNOWN: (void)printf("Unreachable unknown net"); break; case ICMP_UNREACH_HOST_UNKNOWN: (void)printf("Unreachable unknown host"); break; case ICMP_UNREACH_ISOLATED: (void)printf("Unreachable host isolated"); break; case ICMP_UNREACH_NET_PROHIB: (void)printf("Net prohibited access"); break; case ICMP_UNREACH_HOST_PROHIB: (void)printf("Host prohibited access"); break; case ICMP_UNREACH_TOSNET: (void)printf("Bad TOS for net"); break; case ICMP_UNREACH_TOSHOST: (void)printf("Bad TOS for host"); break; case 13: (void)printf("Communication prohibited"); break; case 14: (void)printf("Host precedence violation"); break; case 15: (void)printf("Precedence cutoff"); break; default: (void)printf("Bad Destination Unreachable Code: %d", icp->icmp_code); break; } /* Print returned IP header information */ pr_retip(icp, cc); break; case ICMP_SOURCEQUENCH: if (!ck_pr_icmph(icp, from, cc, 1)) return 0; (void)printf("Source Quench"); pr_retip(icp, cc); break; case ICMP_REDIRECT: if (!ck_pr_icmph(icp, from, cc, 1)) return 0; switch (icp->icmp_code) { case ICMP_REDIRECT_NET: (void)printf("Redirect Network"); break; case ICMP_REDIRECT_HOST: (void)printf("Redirect Host"); break; case ICMP_REDIRECT_TOSNET: (void)printf("Redirect Type of Service and Network"); break; case ICMP_REDIRECT_TOSHOST: (void)printf("Redirect Type of Service and Host"); break; default: (void)printf("Redirect--Bad Code: %d", icp->icmp_code); break; } (void)printf(" New router addr: %s", pr_addr(&icp->icmp_hun.ih_gwaddr)); pr_retip(icp, cc); break; case ICMP_ECHO: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Echo Request: ID=%d seq=%d", ntohs(icp->icmp_id), ntohs(icp->icmp_seq)); break; case ICMP_ECHOREPLY: /* displaying other's pings is too noisey */#if 0 if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Echo Reply: ID=%d seq=%d", ntohs(icp->icmp_id), ntohs(icp->icmp_seq)); break;#else return 0;#endif case ICMP_ROUTERADVERT: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Router Discovery Advert"); break; case ICMP_ROUTERSOLICIT: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Router Discovery Solicit"); break; case ICMP_TIMXCEED: if (!ck_pr_icmph(icp, from, cc, 1)) return 0; switch (icp->icmp_code ) { case ICMP_TIMXCEED_INTRANS: (void)printf("Time To Live exceeded"); break; case ICMP_TIMXCEED_REASS: (void)printf("Frag reassembly time exceeded"); break; default: (void)printf("Time exceeded, Bad Code: %d", icp->icmp_code); break; } pr_retip(icp, cc); break; case ICMP_PARAMPROB: if (!ck_pr_icmph(icp, from, cc, 1)) return 0; (void)printf("Parameter problem: pointer = 0x%02x", icp->icmp_hun.ih_pptr); pr_retip(icp, cc); break; case ICMP_TSTAMP: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Timestamp"); break; case ICMP_TSTAMPREPLY: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Timestamp Reply"); break; case ICMP_IREQ: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Information Request"); break; case ICMP_IREQREPLY: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Information Reply"); break; case ICMP_MASKREQ: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Address Mask Request"); break; case ICMP_MASKREPLY: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Address Mask Reply"); break; default: if (!ck_pr_icmph(icp, from, cc, 0)) return 0; (void)printf("Bad ICMP type: %d", icp->icmp_type); if (pingflags & F_VERBOSE) pr_iph(icp, cc); } return 1;}/* * Print an IP header with options. */static voidpr_iph(struct icmp *icp, int cc){ int hlen; u_char *cp; struct ip ipb, *ip = &ipb; (void) memcpy(ip, icp->icmp_data, sizeof(*ip)); hlen = ip->ip_hl << 2; cp = (u_char *) &icp->icmp_data[20]; /* point to options */ (void)printf("\n Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n"); (void)printf(" %1x %1x %02x %04x %04x", ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); (void)printf(" %1x %04x", ((ip->ip_off)&0xe000)>>13, (ip->ip_off)&0x1fff); (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); (void)printf(" %15s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); /* dump any option bytes */ while (hlen-- > 20 && cp < (u_char*)icp+cc) { (void)printf("%02x", *cp++); }}/* * Print an ASCII host address starting from a string of bytes. */static voidpr_saddr(u_char *cp){ n_long l; struct in_addr addr; l = (u_char)*++cp; l = (l<<8) + (u_char)*++cp; l = (l<<8) + (u_char)*++cp; l = (l<<8) + (u_char)*++cp; addr.s_addr = htonl(l); (void)printf("\t%s", (l == 0) ? "0.0.0.0" : pr_addr(&addr));}/* * Return an ASCII host address * as a dotted quad and optionally with a hostname */static char *pr_addr(struct in_addr *addr) /* in network order */{ struct hostent *hp; static char buf[MAXHOSTNAMELEN+4+16+1]; if ((pingflags & F_NUMERIC) || !(hp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET))) { (void)snprintf(buf, sizeof(buf), "%s", inet_ntoa(*addr)); } else { (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, inet_ntoa(*addr)); } return buf;}/* * Dump some info on a returned (via ICMP) IP packet. */static voidpr_retip(struct icmp *icp, int cc){ int hlen; u_char *cp; struct ip ipb, *ip = &ipb; (void) memcpy(ip, icp->icmp_data, sizeof(*ip)); if (pingflags & F_VERBOSE) pr_iph(icp, cc); hlen = ip->ip_hl << 2; cp = (u_char *) &icp->icmp_data[hlen]; if (ip->ip_p == IPPROTO_TCP) { if (pingflags & F_VERBOSE) (void)printf("\n TCP: from port %u, to port %u", (*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3))); } else if (ip->ip_p == IPPROTO_UDP) { if (pingflags & F_VERBOSE) (void)printf("\n UDP: from port %u, to port %u", (*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3))); } else if (ip->ip_p == IPPROTO_ICMP) { struct icmp icp2; (void) memcpy(&icp2, cp, sizeof(icp2)); if (icp2.icmp_type == ICMP_ECHO) { if (pingflags & F_VERBOSE) (void)printf("\n ID=%u icmp_seq=%u", ntohs((u_int16_t)icp2.icmp_id), ntohs((u_int16_t)icp2.icmp_seq)); else (void)printf(" for icmp_seq=%u", ntohs((u_int16_t)icp2.icmp_seq)); } }}static voidfill(void){ int i, j, k; char *cp; int pat[16]; for (cp = fill_pat; *cp != '\0'; cp++) { if (!isxdigit((unsigned char)*cp)) break; } if (cp == fill_pat || *cp != '\0' || (cp-fill_pat) > 16*2) { (void)fflush(stdout); errx(1, "\"-p %s\": patterns must be specified with" " 1-32 hex digits\n", fill_pat); } i = sscanf(fill_pat, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], &pat[13], &pat[14], &pat[15]); for (k=PHDR_LEN, j = 0; k <= datalen; k++) { opack_icmp.icmp_data[k] = pat[j]; if (++j >= i) j = 0; } if (!(pingflags & F_QUIET)) { (void)printf("PATTERN: 0x"); for (j=0; j<i; j++) (void)printf("%02x", (u_char)opack_icmp.icmp_data[PHDR_LEN+j]); (void)printf("\n"); }}static voidrnd_fill(void){ static u_int32_t rnd; int i; for (i = PHDR_LEN; i < datalen; i++) { rnd = (3141592621U * rnd + 663896637U); opack_icmp.icmp_data[i] = rnd>>24; }}static voidgethost(const char *arg, const char *name, struct sockaddr_in *sa, char *realname, int realname_len){ struct hostent *hp; (void)memset(sa, 0, sizeof(*sa)); sa->sin_family = AF_INET; sa->sin_len = sizeof(struct sockaddr_in); /* If it is an IP address, try to convert it to a name to * have something nice to display. */ if (inet_aton(name, &sa->sin_addr) != 0) { if (realname) { if (pingflags & F_NUMERIC) hp = 0; else hp = gethostbyaddr((char *)&sa->sin_addr, sizeof(sa->sin_addr), AF_INET); (void)strlcpy(realname, hp ? hp->h_name : name, realname_len); } return; } hp = gethostbyname(name); if (!hp) errx(1, "Cannot resolve \"%s\" (%s)",name,hstrerror(h_errno)); if (hp->h_addrtype != AF_INET) errx(1, "%s only supported with IP", arg); (void)memcpy(&sa->sin_addr, hp->h_addr, sizeof(sa->sin_addr)); if (realname) (void)strlcpy(realname, hp->h_name, realname_len);}static voidusage(void){#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC#define IPSECOPT "\n [-E policy] "#else#define IPSECOPT "\n [-AE] "#endif /*IPSEC_POLICY_IPSEC*/#else#define IPSECOPT ""#endif /*IPSEC*/ (void)fprintf(stderr, "usage: \n" "%s [-adDfLnoPqQrRv] [-c count] [-g gateway] [-h host]" " [-i interval] [-I addr]\n" " [-l preload] [-p pattern] [-s size] [-t tos] [-T ttl]" " [-w maxwait] " IPSECOPT "host\n", getprogname()); exit(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -