⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prg12_1.c

📁 《unix网络编程技术与分析》一书的C源程序
💻 C
字号:
// File: prg12_1.c
 #include <iostream.h>
 #include <string.h>
 #include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <arpa/inet.h>   /* inet_ntoa */
 #include <unistd.h>      /* close */
 #include <stdio.h>       /* Basic I/O routines          */
 #include <sys/types.h>   /* standard system types       */
 #include <netinet/in.h>  /* Internet address structures */
 #include <sys/socket.h>  /* socket interface functions  */
 #include <netdb.h>       /* host to IP resolution       */
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>  /* ICMP */
 #include <netinet/ip_icmp.h> /* ICMP */ 

 #define ICMPHEAD  8  // ICMP packet header's length
 #define MAXICMPLEN 200  

 /****************
 class: RawSock
 ******************/
 class RawSock
 {
 public:
 int sock;
 int error;
 RawSock(int protocol =0);
 virtual  ~RawSock();
 int send(const void* msg, int msglen,sockaddr* addr,unsigned int len);
 int send(const void* msg, int msglen,char* addr);
 int receive(void* buf,int buflen,sockaddr* from,int* len);
 int Error() {return error;}
 }; 

 class ICMP: public RawSock
 {
 public:
 struct icmp *packet;
 int max_len;
 int length;

 ushort_t checksum(ushort_t *addr,int len);
 ICMP();
 ICMP(int len);
 ~ICMP();
 int send_icmp(char *to, void* buf,int len);
 int recv_icmp(sockaddr* from);
 void setCode(int c) {  packet->icmp_code = c;}
 void setId(int i) { packet->icmp_id = i; }
 void setSeq(int s) { packet->icmp_seq = s;}
 void setType(int t) { packet->icmp_type = t;}
 };

 RawSock::RawSock(int protocol = 0) {
 sock = socket(AF_INET, SOCK_RAW,protocol);
 setuid(getuid());
 if (sock == -1) error= 1;
   else error = 0;
 }

 RawSock::~RawSock(){
 close(sock);
 }

 int RawSock::send(const void* msg,int msglen,sockaddr* to, unsigned int len) {
 if (error) return -1;
 int length = sendto(sock,msg,msglen,0,(const sockaddr*)to,len); 
 if (length == -1) {
   error = 2;
   return -1;
   }
 return length; 
 }

 int RawSock::send(const void* msg,int msglen,char* hostname) {
 sockaddr_in sin;        // Sock Internet address
 if (error) return -1;
 if(hostname) {
   hostent *hostnm = gethostbyname(hostname); 
   if(hostnm == (struct hostent *) 0) {
     return -1;
     }
   sin.sin_addr.s_addr = *((unsigned long *)hostnm->h_addr);
 }
 else   
   return -1; 
 sin.sin_family = AF_INET;

 return send(msg,msglen,(sockaddr *)&sin, sizeof(sin));
 }

 int RawSock::receive(void* buf,int buflen,sockaddr* from,int* len)
 {
 if (error) return -1;
 while (1) {
   int length = recvfrom(sock,buf,buflen,0,from,len); 
   if (length == -1) 
     if (errno == EINTR) continue;
   else {
     error = 3;
     return -1;
     }
   return length;
   }
 }

 /****************
 class: ICMP
 ******************/
 ICMP::ICMP():  RawSock(IPPROTO_ICMP)
 {
 max_len = MAXICMPLEN;
 packet = (icmp*) new char[max_len];

 packet->icmp_code = 0;
 packet->icmp_id = 0;
 packet->icmp_seq = 0;
 packet->icmp_type = ICMP_ECHO;
 }

 ICMP::ICMP(int len):  RawSock(IPPROTO_ICMP) 
 {
 max_len = len;
 packet = (icmp*) new char[max_len];

 packet->icmp_code = 0;
 packet->icmp_id = 0;
 packet->icmp_seq = 0;
 packet->icmp_type = ICMP_ECHO;
 }   

 ICMP::~ICMP()
 {
 delete[] (char*) packet;
 }

 ushort_t ICMP::checksum(ushort_t *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 ICMP::send_icmp(char *host, void* buf,int len)
 {  
 memcpy(packet->icmp_data,buf,len);
 packet->icmp_cksum = 0;
 packet->icmp_cksum = checksum((unsigned short *)packet, ICMPHEAD + 6);

 int err = send(packet,MAXICMPLEN,host);
 return err;
 }

 int ICMP::recv_icmp(sockaddr* from)
 {
 char buf[MAXICMPLEN + 100];
 int	hlen1, icmplen;
 struct ip	*ip;
 struct icmp  *icmp;

 if (Error()) return -1;
 int addrlen = 0;
 int len = receive(buf,MAXICMPLEN+100,from,&addrlen);

 if (len == -1) {
   cout << "Receiving Failed!\n" ;
   return -1;
   }

 ip = (struct ip *) buf;		/* start of IP header */
 hlen1 = ip->ip_hl << 2;		/* length of IP header */

 icmp = (struct icmp *) (buf + hlen1);	/* start of ICMP header */
 if ( (icmplen = len - hlen1) < 8){
   cout << "Receiving Failed!\n" ;
   return -1;
   }

 length = len - hlen1;
 memcpy(packet,icmp,length);
 return 0;
 }

 main(int argc, char *argv[])
 {
 ICMP icmp;
 sockaddr from;
 char *host;
 int count;

 if (argc < 2) {       
   printf("Usage: %s <IP Address> <try_number>\n",argv[0]); 
   exit(1); 
   } 
 if (argc == 2) {
   host = argv[1];
   count = 5;
   }
 if (argc == 3) {
   host = argv[1];
   count = atoi(argv[2]);
   }

 for (int i = 0; i <= count; i++) {
   icmp.setId(getpid());
   icmp.setSeq(i);
   char* test_data= "abcde";
   icmp.send_icmp(host,test_data,strlen(test_data));
   }
 int num = 1;
 while(1) {
   if (icmp.recv_icmp(&from) < 0) continue;
   if (icmp.packet->icmp_type == ICMP_ECHOREPLY) {
     if (icmp.packet->icmp_id == getpid()) {
       printf("%d bytes from %s: seq=%u, data=%s\n",
         icmp.length, host,icmp.packet->icmp_seq, icmp.packet->icmp_data);
       num ++;
       if (num > count) break;
       }
     }  
  }
 }


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -