#include "strings.h"
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/wait.h"
#include "errno.h"
#include "sys/select.h"
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/signal.h>
void handle_alarm(int signo);
void send_ip(void);
void recv_ip(void);
unsigned short ip_checksum(unsigned short *pcheck,int len);
int ip_fd;
int p_id;
const packet_len=8+20;
struct sockaddr_in send_addr;
char sendbuff[1024];
int sequence=0;
void handle_alarm(int signo){
send_ip();
alarm(2);
}
in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
void send_ip(void) {
int len;
struct icmphdr *icmp_p;
icmp_p=(struct icmphdr *)sendbuff;
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=packet_len+sizeof(struct timeval);
icmp_p->checksum=0;
//icmp_p->checksum=ip_checksum(icmp_p,len);
len=sendto(ip_fd,sendbuff,len,0,(struct sockaddr *)&send_addr,sizeof(send_addr));
if(len<0)
fprintf(stderr,"sendto error./n");
sequence++;
printf("sendto %s./n",inet_ntoa(send_addr.sin_addr));
}
void recv_ip(){
char recv_buff[1024];
struct ip *ip_p;
struct icmphdr *icmp_p;
int n;
int len,iphead_len,icmp_len;
struct timeval now,*time_now,*time_send;
float delay;
while(1){
n=recvfrom(ip_fd,recv_buff,sizeof(recv_buff),0,NULL,NULL);
if(n<0){
if(errno==EINTR)
continue;
else {
printf("recv error!");
continue;
}
}
ip_p=(struct ip *)recv_buff;
iphead_len=ip_p->ip_hl<<2;
icmp_len=n-iphead_len;
if(icmp_len<8){
fprintf(stderr,"error icmp_len=%d./n",icmp_len);
return;
}
if(icmp_p->type==ICMP_ECHOREPLY){
if((icmp_p->un).echo.id!=p_id)
return;
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+time_now->tv_usec/1000;
printf("%d bytes from %s:sequence:%d,ttl=%d,rtt=%dms/n",icmp_len,inet_ntoa(send_addr.sin_addr),(icmp_p->un).echo.sequence,ip_p->ip_ttl,delay);
}
}
}
int main(int argc, char **argv) {
struct sigaction act;
if(argc!=2) {
fprintf(stderr,"usage:ping1 <ip adress>/n");
return;
}
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./n");
exit(1);
}
raise(SIGALRM);
recv_ip();
}