- 论坛徽章:
- 0
|
/************关于本文档********************************************
*filename: ping.c
*purpose: 实现简单的ping程序目的
*wrote by: fanyunfei(yinshulei5211314@yahoo.com.cn)
*date time:2007-01-30 20:03
*********************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SA struct sockaddr
#define BUFFSIZE 1024
static struct sockaddr_in dest_addr;
static int sockfd; /** raw socket **/
static int sequence; /** auto initialize to 0 **/
static int counter; /** 记录ping的次数,如果5次都没有反应则放弃 **/
void sig_alrm(int signo); /** handler SIGALRM **/
void send_echo_request(int sockfd, SA *dest_addr);
void recv_echo_reply(int sockfd);
unsigned short check_sum(unsigned short *addr,int len);
void err_sys(const char *errmsg);
int main(int argc, char **argv)
{
struct hostent *h;
struct sigaction act; /* SIGALRM handler **/
/** detect command line argumnet number **/
if (argc != 2) {
fprintf(stderr, "Usage: ./ping \n");
exit(1);
}
/** install SIGALRM signal handler **/
act.sa_handler = sig_alrm;
if (sigemptyset(&act.sa_mask) == -1)
err_sys("sigemptyset error");
act.sa_flags = 0;
if (sigaction(SIGALRM, &act, NULL) == -1)
err_sys("sigaction error");
/** create IPPROTO_ICMP raw socket **/
if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
err_sys("socket error");
if (inet_aton(argv[1], &dest_addr.sin_addr) == 0) {
if ((h = gethostbyname(argv[1])) == NULL) {
fprintf(stderr, "gethostbyname error: %s\n", hstrerror(h_errno));
exit(1);
} else
memcpy(&dest_addr.sin_addr, h->h_addr, sizeof(struct in_addr));
}
/** generate SIGALRM signal for send first echo request **/
if (kill(getpid(), SIGALRM) == -1)
err_sys("kill error");
/** read echo reply **/
recv_echo_reply(sockfd);
exit(0);
}
void sig_alrm(int signo)
{
send_echo_request(sockfd, (SA *) &dest_addr);
counter++; /** increment counter **/
if (counter == 5) {
fprintf(stderr, "host is not alive...\n");
exit(1);
}
alarm(1); /** 每妙钟发送一个回显请求 **/
}
void err_sys(const char *errmsg)
{
perror(errmsg);
exit(errno);
}
void send_echo_request(int sockfd, SA *dest_addr)
{
struct icmp *icmp;
char buff[BUFFSIZE];
ssize_t n;
bzero(buff, sizeof(buff));
icmp = (struct icmp *) buff;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_id = getpid();
icmp->icmp_seq = sequence++;
icmp->icmp_cksum = 0;
icmp->icmp_cksum = check_sum((unsigned short *) icmp, sizeof(struct icmp));
n = sendto(sockfd, buff, sizeof(struct icmp), 0, dest_addr, 16);
if (n != sizeof(struct icmp))
err_sys("sendto error");
}
void recv_echo_reply(int sockfd)
{
struct ip *ip;
struct icmp *icmp;
char buff[BUFFSIZE];
ssize_t len;
int iphlen; /** ip header length **/
for (;;) {
if ((len = recvfrom(sockfd, buff, BUFFSIZE, 0, NULL, NULL)) == -1) {
if (errno = EINTR)
continue;
/** process interrupt **/
else
err_sys("recvfrom error");
}
ip = (struct ip *) buff; /** start of IP header **/
iphlen = ip->ip_hl ip_p != IPPROTO_ICMP) {
fprintf(stderr, "ip datagram is not icmp\n");
exit(1);
}
icmp = (struct icmp *) (buff + iphlen);
if (icmp->icmp_type == ICMP_ECHOREPLY) {
if (icmp->icmp_id != getpid()) {
fprintf(stderr, "icmp_id error\n");
exit(1);
} else {
printf("host is alive...\n");
exit(0);
}
}
} /** for **/
}
/* 下面是首部校验和的算法,偷了别人的 */
unsigned short check_sum(unsigned short *addr,int len)
{
register int nleft = len;
register int sum = 0;
register short *w = addr;
short answer = 0;
while (nleft>1) {
sum+=*w++;
nleft-=2;
}
if (nleft == 1) {
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
return(answer);
}
/******** 运行结果
*********
[root@localhost root]# gcc ping.c -o ping
[root@localhost root]# ./ping www.sohu.com
host is alive...
[root@localhost root]# ./ping 192.168.1.2
host is not alive...
[root@localhost root]#
**************************/
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30746/showart_240433.html |
|