|
|
|
|
|
|
|
[Original]
[Print]
[Top]
|
使用原始套接字编写了一个ping命令:
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#define IP_HEAD_LEN 20
#define ICMP_LEN 8
void handle_alarm(int signo);
void send_ip(void);
void recv_ip(void);
unsigned short ip_checksum(unsigned short * pcheck,int check_len);
int ip_fd;//原始套接字的描述符
int p_id;//进程号
int packet_len=IP_HEAD_LEN+ICMP_LEN;
struct sockaddr_in send_addr;
char send_buf[1024];
int sequence=0;//报文的序列号
void handle_alarm(int signo)
{
alarm(1);
send_ip();
}
void send_ip(void)
{
int len;
struct icmphdr *icmp_p;
icmp_p=(struct icmphdr *)send_buf;
icmp_p->type=ICMP_ECHO;
icmp_p->code=0;
(icmp_p->un).echo.id=p_id;
(icmp_p->un).echo.sequence=sequence;
gettimeofday((struct timeval *)(icmp_p+1),NULL);
len=sizeof(struct timeval)+ICMP_LEN;
icmp_p->checksum=0;
icmp_p->checksum=ip_checksum((u_short *)icmp_p,len);
len=sendto(ip_fd,send_buf,len,0,(struct sockaddr *)&send_addr,
sizeof(send_addr));
if(len<0)
fprintf(stderr,"sendto error.
");
sequence++;
printf("sendto %s",inet_ntoa(send_addr.sin_addr));
}
void recv_ip(void)
{
char recv_buf[1024];
int len;
int n;
struct ip *ip_p;
struct timeval *time_now,*time_send;
struct timeval now;
int iphead_len;
int icmp_len;
struct icmphdr *icmp_p;
float delay;
while(1){
printf("
-------------");
n=recvfrom(ip_fd,recv_buf,sizeof(recv_buf),0,NULL,NULL);
printf("
n=%d",n);
if(n<0)
{
if(errno==EINTR)
continue;
else{printf("recvfrom error");
continue;}
}
ip_p=(struct ip*)recv_buf;
iphead_len=ip_p->ip_hl<<2;
icmp_p=(struct icmphdr *)(recv_buf+iphead_len);
icmp_len=n-iphead_len;
if(icmp_len<8)
fprintf(stderr,"error icmp len=%d.
",icmp_len);
if(icmp_p->type==ICMP_ECHOREPLY){
if((icmp_p->un).echo.id!=p_id)
return;
if(icmp_len<16)
printf("icmplen=%d.
",icmp_len);
gettimeofday(&now,NULL);
time_now=&now;
time_send=(struct timeval *)(icmp_p+1);
if(time_now->tv_usec-=time_send->tv_usec<0){
time_now->tv_sec--;
time_now->tv_usec+=1000000;}
time_now->tv_sec-=time_send->tv_sec;
delay=time_now->tv_sec*1000.0+time_now->tv_usec/1000.0;
printf("
%dbytes recv from %s:sequence=%d,ttl=%d,rtt=%fms.
",
icmp_len,inet_ntoa(send_addr.sin_addr),(icmp_p->un).echo.
sequence,ip_p->ip_ttl,delay);}
}
}
unsigned short ip_checksum(unsigned short *pcheck,int check_len)
{
int nleft=check_len;
int sum=0;
unsigned short *p=pcheck;
unsigned short result=0;
while(nleft>1){sum=sum+(*p++);
nleft-=2;}
if(nleft==1){
*(unsigned char *)(&result)=*(unsigned char *)p;
sum+=result;}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
result=sum;
return result;
}
int main(int argc,char ** argv[])
{
struct sigaction act;
if(argc!=2){
fprintf(stderr,"usage:ping<IP_ADDR>.
");
exit(1);}
setuid(getuid());
act.sa_handler=handle_alarm;
act.sa_flags=0;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM,&act,NULL);
p_id=getpid();
inet_aton(argv[1],&send_addr.sin_addr);
ip_fd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(ip_fd<0){
fprintf(stderr,"raw socket error.
");
exit(1);}
raise(SIGALRM);
recv_ip();
}
在执行时,可以ping通自己的机器,但如果ping其它的机器则没有响应,请问这个是怎么回事?
另外,ping自己机器时的响应时间和linux自带的ping命令比较起来要长很多,请问这又是怎么回事?
我使用的是linux(rh9.0)平台。
|
|
|
[Original]
[Print]
[Top]
|
|
|