📄 my_ping.c
字号:
#include "my_ping.h" extern int errno;struct proto proto_v4 = {proc_v4, send_v4, NULL, NULL,NULL, 0, IPPROTO_ICMP};int n_send;int n_recv; void sig_intr(int signum) { printf("---------------------------------\n"); printf("success send %d packets,recvie %d packtes,lost %d packets\n", n_send, n_recv, n_send-n_recv); exit(0);} int main(int argc, char** argv) { datalen = 56; int c; struct addrinfo *ai; opterr = 0; while((c = getopt(argc, argv, "v")) != -1) { switch(c) { case 'v':verbose++;break; case '?':printf("error option: %c\n", c);return -1; } } if(optind != argc-1) { printf("use ping [-v] <hostname>\n"); return -1; } host = argv[optind]; pid = getpid(); struct sigaction sa; sa.sa_handler = sig_alarm; sigaction(SIGALRM, &sa, NULL); struct sigaction sa2; sa2.sa_handler = sig_intr; sigaction(SIGINT, &sa2, NULL); printf("host:%s\n", host); int n = getaddrinfo(host, 0, 0, &ai); if(n != 0) { printf("error getaddrinfo()\n"); perror("info"); } printf("------------------------------------\n"); printf("ai_family : %d\n", ai->ai_family); printf("ai_socktype:%d\n", ai->ai_socktype); printf("ai_protocol:%d\n", ai->ai_protocol); printf("ai_addrlen:%d\n", ai->ai_addrlen); printf("ai_canonname: %s\n", ai->ai_canonname); printf("------------------------------------\n"); char buf[1024]; const char* p; if(ai->ai_family == AF_INET) { p = inet_ntop(ai->ai_family, &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), buf, 1024); pr = &proto_v4; } if(p == NULL)printf("error inet_ntop()\n"); pr->sasend = ai->ai_addr; pr->sarecv = (struct sockaddr*)malloc(ai->ai_addrlen); pr->salen = ai->ai_addrlen; readloop(); return 0;} void readloop(void) { char recvbuf[BUFSIZE]; char controlbuf[BUFSIZE]; struct msghdr msg; struct iovec iov; struct timeval tval; sockfd = socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto); if(sockfd == -1)perror("sockfd error"); setuid(getuid()); int size = 60*1024; setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, 4); sig_alarm(SIGALRM); iov.iov_base = recvbuf; iov.iov_len = sizeof(recvbuf); msg.msg_name = pr->sarecv; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = controlbuf; for(;;) { msg.msg_namelen = pr->salen; msg.msg_controllen = sizeof(controlbuf); int n = recvmsg(sockfd, &msg, 0); if(n < 0) { if(errno == EINTR)continue; else { perror("recvmsg"); return; } } n_recv++; gettimeofday(&tval, NULL); (*pr->fproc)(recvbuf, n, &msg, &tval); } }void tv_sub(struct timeval* out, struct timeval *in) { if((out->tv_usec -= in->tv_usec) < 0) { --out->tv_sec; out->tv_usec += 1000000; } out->tv_sec -= in->tv_sec;}void proc_v4(char* ptr, ssize_t len, struct msghdr* msg, struct timeval* tvrecv) { int hlen1, icmplen; double rtt; struct ip *ip; struct icmp *icmp; struct timeval *tvsend; ip = (struct ip*)ptr; hlen1 = ip->ip_hl << 2; if(ip->ip_p != IPPROTO_ICMP)return; icmp = (struct icmp*)(ptr + hlen1); icmplen = len-hlen1; if(icmp->icmp_type == ICMP_ECHOREPLY) { if(icmp->icmp_id != pid) { printf("icmp_id doesn't equal process id\n"); return; } if(icmplen < 0) { printf("icmplen less than 0\n"); return; } tvsend = (struct timeval*)icmp->icmp_data; tv_sub(tvrecv, tvsend); rtt = tvrecv->tv_sec*1000.0 + tvrecv->tv_usec/1000.0; char buf[1024]; inet_ntop(AF_INET, &(((struct sockaddr_in*)(pr->sarecv))->sin_addr), buf, 1024); printf("%d bytes from:%s id:%d rtt:%.3fms\n", icmplen, buf, icmp->icmp_seq, rtt); } }void send_v4(void) { int len; struct icmp *icmp; icmp = (struct icmp*)sendbuf; icmp->icmp_type = ICMP_ECHO; icmp->icmp_code = 0; icmp->icmp_id = pid; icmp->icmp_seq = nsent++; memset(icmp->icmp_data, 0xa5, datalen); gettimeofday((struct timeval*)icmp->icmp_data, NULL); len = 8+datalen; icmp->icmp_cksum = 0; icmp->icmp_cksum = in_cksum((u_short*)icmp, len); int n = sendto(sockfd, sendbuf, len, 0, pr->sasend, pr->salen); printf("success send %d bytes\n", n); n_send++;}void sig_alarm(int signum) { (*pr->fsend)(); alarm(1); return;} u_short in_cksum(u_short* data, int len) { int result = 0; for(int i=0; i<len/2; i++) { result += *data; data++; } while(result >> 16)result = (result&0xffff) + (result >> 16); return ~result; }/*u_short in_cksum(u_short *addr, int len){ register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer =0; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return(answer);}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -