//제작은 제가 한거 같은데...어디서 참고를 한건지는 기억이 잘..-_-;;
//쓰실때 출처는..코멘트를 해주세요.....흐..
//아마도 제가 기억하기로는 linux source쪽에서 가져 온거로 알고 있습니다..
//모 거의 모든 부분이 linux source쪽 그대로지 않나 싶네요..
//수정한 부분이 있긴 있을텐데..기억이 잘 안나네요..2년전에 작성한거라서리..-_-;;
ping.h
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#define BUFSIZE 1500
char recvbuf[BUFSIZE];
char sendbuf[BUFSIZE];
int datalen;
char *host;
int nsent;
pid_t pid;
int sockfd;
int verbose;
void proc_v4(char *,ssize_t,struct timeval*);
void send_v4(void);
void readloop(void);
void sig_alram(int);
void tv_sub(struct timeval*,struct timeval*);
struct proto{
void (*fproc)(char*,ssize_t,struct timeval*);
void (*fsend)(void);
struct sockaddr *sasend;
struct sockaddr *sarecv;
socklen_t salen;
int icmpproto;
}*pr;
----------------------------------------------------------------------------------------
ping.c
#include "ping.h"
struct proto proto_v4 = {proc_v4,send_v4,NULL,NULL,0,IPPROTO_ICMP};
void readloop(void);
void tv_sub(struct timeval *out,struct timeval *in);
void readloop(void);
int datalen = 56;
void sig_alrm(int signo)
{
(*pr->fsend)();
alarm(1);
return;
}
void send_v4(void)
{
int len;
struct icmp *icmp;
icmp = (struct icmp*)sendbuf;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_id = pid;
icmp->icmp_seq = nsent++;
Gettimeofday((struct timeval *)icmp->icmp_data,NULL);
len = 8+datalen;
icmp->icmp_cksum = 0;
icmp->icmp_cksum = in_cksum((u_short *)icmp,len);
sendto(sockfd,sendbuf,len,0,pr->sasend,pr->salen);
}
unsigned short in_cksum(unsigned short *addr,int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned 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);
}
int main(int argc, char *argv[])
{
int c;
struct addrinfo *ai;
while((c = getopt(argc,argv,"v")) != -1)
{
switch (c)
{
case 'v':
verbose++;
break;
case '?':
printf("error : %c",c);
exit(1);
}
}
if(argc<2)
{
printf("usage: ping <hostname>\n");
exit(0);
}
host = argv[1];
pid = getpid();
Signal(SIGALRM,sig_alrm);
ai = Host_serv(host,NULL,0,0);
printf("PING %s (%s) : %d data bytes\n",ai->ai_canonname,
sock_ntop_host(ai->ai_addr,ai->ai_addrlen),datalen);
if(ai->ai_family == AF_INET){
pr = &proto_v4;
}
else
{
printf("unknown address family %d",ai->ai_family);
exit(0);
}
pr->sasend = ai->ai_addr;
pr->sarecv = Calloc(1,ai->addrlen);
pr->salen = ai->ai_addrlen;
readloop();
exit(0);
}
void readloop(void)
{
int size;
char recvbuf[BUFSIZE];
socklen_t len;
ssize_t n;
struct timeval tval;
sockfd = Socket(pr->sasend->sa_family,SOCK_RAW,pr->icmpproto);
setuid(getuid());
size = 60*1024;
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
sig_alrm(SIGALRM);
for(;;)
{
len = pr->salen;
n = recvfrom(sockfd,recvbuf,sizeof(recvbuf),0,pr->sarecv,&len);
if(n<0)
{
if(errno == EINTR)
continue;
else
err_sys("recvfrom err");
}
Gettimeofday(&tval,NULL);
(*pr->fproc)(recvbuf,n,&tval);
}
}
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;
};
void proc_v4(char *ptr,ssize_t len,struct timeval *tvrecv)
{
int hlen1,icmplen;
double rtt;
struct ip *ip;
struct icmp *icmp;
struct timeval *tvsend;
ip = (struct ip*)ptr;
hlen1 = ip->ip_hl<<2;
icmp = (struct icmp*)(ptr+hlen1);
if((icmplen = len-hlen1)<8)
{
printf("icmplen (%d)<8\n"),icmplen);
exit(-1);
}
if(icmp->icmp_type == ICMP_ECHOREPLY)
{
if(icmp->icmp_id != pid)
return;
if(icmplen<16)
{
printf("icmplen (%d)<16)\n",icmplen);
exit(-1);
}
tvsend = (struct timeval*)icmp->icmp_data;
tv_sub(tvrecv,tvsend);
rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec/1000.0;
printf("%d bytes from %s: type = %d,code = %d\n",
icmplen,Sock_ntop_host(pr->sarecv,pr->salen),
icmp->icmp_seq,ip->ip_ttl,rtt);
}else if(verbose)
{
printf(" %d bytes from %s: type = %d,code = %d\n",
icmplen,Sock_ntop_host(pr->sarecv,pr->salen),
icmp->icmp_type,icmp->icmp_code);
}
}