- 论坛徽章:
- 11
|
加了几个头文件,主要问题是后面icmp包的没有计算checksum,sequence应该转为network byte order,Linux的IP和ICMP包头都是network order,所以16bit和32bit的整数字段在接收和发送都要转byte order,附上简单修改的代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#define DATASIZE 56
#define IP4STRSIZE 16
#define TIMEOUT 3
static pthread_t tid;
static char *strip=NULL;
static struct timeval sndtime,rcvtime,starttime,endtime;
static char *savedomain=NULL;
static int packet=0;
static int rcvpacket=0;
static int lostpacket=0;
static float avg=0;
static float max=0;
static float min=100;
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct ping_msg_st {
struct icmphdr hdr;
char data[DATASIZE];
};
struct pong_msg_st {
struct iphdr iphdr;
struct icmphdr icmphdr;
char data[DATASIZE];
};
uint16_t
in_cksum (uint16_t * addr, int len)
{
int nleft = len;
uint32_t sum = 0;
uint16_t *w = addr;
uint16_t 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) {
* (unsigned char *) (&answer) = * (unsigned 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);
}
static void
int_handler(int s,siginfo_t *infop , void *ptr)
{
fprintf(stderr,"\n--- %s ping statistics ---\n",savedomain);
gettimeofday(&endtime,NULL);
fprintf(stderr,"%d packets transmitted, %d received, %d packet loss, time %.0fms\n",packet,rcvpacket,lostpacket,(float)((endtime.tv_sec - starttime.tv_sec)*1000 + (endtime.tv_usec - starttime.tv_usec)) * (0.001));
if(rcvpacket) {
fprintf(stderr,"rtt min/avg/max = %.3f/%.3f/%.3f ms\n",min,avg/rcvpacket,max);
}
exit(1);
}
static void*
rcv_msg(void *ptr)
{
int sd,ret;
struct pong_msg_st rmsg;
struct sigaction sa,osa;
float cursave=0;
pthread_detach(pthread_self());
sa.sa_sigaction=int_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART|SA_SIGINFO;
sigaction(SIGINT,&sa,&osa);
sd=(int)ptr;
while(1) {
pthread_mutex_lock(&mut);
pthread_cond_wait(&cond,&mut);
ret=recvfrom(sd, &rmsg, sizeof(rmsg), 0, NULL, NULL);
gettimeofday(&rcvtime,NULL);
if (ret==-1) {
if (errno == EAGAIN) {
++lostpacket;
puts("Timed out.");
} else {
perror("sendto()");
exit(1);
}
} else {
++rcvpacket;
cursave = (float)((rcvtime.tv_sec - sndtime.tv_sec)*1000 + (rcvtime.tv_usec - sndtime.tv_usec)) * (0.001);
if(min > cursave) {
min = cursave;
}
if (max < cursave) {
max = cursave;
}
avg += cursave;
if(strcmp(savedomain,strip) == 0) {
printf("%d bytes from %s: icmp_seq=%d ttl=%d time=%.3f ms\n",sizeof(rmsg), strip, ntohs(rmsg.icmphdr.un.echo.sequence),rmsg.iphdr.ttl,cursave);
}else {
printf("%d bytes from %s (%s): icmp_seq=%d ttl=%d time=%.3f ms\n",sizeof(rmsg),savedomain, strip, ntohs(rmsg.icmphdr.un.echo.sequence), rmsg.iphdr.ttl,cursave);
}
}
pthread_mutex_unlock(&mut);
}
pthread_exit(NULL);
}
|
|
|