/*
author: zhangzhijian
time: 2012-11-14
creater sock must root
ping localhost [-n count]
*/
#include <stdio.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <setjmp.h>
#include <errno.h>
#define MAX_WAIT_TIME 5
#define PACKET_SIZE 4096
int sockfd;
int data_len = 56;
int n_send = 0;
int n_recv = 0;
int max_no_packets = 3;
pid_t pid;
char send_data[PACKET_SIZE];
char recv_data[PACKET_SIZE];
struct sockaddr_in dest_addr;
struct sockaddr_in from;
struct timeval tv_recv;
void statistics(int signo);
void tv_sub(struct timeval *out, struct timeval *in);
unsigned short cal_chksum(unsigned short *addr, int len);
int init_pack(int pack_no);
void send_pack();
int unpack(char *buf, int len);
void recv_pack();
int main(int argc,char *argv[])
{
struct hostent *host;
struct protoent *protocol;
unsigned long inaddr = 0l;
int wait_time = MAX_WAIT_TIME;
int size = 50 * 1024;
if(argv < 2)
{
printf("usage:%s hostname/IP [-n count]\n", argv[0]);
exit(1);
}
if( (argc >= 3) )
{
max_no_packets = atoi(argv[3]);
}
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)
{//user host name
if( (host = gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname error");
exit(1);
}
memcpy( (char*)&dest_addr.sin_addr, host->h_addr, host->h_length);
}
else
{//user IP adder
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), data_len);
send_pack();
recv_pack();
statistics(SIGALRM);
return 0;
}
void send_pack()
{
int pack_size;
while( n_send < max_no_packets)
{
n_send ++;
pack_size = init_pack(n_send);
if( sendto(sockfd, send_data, pack_size, 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0)
{
perror("sendto error");
continue;
}
sleep(1);
}
return ;
}
int init_pack(int pack_no)
{
int i, pack_size;
struct icmp *picmp;
struct timeval *tval;
picmp = (struct icmp *)send_data;
picmp->icmp_type = ICMP_ECHO;
picmp->icmp_code = 0;
picmp->icmp_cksum = 0;
picmp->icmp_seq = pack_no;
picmp->icmp_id = pid;
pack_size = 8 + data_len;
tval = (struct timeval *)picmp->icmp_data;
gettimeofday(tval, NULL);
picmp->icmp_cksum = cal_chksum( (unsigned short *)picmp, pack_size);
return pack_size;
}
unsigned short cal_chksum(unsigned short *addr, int len)
{
int n_left = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
while(n_left > 1)
{
sum += *w++;
n_left -= 2;
}
if(n_left == 1)
{
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
void recv_pack()
{
int n, from_len;
extern int errno;
signal(SIGALRM, statistics);
from_len = sizeof(from);
while( n_recv < n_send )
{
alarm(MAX_WAIT_TIME);
if( (n = recvfrom(sockfd, recv_data, sizeof(recv_data), 0,
(struct sockaddr *)&from, &from_len)) < 0 )
{
if(EINTR == errno)
continue;
perror("recvfrom error");
continue;
}
gettimeofday(&tv_recv, NULL);
if(unpack(recv_data, n) == -1)
continue;
n_recv ++;
}
return;
}
int unpack(char *buf, int len)
{
int i, iphdr_len;
struct ip *ip;
struct icmp *picmp;
struct timevak *tv_send;
double rtt;
ip = (struct ip *)buf;
iphdr_len = ip->ip_hl << 2;
picmp = (struct icmp *)(buf + iphdr_len);
len -= iphdr_len;
if(len < 8 )
{
printf("ICMP packets\'s length is less than 8.\n");
return -1;
}
if( (picmp->icmp_type == ICMP_ECHOREPLY) && (picmp->icmp_id == pid) )
{
tv_send = (struct timeval *)picmp->icmp_data;
tv_sub(&tv_recv, tv_send);
rtt = tv_recv.tv_sec * 1000 + tv_recv.tv_usec / 1000;
printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n",
len, inet_ntoa(from.sin_addr),
picmp->icmp_seq, ip->ip_ttl, rtt);
}
else
{
return -1;
}
}
void statistics(int signo)
{
printf("\n----------------------PING statistics---------------------\n");
printf("%d packets transmitted, %d received, %%%d lost\n",
n_send, n_recv, (n_send - n_recv) / n_send * 100);
close(sockfd);
exit(1);
}
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;
}
ping 代码
最新推荐文章于 2022-10-18 18:05:35 发布