int main(int argc,char *argv[])
{
structhostent *host;
structprotoent *protocol;
unsignedlong inaddr=0l;
intwaittime=MAX_WAIT_TIME;
intsize=50*1024;
if(argc<2)
{
printf("usage:%s hostname/IP address\n",argv[0]);
exit(1);
}
if((protocol=getprotobyname("icmp") )==NULL)
{
perror("getprotobyname");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto))<0)
{
perror("socket error");
exit(1);
}
setuid(getuid());
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
bzero(&dest_addr,sizeof(dest_addr));
dest_addr.sin_family=AF_INET;
if(inaddr=inet_addr(argv[1])==INADDR_NONE)
{
if((host=gethostbyname(argv[1]) )==NULL)
{
perror("gethostbyname error");
exit(1);
}
memcpy( (char*)&dest_addr.sin_addr,host->h_addr,host->h_length);
}
else
memcpy((char *)&dest_addr,(char*)&inaddr,host->h_length);
pid=getpid();
printf("PING%s(%s): %d bytes data in ICMP packets.\n",argv[1],
inet_ntoa(dest_addr.sin_addr),datalen);
send_packet();
recv_packet();
statistics(SIGALRM);
return0;
}
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;
}
特别注意
只有root用户才能利用socket()函数生成原始套接字,要让Linux的一般用户能执行以上程序,需进行如下的特别操作:
用root登陆,编译以上程序:gcc -o mypingmyping.c,其目的有二:一是编译,二是让myping属于root用户。
再执行chmod u+s myping,目的是把myping程序设成SUID的属性。
退出root,用一般用户登陆,执行./myping www.cn.ibm.com,有以下执行结果:
PING www.cn.ibm.com(202.95.2.148): 56 bytes data in ICMPpackets.
64 byte from 202.95.2.148: icmp_seq=1 ttl=242 rtt=3029.000 ms
64 byte from 202.95.2.148: icmp_seq=2 ttl=242 rtt=2020.000 ms
64 byte from 202.95.2.148: icmp_seq=3 ttl=242 rtt=1010.000 ms
--------------------PING statistics-------------------
3 packets transmitted, 3 received , %0 lost |