//쓰실때 출처는..코멘트를 해주세요.....흐..
//아마도 제가 기억하기로는 linux source쪽에서 가져 온거로 알고 있습니다..
//모 거의 모든 부분이 linux source쪽 그대로지 않나 싶네요..
less..
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); } }
less..