📄 ping.c
字号:
if (timing) (void)gettimeofday((struct timeval *)&outpack[8], (struct timezone *)NULL); cc = datalen + 8; /* skips ICMP portion */ /* compute ICMP checksum here */ icp->icmp_cksum = in_cksum((u_short *)icp, cc); i = sendto(s, (char *)outpack, cc, 0, &whereto, sizeof(struct sockaddr)); if (i < 0 || i != cc) { if (i < 0) perror("ping: sendto"); (void)printf("ping: wrote %s %d chars, ret=%d\n", hostname, cc, i); } if (!(options & F_QUIET) && options & F_FLOOD) (void)write(STDOUT_FILENO, &DOT, 1);}/* * pr_pack -- * Print out the packet, if it came from us. This logic is necessary * because ALL readers of the ICMP socket get a copy of ALL ICMP packets * which arrive ('tis only fair). This permits multiple copies of this * program to be run without having intermingled output (or statistics!). */voidpr_pack(char *buf, int cc, struct sockaddr_in *from){ register struct icmphdr *icp; register int i; register u_char *cp,*dp;/*#if 0*/ register u_long l; register int j; static int old_rrlen; static char old_rr[MAX_IPOPTLEN];/*#endif*/ struct iphdr *ip; struct timeval tv, *tp; long triptime = 0; int hlen, dupflag; (void)gettimeofday(&tv, (struct timezone *)NULL); /* Check the IP header */ ip = (struct iphdr *)buf; hlen = ip->ip_hl << 2; if (cc < datalen + ICMP_MINLEN) { if (options & F_VERBOSE) (void)fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc, inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr)); return; } /* Now the ICMP part */ cc -= hlen; icp = (struct icmphdr *)(buf + hlen); if (icp->icmp_type == ICMP_ECHOREPLY) { if (icp->icmp_id != ident) return; /* 'Twas not our ECHO */ ++nreceived; if (timing) {#ifndef icmp_data tp = (struct timeval *)(icp + 1);#else tp = (struct timeval *)icp->icmp_data;#endif tvsub(&tv, tp); triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); tsum += triptime; if (triptime < tmin) tmin = triptime; if (triptime > tmax) tmax = triptime; } if (TST(icp->icmp_seq % mx_dup_ck)) { ++nrepeats; --nreceived; dupflag = 1; } else { SET(icp->icmp_seq % mx_dup_ck); dupflag = 0; } if (options & F_QUIET) return; if (options & F_FLOOD) (void)write(STDOUT_FILENO, &BSPACE, 1); else { (void)printf("%d bytes from %s: icmp_seq=%u", cc, inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), icp->icmp_seq); (void)printf(" ttl=%d", ip->ip_ttl); if (timing) (void)printf(" time=%ld.%ld ms", triptime/10, triptime%10); if (dupflag) (void)printf(" (DUP!)"); /* check the data */#ifndef icmp_data cp = ((u_char*)(icp + 1) + 8);#else cp = (u_char*)icp->icmp_data + 8;#endif dp = &outpack[8 + sizeof(struct timeval)]; for (i = 8; i < datalen; ++i, ++cp, ++dp) { if (*cp != *dp) { (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp); cp = (u_char*)(icp + 1); for (i = 8; i < datalen; ++i, ++cp) { if ((i % 32) == 8) (void)printf("\n\t"); (void)printf("%x ", *cp); } break; } } } } else { /* We've got something other than an ECHOREPLY */ if (!(options & F_VERBOSE)) return; (void)printf("%d bytes from %s: ", cc, pr_addr(from->sin_addr.s_addr)); pr_icmph(icp); }/*#if 0*/ /* Display any IP options */ cp = (u_char *)buf + sizeof(struct iphdr); for (; hlen > (int)sizeof(struct iphdr); --hlen, ++cp) switch (*cp) { case IPOPT_EOL: hlen = 0; break; case IPOPT_LSRR: (void)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) (void)printf("\t0.0.0.0"); else (void)printf("\t%s", pr_addr(ntohl(l))); hlen -= 4; j -= 4; if (j <= IPOPT_MINOFF) break; (void)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 *)buf + sizeof(struct iphdr) + 2 && !memcmp((char *)cp, old_rr, i) && !(options & F_FLOOD)) { (void)printf("\t(same route)"); i = ((i + 3) / 4) * 4; hlen -= i; cp += i; break; } old_rrlen = i; memcpy(old_rr, cp, i); (void)printf("\nRR: "); for (;;) { l = *++cp; l = (l<<8) + *++cp; l = (l<<8) + *++cp; l = (l<<8) + *++cp; if (l == 0) (void)printf("\t0.0.0.0"); else (void)printf("\t%s", pr_addr(ntohl(l))); hlen -= 4; i -= 4; if (i <= 0) break; (void)putchar('\n'); } break; case IPOPT_NOP: (void)printf("\nNOP"); break; default: (void)printf("\nunknown option %x", *cp); break; }/*#endif*/ if (!(options & F_FLOOD)) { (void)putchar('\n'); (void)fflush(stdout); }}/* * in_cksum -- * Checksum routine for Internet Protocol family headers (C Version) */static intin_cksum(u_short *addr, int len){ register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer);}/* * tvsub -- * Subtract 2 timeval structs: out = out - in. Out is assumed to * be >= in. */static voidtvsub(register struct timeval *out, register struct timeval *in){ if ((out->tv_usec -= in->tv_usec) < 0) { --out->tv_sec; out->tv_usec += 1000000; } out->tv_sec -= in->tv_sec;}/* * finish -- * Print out statistics, and give up. */static voidfinish(int ignore){ (void)ignore; (void)signal(SIGINT, SIG_IGN); (void)putchar('\n'); (void)fflush(stdout); (void)printf("--- %s ping statistics ---\n", hostname); (void)printf("%ld packets transmitted, ", ntransmitted); (void)printf("%ld packets received, ", nreceived); if (nrepeats) (void)printf("+%ld duplicates, ", nrepeats); if (ntransmitted) if (nreceived > ntransmitted) (void)printf("-- somebody's printing up packets!"); else (void)printf("%d%% packet loss", (int) (((ntransmitted - nreceived) * 100) / ntransmitted)); (void)putchar('\n'); if (nreceived && timing) (void)printf("round-trip min/avg/max = %ld.%ld/%lu.%ld/%ld.%ld ms\n", tmin/10, tmin%10, (tsum / (nreceived + nrepeats))/10, (tsum / (nreceived + nrepeats))%10, tmax/10, tmax%10); if (nreceived==0) exit(1); exit(0);}#ifdef notdefstatic char *ttab[] = { "Echo Reply", /* ip + seq + udata */ "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ "Source Quench", /* IP */ "Redirect", /* redirect type, gateway, + IP */ "Echo", "Time Exceeded", /* transit, frag reassem + IP */ "Parameter Problem", /* pointer + IP */ "Timestamp", /* id + seq + three timestamps */ "Timestamp Reply", /* " */ "Info Request", /* id + sq */ "Info Reply" /* " */};#endif/* * pr_icmph -- * Print a descriptive string about an ICMP header. */static voidpr_icmph(struct icmphdr *icp){ switch(icp->icmp_type) { case ICMP_ECHOREPLY: (void)printf("Echo Reply\n"); /* XXX ID + Seq + Data */ break; case ICMP_DEST_UNREACH: switch(icp->icmp_code) { case ICMP_NET_UNREACH: (void)printf("Destination Net Unreachable\n"); break; case ICMP_HOST_UNREACH: (void)printf("Destination Host Unreachable\n"); break; case ICMP_PROT_UNREACH: (void)printf("Destination Protocol Unreachable\n"); break; case ICMP_PORT_UNREACH: (void)printf("Destination Port Unreachable\n"); break; case ICMP_FRAG_NEEDED: (void)printf("frag needed and DF set\n"); break; case ICMP_SR_FAILED: (void)printf("Source Route Failed\n"); break; case ICMP_NET_UNKNOWN: (void)printf("Network Unknown\n"); break; case ICMP_HOST_UNKNOWN: (void)printf("Host Unknown\n"); break; case ICMP_HOST_ISOLATED: (void)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: (void)printf("Packet Filtered\n"); break;#endif#ifdef ICMP_PREC_VIOLATION case ICMP_PREC_VIOLATION: (void)printf("Precedence Violation\n"); break;#endif#ifdef ICMP_PREC_CUTOFF case ICMP_PREC_CUTOFF: (void)printf("Precedence Cutoff\n"); break;#endif default: (void)printf("Dest Unreachable, Unknown Code: %d\n", icp->icmp_code); break; } /* Print returned IP header information */#ifndef icmp_data pr_retip((struct iphdr *)(icp + 1));#else pr_retip((struct iphdr *)icp->icmp_data);#endif break; case ICMP_SOURCE_QUENCH: (void)printf("Source Quench\n");#ifndef icmp_data pr_retip((struct iphdr *)(icp + 1));#else pr_retip((struct iphdr *)icp->icmp_data);#endif break; case ICMP_REDIRECT: switch(icp->icmp_code) { case ICMP_REDIR_NET: (void)printf("Redirect Network"); break; case ICMP_REDIR_HOST: (void)printf("Redirect Host"); break; case ICMP_REDIR_NETTOS: (void)printf("Redirect Type of Service and Network"); break; case ICMP_REDIR_HOSTTOS: (void)printf("Redirect Type of Service and Host"); break; default: (void)printf("Redirect, Bad Code: %d", icp->icmp_code); break; } (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr));#ifndef icmp_data pr_retip((struct iphdr *)(icp + 1));#else pr_retip((struct iphdr *)icp->icmp_data);#endif break; case ICMP_ECHO: (void)printf("Echo Request\n"); /* XXX ID + Seq + Data */ break; case ICMP_TIME_EXCEEDED: switch(icp->icmp_code) { case ICMP_EXC_TTL: (void)printf("Time to live exceeded\n"); break; case ICMP_EXC_FRAGTIME: (void)printf("Frag reassembly time exceeded\n"); break; default: (void)printf("Time exceeded, Bad Code: %d\n", icp->icmp_code); break; }#ifndef icmp_data pr_retip((struct iphdr *)(icp + 1));#else pr_retip((struct iphdr *)icp->icmp_data);#endif break; case ICMP_PARAMETERPROB: (void)printf("Parameter problem: IP address = %s\n", inet_ntoa (icp->icmp_gwaddr));#ifndef icmp_data pr_retip((struct iphdr *)(icp + 1));#else pr_retip((struct iphdr *)icp->icmp_data);#endif break; case ICMP_TIMESTAMP: (void)printf("Timestamp\n"); /* XXX ID + Seq + 3 timestamps */ break; case ICMP_TIMESTAMPREPLY: (void)printf("Timestamp Reply\n"); /* XXX ID + Seq + 3 timestamps */ break; case ICMP_INFO_REQUEST: (void)printf("Information Request\n"); /* XXX ID + Seq */ break; case ICMP_INFO_REPLY: (void)printf("Information Reply\n"); /* XXX ID + Seq */ break;#ifdef ICMP_MASKREQ case ICMP_MASKREQ: (void)printf("Address Mask Request\n"); break;#endif#ifdef ICMP_MASKREPLY case ICMP_MASKREPLY: (void)printf("Address Mask Reply\n"); break;#endif default: (void)printf("Bad ICMP type: %d\n", icp->icmp_type); }}/* * pr_iph -- * Print an IP header with options. */static voidpr_iph(struct iphdr *ip){ int hlen; u_char *cp; hlen = ip->ip_hl << 2; cp = (u_char *)ip + 20; /* point to options */ (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\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(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_src))); (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_dst))); /* dump and option bytes */ while (hlen-- > 20) { (void)printf("%02x", *cp++); } (void)putchar('\n');}/* * pr_addr -- * Return an ascii host address as a dotted quad and optionally with * a hostname. */static char *pr_addr(u_long l){ struct hostent *hp; static char buf[256]; if ((options & F_NUMERIC) || !(hp = gethostbyaddr((char *)&l, 4, AF_INET))) (void)sprintf(buf, /*sizeof(buf),*/ "%s", inet_ntoa(*(struct in_addr *)&l)); else (void)sprintf(buf, /*sizeof(buf),*/ "%s (%s)", hp->h_name, inet_ntoa(*(struct in_addr *)&l)); return(buf);}/* * pr_retip -- * Dump some info on a returned (via ICMP) IP packet. */static voidpr_retip(struct iphdr *ip){ int hlen; u_char *cp; pr_iph(ip); hlen = ip->ip_hl << 2; cp = (u_char *)ip + hlen; if (ip->ip_p == 6) (void)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) (void)printf("UDP: from port %u, to port %u (decimal)\n", (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));}static voidfill(void *bp1, char *patp){ register int ii, jj, kk; int pat[16]; char *cp, *bp = (char *)bp1; for (cp = patp; *cp; cp++) if (!isxdigit(*cp)) { (void)fprintf(stderr, "ping: patterns must be specified as hex digits.\n"); exit(2); } ii = sscanf(patp, "%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]); if (ii > 0) for (kk = 0; kk <= MAXPACKET - (8 + ii); kk += ii) for (jj = 0; jj < ii; ++jj) bp[jj + kk] = pat[jj]; if (!(options & F_QUIET)) { (void)printf("PATTERN: 0x"); for (jj = 0; jj < ii; ++jj) (void)printf("%02x", bp[jj] & 0xFF); (void)printf("\n"); }}static voidusage(void){ (void)fprintf(stderr, "usage: ping [-LRdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] [-t ttl] [-I interface address] host\n"); exit(2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -