|
|
有了kj501的提醒这次重新发了代码,希望各位朋友帮我分析一下代码。
主要问题:每次只执行 send_icmp() ,有时执行 recv_icmp() ,用 gdb 跟踪
发现如执行 recv_icmp() 也执行到 /?????????/处不再往下执行。
- #include<stdio.h>
- #include<sys/types.h>
- #include<sys/time.h>
- #include<sys/socket.h>
- #include<sys/signal.h>
- #include<netdb.h>
- #include<netinet/in.h>
- #include<netinet/in_systm.h>
- #include<netinet/ip.h>
- #include<netinet/ip_icmp.h>
- #include<errno.h>
- #include<unistd.h>
- #include<stdlib.h>
- #include<ctype.h>
- #include<string.h>
- #define MSG_BUF_SIZE 256
- #define HOST_BUF_SIZE 128
- struct sockaddr_in dest,send_addr;
- int sockfd;
- int pid;
- int datalen=56;
- char hostname[HOST_BUF_SIZE];
- char message_buf[MSG_BUF_SIZE];
- int seq=0;
- // some functions will be used
- void handle_singal(int);
- void handle_tv(struct timeval *,struct timeval *);
- unsigned short check_sum(unsigned short *,int);
- void handle_icmp(char *,int);
- void recv_icmp(void);
- void send_icmp(struct sockaddr_in);
- void handle_signal(int);
- void stat();
- int main(int argc,char *argv[])
- {
- int n;
- struct hostent *he;
- struct sigaction action;
- if(argc!=2)
- {
- fprintf(stderr,"USAGE:ping host!\n");
- exit(1);
- }
- action.sa_handler=handle_signal;
- sigemptyset(&action.sa_mask);
- action.sa_flags=0;
- // use the signal
- sigaction(SIGALRM,&action,NULL);
- /* get pid of 'main' to set the flag of ICMP */
- pid=getpid();
- dest.sin_family=AF_INET;
- // use inet_aton() making IP_address(argv[1]) to binary
- if(inet_aton(argv[1],&dest.sin_addr)==1)
- {
- strcpy(hostname,argv[1]);
- }
- // if argv[1] is not IP_address
- else
- {
- // get info by host_name
- he=gethostbyname(argv[1]);
- if(he!=NULL)
- {
- dest.sin_addr=*(struct in_addr *)he->h_addr[0];
- strcpy(hostname,he->h_name);
- exit(1);
- }
- else
- {
- fprintf(stderr,"host name error:%s%s\n",argv[1],hstrerror(h_errno));
- exit(1);
- }
- }
- printf("PING %s(%s):\n",hostname,inet_ntoa(dest.sin_addr));
-
- // create a socket
- sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
- if(sockfd<0)
- {
- fprintf(stderr,"socket error\n");
- exit(1);
- }
- // set uid( get back root's right,set current's right)
- setuid(getuid());
- /* handle sigalrm */
- handle_signal(SIGALRM);
- /* receive data */
- recv_icmp();
- }
- // handle sigalrm : call send_icmp() interval 1 second
- void handle_signal(int signal)
- {
- send_icmp(dest);
- arlarm(1);
- return;
- }
- // send message to host
- void send_icmp(struct sockaddr_in send_addr)
- {
- int len;
- struct icmphdr *icmp;
- icmp=(struct icmphdr *)message_buf;
- icmp->type=ICMP_ECHO;
- icmp->code=0;
- icmp->un.echo.sequence=seq++;
- /* ?????? */
- struct timeval *a=(struct timeval *)(icmp+1);
- gettimeofday(a,NULL); //calc process time
- len=datalen+8;
- icmp->checksum=0;
- icmp->checksum=check_sum((u_short *)icmp,len);
- // use the sendto
- len=sendto(sockfd,message_buf,len,0,(struct sockaddr *)&send_addr,sizeof(send_addr));
-
- if(len<0) // if unsuccess
- {
- fprintf(stderr,"send to error!\n");
- exit(1);
- }
- printf("%d bytes sendto %s!\n",len,inet_ntoa(send_addr.sin_addr));
- }
- // receive answer from host
- void recv_icmp(void)
- {
- int n=0;
- while(1)
- {
- n=recvfrom(sockfd,message_buf,sizeof(message_buf),0,NULL,NULL);
-
- /* recive nothing */
- if(n<0)
- {
- if(errno==EINTR)
- continue;
- else
- {
- fprintf(stderr,"recvfrom error");
- continue;
- }
- }
- else
- /* call hand_icmp() */
- {handle_icmp(message_buf,n);}
- }
- }
- // handle the ICMP data
- void handle_icmp(char *ptr,int len)
- {
- int hlen1,icmplen;
- double rtt;
- struct ip *ip;
- struct icmphdr *icmp;
- struct timeval *tvsend;
- struct timeval tvrecv;
-
- ip=(struct ip *)ptr;
- hlen1=ip->ip_hl<<2; // move right 2 bit to get IP's length
- // why! try to understand
-
- // get begin address of icmp
- icmp=(struct icmphdr *)(ptr+hlen1);
-
- // icmplen is often 8 bit
- if((icmplen=len-hlen1)<8)
- printf("icmplen(%d)<8",icmplen);
- /* if the type is not so ,do not do anything */
- /* ICMP_ECHORELY :xiangying -- yingdai */
- if(icmp->type==ICMP_ECHOREPLY)
- {
- if(icmp->un.echo.id!=pid) /??????????/ 到这就不往下执行了
- return;
- if(icmplen<16)
- printf("icmplen(%d)<16");
- /* get current time */
- gettimeofday(&tvrecv,NULL);
- /* get time address */
- tvsend=(struct timeval *)(icmp+1);
-
- handle_tv(&tvrecv,tvsend); /* calc the interval time */
-
- rtt=tvrecv.tv_sec*1000.0+tvrecv.tv_usec/1000.0;
- printf("%d bytes from %s:seq=%u,ttl=%d,rtt=%.3fms\n",icmplen,hostname,inet_ntoa(dest.sin_addr),icmp->un.echo.sequence,ip->ip_ttl,rtt);
- }
- }
- // process the interval time (icmp to and back time)
- void handle_tv(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;
- }
-
-
- unsigned short check_sum(unsigned short *addr,int len)
- {
- int nleft=len;
- int sum=0;
- unsigned short *w=addr;
- unsigned short answer=0;
- while(nleft>1)
- {
- sum+=*w++;
- nleft-=2;
- }
- if(nleft==1)
- {
- *(unsigned char *)(&answer)=*(unsigned char *)w;
- sum+=answer;
- }
- sum=(sum>>16)+(sum&0xffff);
- sum+=(sum>>16);
- answer=sum;
- return(answer);
- }
复制代码 |
|