📄 ping.c
字号:
icp->icmp_code); break; } /* Print returned IP header information */ pr_retip((struct ip *)icp->icmp_data); break; case ICMP_SOURCE_QUENCH: printf("Source Quench\n"); pr_retip((struct ip *)icp->icmp_data); break; case ICMP_REDIRECT: switch(icp->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", icp->icmp_code); break; } printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); pr_retip((struct ip *)icp->icmp_data); break; case ICMP_ECHO: printf("Echo Request\n"); /* XXX ID + Seq + Data */ break; case ICMP_TIME_EXCEEDED: switch(icp->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", icp->icmp_code); break; } pr_retip((struct ip *)icp->icmp_data); break; case ICMP_PARAMETERPROB: printf("Parameter problem: IP address = %s\n", inet_ntoa(icp->icmp_gwaddr)); pr_retip((struct ip *)icp->icmp_data); 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", icp->icmp_type); }}staticvoidpr_opts(void){ static int old_rrlen; static char old_rr[MAX_IPOPTLEN]; int i,j,k; u_int32_t addr; u_int8_t *cp = INPACK_OPTS; for (i=0; i<ipoptlen; i++) { switch (cp[i]) { case IPOPT_EOL: return; case IPOPT_LSRR: printf("\nLSRR: "); j = cp[++i]; i++; /* ? */ if (j > IPOPT_MINOFF) { while (i<ipoptlen) { memcpy(&addr, &cp[i+1], sizeof(addr)); printf("\t%s", pr_addr(ntohl(addr))); i += sizeof(addr); j -= sizeof(addr); if (j <= IPOPT_MINOFF) break; putchar('\n'); } } break; case IPOPT_RR: j = cp[++i]; /* get length */ k = cp[++i]; /* and pointer */ if (k > j) k = j; k -= IPOPT_MINOFF; if (k <= 0) continue; if (k == old_rrlen && i==2 && !memcmp(cp+i, old_rr, k) && !(options & F_FLOOD)) { printf("\t(same route)"); k = ((k + 3) / 4) * 4; i += k; break; } if (k < MAX_IPOPTLEN) { old_rrlen = k; memcpy(old_rr, cp+i, k); } else { old_rrlen = 0; } j=0; printf("\nRR: "); for (;;) { memcpy(&addr, &cp[i+1], sizeof(addr)); printf("\t%s", pr_addr(ntohl(addr))); i += 4; j += 4; k -= 4; if (k <= 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[i]); break; } }}staticvoidcheck_packet_data(void){ u_int8_t *cp, *dp; int i; cp = INPACK_PAYLOAD; dp = OUTPACK_PAYLOAD; for (i=0; i<datalen-ICMP_MINLEN; i++) { if (cp[i] != dp[i]) { printf("\n"); printf("wrong data byte #%d should be 0x%x " "but was 0x%x", i, dp[i], cp[i]); for (i=0; i<datalen-ICMP_MINLEN; i++) { if ((i % 32) == 8) printf("\n\t"); printf("%x ", cp[i]); } return; } }}/* * pr_pack * * Print out the packet, if it came from us. * * This check 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!). * * Returns nonzero if it was one of our echo replies. */staticintpr_pack(int packlen, struct sockaddr_in *from){ struct ip *ip; struct icmp *icp; struct timeval now, packettv, *tp; long triptime = 0; int hlen, dupflag; int rv; gettimeofday(&now, NULL); /* Check the IP header */ ip = INPACK_IP; hlen = ip->ip_hl << 2; if (hlen < (int)sizeof(struct ip)) { if (options & F_VERBOSE) { fprintf(stderr, "ping: packet too short (%d octets with " "IP header) from %s\n", packlen, inet_ntoa(from->sin_addr)); } return 0; } if (hlen > packlen) { if (options & F_VERBOSE) { fprintf(stderr, "ping: partial packet (%d octets IP header, " "whole packet only %d) from %s\n", hlen, packlen, inet_ntoa(from->sin_addr)); } return 0; } ipoptlen = hlen - sizeof(struct ip); packlen -= hlen; icp = INPACK_ICMP; /* ICMP_MINLEN is the size of the icmp header (8 octets) */ if (packlen < ICMP_MINLEN + datalen) { if (options & F_VERBOSE) { fprintf(stderr, "ping: packet too short (%d octets) from %s\n", packlen, inet_ntoa(from->sin_addr)); } return 0; } /* Now the ICMP part */ if (icp->icmp_type == ICMP_ECHOREPLY) { if (icp->icmp_id != ident) return 0; /* 'Twas not our ECHO */ nreceived++; if (timing) { tp = (struct timeval *)icp->icmp_data; memcpy(&packettv, tp, sizeof(struct timeval)); tvsub(&now, &packettv); /* precision: tenths of milliseconds */ triptime = now.tv_sec * 10000 + (now.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 1; } rv = 1; if (options & F_FLOOD) { write(STDOUT_FILENO, &BSPACE, 1); } else { printf("%d octets from %s: icmp_seq=%u", packlen, inet_ntoa(from->sin_addr), icp->icmp_seq); printf(" ttl=%d", ip->ip_ttl); if (timing) { printf(" time=%ld.%ld ms", triptime/10, triptime%10); } if (dupflag) { printf(" (DUP!)"); } /* check the data */ check_packet_data(); } } else { /* We've got something other than an ECHOREPLY */ if ((options & F_VERBOSE)==0) { return 0; } printf("%d octets from %s: ", packlen, pr_addr(from->sin_addr.s_addr)); pr_icmph(icp); rv = 0; } /* Display any IP options */ pr_opts(); if ((options & F_FLOOD)==0) { putchar('\n'); fflush(stdout); } return rv;}/********************* pinging code ********************//* * finish -- * Print out statistics, and give up. */staticvoidfinish(int ignore){ (void)ignore; signal(SIGINT, SIG_IGN); putchar('\n'); fflush(stdout); printf("--- %s ping statistics ---\n", hostname); printf("%ld packets transmitted, ", ntransmitted); printf("%ld packets received, ", nreceived); if (nrepeats) { printf("+%ld duplicates, ", nrepeats); } if (ntransmitted) { if (nreceived > ntransmitted) printf("-- somebody's printing up packets!"); else printf("%ld%% packet loss", ((ntransmitted - nreceived) * 100) / ntransmitted); } putchar('\n'); if (nreceived && timing) { printf("round-trip min/avg/max = %ld.%ld/%lu.%lu/%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);}/* * pinger * * Compose and transmit an ICMP ECHO REQUEST packet. The IP header * will be added on by the kernel. The ID field is our UNIX process ID, * and the sequence number is an ascending integer. The first few bytes * of the data portion are used to hold a UNIX "timeval" struct, to * compute the round-trip time. */staticvoidpinger(void){ struct icmp *icp; size_t packlen; int sentlen; icp = OUTPACK_ICMP; icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; icp->icmp_cksum = 0; icp->icmp_seq = ntransmitted++; icp->icmp_id = ident; CLR(icp->icmp_seq % mx_dup_ck); if (timing) { struct timeval tmptm; gettimeofday(&tmptm, NULL); memcpy(OUTPACK_TIME, &tmptm, sizeof(tmptm)); } /* get total length of outpack (datalen is total length of payload) */ packlen = datalen + (OUTPACK_PAYLOAD - outpack); /* compute ICMP checksum here */ icp->icmp_cksum = in_cksum((u_short *)outpack, packlen); sentlen = sendto(sock, outpack, packlen, 0, (struct sockaddr *)&whereto, sizeof(whereto)); if (sentlen != (int)packlen) { if (sentlen < 0) { perror("sendto"); } printf("ping: sent %d octets to %s, ret=%d\n", (int)packlen, hostname, sentlen); } if ((options & F_QUIET)==0 && (options & F_FLOOD)) { write(STDOUT_FILENO, &DOT, 1); }}staticintcompute_waittime(void){ int waittime; if (nreceived) { waittime = 2 * tmax / 1000; if (!waittime) waittime = 1; if (waittime > MAXWAIT) waittime = MAXWAIT; } else { waittime = MAXWAIT; } return waittime;}staticvoiddoping(void){ struct sockaddr_in from; socklen_t fromlen; struct timeval interval, next, now, timeout; fd_set mask; int dosend=1, packlen; if (options & F_FLOOD) { interval.tv_sec = 0; interval.tv_usec = 10000; } else { interval.tv_sec = intervalsecs; interval.tv_usec = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -