//dos下的ping.c
//网络是pctcp,开发工具borlandc 3.1
//问题是:1,dos发icmp包时,SOKET用什么参数,否则recvfrom不能接受到回复包
//问题是:2,谁有更好的方法,请和我联系,
toter@163.com
//全部源码如下,请教高手。。。
 /*所用的lib包
   sconfig.lib
   snetlib.lib
   spc.lib
   ssocket.lib
 */
  #include   <stdio.h>
  #include   <dos.h>
  #include   <stdlib.h>
  #include   <string.h>   
  #include   <time.h> 
  #include   <netdb.h>  
  #include   <process.h>  
  #include   <arpa/inet.h>  
  #include   <sys/types.h>
  #include   <sys/socket.h>
  #include   <sys/types.h>   
  #include   <sys/ioctl.h>      
  #include   <netinet\in.h>
 
	typedef int INT;
	typedef unsigned int UINT;
	typedef unsigned long DWORD;
	typedef int BOOL;
	typedef unsigned char BYTE;
	typedef unsigned short WORD;
	typedef float FLOAT;
	typedef unsigned long ULONG;
	typedef unsigned short USHORT;
	typedef unsigned char UCHAR;
	typedef char *PSZ;
	
	#define PORT 1000    /* the port client will be connecting to */
	#define  ServerIP   "192.168.1.43"
	#define   ICMP_ECHO   8     
	#define MAX_PACKET       1024      // Max ICMP packet size
typedef struct _iphdr 
{
    unsigned int   h_len:4;        // Length of the header
    unsigned int   version:4;      // Version of IP
    unsigned char  tos;            // Type of service
    unsigned short total_len;      // Total length of the packet
    unsigned short ident;          // Unique identifier
    unsigned short frag_and_flags; // Flags
    unsigned char  ttl;            // Time to live
    unsigned char  proto;          // Protocol (TCP, UDP etc)
    unsigned short checksum;       // IP checksum
    unsigned int   sourceIP;
    unsigned int   destIP;
} IpHeader;
typedef struct _icmphdr 
{
    BYTE   i_type;
    BYTE   i_code;                 // Type sub code
    USHORT i_cksum;
    USHORT i_id;
    USHORT i_seq;
    // This is not the standard header, but we reserve space for time
    ULONG  timestamp;
} IcmpHeader;
//
// IP option header - use with socket option IP_OPTIONS
//
typedef struct _ipoptionhdr
{
    unsigned char        code;        // Option type
    unsigned char        len;         // Length of option hdr
    unsigned char        ptr;         // Offset into options
    unsigned long        addr;     // List of IP addrs
} IpOptionHeader;
void FillICMPData(char *icmp_data, int datasize)
{
   IcmpHeader *icmp_hdr = NULL;
    char       *datapart = NULL;
    icmp_hdr = (IcmpHeader*)icmp_data;
    icmp_hdr->i_type = ICMP_ECHO;        // Request an ICMP echo
    icmp_hdr->i_code = 0;
    icmp_hdr->i_id = (USHORT)getpid();
    icmp_hdr->i_cksum = 0;
    icmp_hdr->i_seq = 0;
  
    datapart = icmp_data + sizeof(IcmpHeader);
}
  //puclic   code   
  //网际校验和生产算法   
  //网际校验和是被校验数据16位值的反码和(ones-complement   sum)   
  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);   
  }   
  
  main()
  {
	int   sockfd;
	int  iSendSize;
	  struct   sockaddr_in   dest,from;   
	char   icmp_data;
	int   datasize,ret,tmp;
	USHORT             seq_no ;
 
	int   fromlen;
	int   iRecvSize; 
	IpOptionHeader   m_ipopt;
	char   recv_buffer;
	long            last_time, now, timeout = 15L;
	
  if((sockfd=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))<0)//这里不知道用在dos下用什么参数
  //if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)//dos下的upd通讯连接方式
  {
     printf("socket() failed\n");
     exit(1);
  }
  dest.sin_family =AF_INET;
  //server.sin_port   =htons( PORT );
  dest.sin_addr.s_addr = inet_addr(ServerIP);
  
    // Create the ICMP packet 
datasize += sizeof(IcmpHeader);
memset(icmp_data,0,MAX_PACKET);
FillICMPData(icmp_data,datasize);
 ((IcmpHeader*)icmp_data)->i_cksum = 0;
 ((IcmpHeader*)icmp_data)->timestamp = (unsigned   long)time(NULL);
 ((IcmpHeader*)icmp_data)->i_seq = seq_no++;
 ((IcmpHeader*)icmp_data)->i_cksum = in_cksum((unsigned   short*)icmp_data,   sizeof(IcmpHeader)   +   datasize);
 
  iSendSize=  sendto(sockfd, icmp_data,1024,0, (struct sockaddr*)&dest, sizeof(dest)) ;
  if (iSendSize< 0 )
  {
  	printf("icmp sendto 192.168.1.43 failed\n");
  	close(sockfd);
  	exit(2);		  		
  }
   printf("发送的数据 %d \n",iSendSize);
   fprintf(stdout,   "Reply...\r\n");   
  
  
	
  memset(&from,   0,   sizeof   from);   
  memset(recv_buffer,   0,   1024);  
  fromlen   =   sizeof(from);   
  iRecvSize   =   recvfrom(sockfd,   recv_buffer,   1024,   0,   (struct   sockaddr*)&from,     &fromlen);   
  if   (iRecvSize   >   0){   
  	printf("recvfrom 192.168.1.43 success\n");
  }else
  {    
  	printf("recvfrom 192.168.1.43 failed\n");
  }	
	  
    close(sockfd);
    return 1;
  }