|
//******************************************************************* // A ping program. // Copright by Hugo. 2006/03/20 //******************************************************************* #include "stdio.h" #include "sys/types.h" #include "sys/socket.h" #include "netdb.h" #include "netinet/in.h" #include "netinet/in_systm.h" #include "sys/select.h" #include "sys/time.h" // IP Header -- RFC 791 #define ICMP_ECHOREPLY 0 #define ICMP_ECHO 8 #define REQ_DATASIZE 32 typedef struct tagIPHDR { u_char VIHL; // Version and IHL u_char TOS; // Type Of Service short TotLen; // Total Length short ID; // Identification short FlagOff; // Flags and Fragment Offset u_char TTL; // Time To Live u_char Protocol; // Protocol u_short Checksum; // Checksum struct in_addr iaSrc; // Internet Address - Source struct in_addr iaDst; // Internet Address - Destination }IPHDR, *PIPHDR; // ICMP Header - RFC 792 typedef struct tagICMPHDR { u_char Type; // Type u_char Code; // Code u_short Checksum; // Checksum u_short ID; // Identification u_short Seq; // Sequence char Data; // Data }ICMPHDR, *PICMPHDR; // ICMP Echo Request typedef struct tagECHOREQUEST { ICMPHDR icmpHdr; struct timeval echoTime; char cData[REQ_DATASIZE]; }ECHOREQUEST, *PECHOREQUEST; // ICMP Echo Reply typedef struct tagECHOREPLY { IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller[256]; }ECHOREPLY, *PECHOREPLY; pid_t pid; void tv_sub(struct timeval *out,struct timeval *in); unsigned short checksum(unsigned short *buffer, int size); int WaitForEchoReply(int socket); int main(int argc, char **argv) { int sockfd; int nRet; struct sockaddr_in addrDest; struct hostent *Dest; float spenttime; if(argc != 2) { fprintf(stderr, "usage: %s hostname\n", argv[0]); exit(1); } if ((Dest=gethostbyname(argv[1])) == NULL) { /* get the host info */ herror("gethostbyname"); exit(1); } printf("Host name : %s\n", Dest->h_name); // printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)Dest->h_addr))); if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { perror("socket"); exit(1); } addrDest.sin_addr = *((struct in_addr *)Dest->h_addr); addrDest.sin_family = AF_INET; bzero(&(addrDest.sin_zero), 8); ECHOREQUEST echoReq; echoReq.icmpHdr.Type = ICMP_ECHO; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.ID = getpid(); int Seq = 0; for (nRet = 0; nRet < REQ_DATASIZE; nRet++) echoReq.cData[nRet] = ' '+nRet; while(1){ echoReq.icmpHdr.Seq = Seq++; echoReq.icmpHdr.Checksum = 0; gettimeofday(&echoReq.echoTime,NULL); echoReq.icmpHdr.Checksum = checksum((unsigned short*)&echoReq, sizeof(struct tagECHOREQUEST));
if (sendto(sockfd, (struct ECHOREQUEST*)&echoReq, sizeof(struct
tagECHOREQUEST), 0, (struct sockaddr *)&addrDest, sizeof(addrDest))
< 0) { perror("sendto"); exit(1); } if(WaitForEchoReply(sockfd) == -1) { perror("select"); exit(1); } ECHOREPLY icmpRecv; int addr_len; addr_len = sizeof(struct sockaddr);
if (recvfrom(sockfd, (struct ECHOREPLY*)&icmpRecv, sizeof(struct
tagECHOREPLY), 0, (struct sockaddr *)&addrDest, &addr_len) <
0) { perror("sendto"); } else if(icmpRecv.echoRequest.icmpHdr.Type == ICMP_ECHOREPLY) { gettimeofday(&icmpRecv.echoRequest.echoTime, NULL); tv_sub(&icmpRecv.echoRequest.echoTime, &echoReq.echoTime); spenttime=icmpRecv.echoRequest.echoTime.tv_sec*1000+icmpRecv.echoRequest.echoTime.tv_usec*0.001;
printf("Reply from %s: Bytes=%d Id_seq = %d time=%4.3fms
TTL=%d\n",Dest->h_name, sizeof(icmpRecv.echoRequest),
icmpRecv.echoRequest.icmpHdr.Seq, spenttime,icmpRecv.ipHdr.TTL); sleep(1); } } } unsigned short checksum(unsigned short *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(unsigned short); } if(size) { cksum += *(unsigned char*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (unsigned short)(~cksum); } //Wait for echoRecv int WaitForEchoReply(int socket) { struct timeval Timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(socket, &readfds); Timeout.tv_sec = 1; Timeout.tv_usec = 0; return(select(socket+1, &readfds, NULL, NULL, &Timeout)); } /*timeval*/ 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; }
|