我想把TCP/IP详解(卷1)第六章 ICMP 中的 icmpaddmask程序移植到windows下,
但是用recvfrom接受不到数据,请指教?
下面是我写的程序:/*File:icmpaddrmask.cpp
*Author:ybluo
*Date:2003-10-27
*Description:
*Issue an ICMP address mask request and print the reply for microsoft windows
*/#include <winsock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")//-------------------------
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;
} IP;typedef struct _icmp
{
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_chsum;
unsigned short icmp_id;
unsigned short icmp_seq;
unsigned long icmp_mask;
}ICMP;const unsigned char ICMP_MASKREQ=17; //mask request
const unsigned char ICMP_MASKREPLY=18;//mask reply;
const int ICMP_MASKLEN=12; /* 12 = 8 bytes of header, 4 bytes of mask */
const int MAX_PACKET=1024; // Max ICMP packet size//-------------------------
SOCKET sockRaw = INVALID_SOCKET;
char recvbuf[MAX_PACKET];
struct sockaddr_in dest;
void Help();
void ShowError(char *);
void SendIcmp();
unsigned short checksum(unsigned short *buffer, int size);
void DecodePack(char *recvbuf, int ilen,sockaddr_in *from);//--------------------------
void main(int argc,char **argv)
{
if( argc !=2 )
{
Help();
return;
} char *szHost=argv[1];
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout<<"WSAStartup() failed: "<<GetLastError();
return;
}
// raw socket
sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(sockRaw == INVALID_SOCKET)
{
ShowError("socket");
}
struct hostent *hp = NULL;
dest.sin_family=AF_INET; //
// Resolve the host's name if necessary
//
dest.sin_family = AF_INET;
if ((dest.sin_addr.s_addr = inet_addr(szHost)) == INADDR_NONE)
{
if ((hp = gethostbyname(szHost)) != NULL)
{
memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length);
dest.sin_family = hp->h_addrtype;
cout<<"dest.sin_addr = "<< inet_ntoa(dest.sin_addr)<<endl;
}
else
{
ShowError("gethostbyname");
}
}
//Send the ICMP address mask request.
SendIcmp(); //receive
while(1)
{
struct sockaddr_in from;
int fromlen;
int iret;
fromlen=sizeof(from);
cout<<"before recvfrom() function "<<endl;
iret=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(sockaddr *)&from, &fromlen);
cout<<"after recvfrom() function "<<endl;
if( iret<0 )
{
ShowError("recvfrom");
continue;
}
cout<<"recv = "<<iret<<endl;
DecodePack(recvbuf,iret,&from);
Sleep(1000); }
WSACleanup();
}
//---------------------------
void Help()
{
cout<<"icmpaddrmask for Microsoft Windows"<<endl;
cout<<"\tby ybluo 2003-10-27"<<endl;
cout<<"Usage:"<<endl;
cout<<"\ticmpaddrmask <Host>"<<endl;
}
//---------------------------
void ShowError(char *szErrorFunction)
{
cout<<szErrorFunction
<<"() failed: "
<<WSAGetLastError()<<endl;
exit(0);
}
//---------------------------
void SendIcmp()
{
ICMP icmp;
memset(&icmp,0,sizeof(ICMP));
icmp.icmp_type=ICMP_MASKREQ;
icmp.icmp_code=0; icmp.icmp_id=GetCurrentProcessId();/* seq and id must be reflected */
icmp.icmp_seq=12345;
/* compute ICMP checksum here */
icmp.icmp_chsum=checksum((unsigned short *)&icmp,ICMP_MASKLEN);
int iret=sendto(sockRaw,
(char *)&icmp,
ICMP_MASKLEN,
0,
(sockaddr *)&dest,
sizeof(sockaddr));
if (iret < 0 || iret != ICMP_MASKLEN)
{
if (iret < 0)
{
ShowError("sendto");
}
cout<<"wrote "<<ICMP_MASKLEN<<" ret="<<iret<<endl;
}
cout<<"wrote = "<<iret<<endl;}
//---------------------------
//
// Function: checksum
//
// Description:
// This function calculates the 16-bit one's complement sum
// of the supplied buffer (ICMP) header
//
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);
}
//--------------------------------------------
void DecodePack(char *recvbuf, int ilen,sockaddr_in *from)
{
IP *ip=NULL;
ICMP *icmp=NULL;
ip=(IP *)recvbuf;
int hlen=ip->h_len * 4; icmp=(ICMP *)(recvbuf+hlen);
if( icmp->icmp_type== ICMP_MASKREPLY)
{
if( ilen-hlen !=ICMP_MASKLEN )
{
cout<<"ilen-hlen = "<<ilen-hlen <<" expected = 12"<<endl;
}
if ( icmp->icmp_seq != 12345)
{
cout<<"received sequence ="<< icmp->icmp_seq<<endl;
}
if( icmp->icmp_id !=GetCurrentProcessId() )
{
cout<< "received id = "<<icmp->icmp_id<<endl;
} cout<<" received mask = "<<hex
<<ntohl(icmp->icmp_mask)
<<inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr)
<<endl;
}
}
//-------------------------------------------
但是用recvfrom接受不到数据,请指教?
下面是我写的程序:/*File:icmpaddrmask.cpp
*Author:ybluo
*Date:2003-10-27
*Description:
*Issue an ICMP address mask request and print the reply for microsoft windows
*/#include <winsock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")//-------------------------
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;
} IP;typedef struct _icmp
{
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_chsum;
unsigned short icmp_id;
unsigned short icmp_seq;
unsigned long icmp_mask;
}ICMP;const unsigned char ICMP_MASKREQ=17; //mask request
const unsigned char ICMP_MASKREPLY=18;//mask reply;
const int ICMP_MASKLEN=12; /* 12 = 8 bytes of header, 4 bytes of mask */
const int MAX_PACKET=1024; // Max ICMP packet size//-------------------------
SOCKET sockRaw = INVALID_SOCKET;
char recvbuf[MAX_PACKET];
struct sockaddr_in dest;
void Help();
void ShowError(char *);
void SendIcmp();
unsigned short checksum(unsigned short *buffer, int size);
void DecodePack(char *recvbuf, int ilen,sockaddr_in *from);//--------------------------
void main(int argc,char **argv)
{
if( argc !=2 )
{
Help();
return;
} char *szHost=argv[1];
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout<<"WSAStartup() failed: "<<GetLastError();
return;
}
// raw socket
sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(sockRaw == INVALID_SOCKET)
{
ShowError("socket");
}
struct hostent *hp = NULL;
dest.sin_family=AF_INET; //
// Resolve the host's name if necessary
//
dest.sin_family = AF_INET;
if ((dest.sin_addr.s_addr = inet_addr(szHost)) == INADDR_NONE)
{
if ((hp = gethostbyname(szHost)) != NULL)
{
memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length);
dest.sin_family = hp->h_addrtype;
cout<<"dest.sin_addr = "<< inet_ntoa(dest.sin_addr)<<endl;
}
else
{
ShowError("gethostbyname");
}
}
//Send the ICMP address mask request.
SendIcmp(); //receive
while(1)
{
struct sockaddr_in from;
int fromlen;
int iret;
fromlen=sizeof(from);
cout<<"before recvfrom() function "<<endl;
iret=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(sockaddr *)&from, &fromlen);
cout<<"after recvfrom() function "<<endl;
if( iret<0 )
{
ShowError("recvfrom");
continue;
}
cout<<"recv = "<<iret<<endl;
DecodePack(recvbuf,iret,&from);
Sleep(1000); }
WSACleanup();
}
//---------------------------
void Help()
{
cout<<"icmpaddrmask for Microsoft Windows"<<endl;
cout<<"\tby ybluo 2003-10-27"<<endl;
cout<<"Usage:"<<endl;
cout<<"\ticmpaddrmask <Host>"<<endl;
}
//---------------------------
void ShowError(char *szErrorFunction)
{
cout<<szErrorFunction
<<"() failed: "
<<WSAGetLastError()<<endl;
exit(0);
}
//---------------------------
void SendIcmp()
{
ICMP icmp;
memset(&icmp,0,sizeof(ICMP));
icmp.icmp_type=ICMP_MASKREQ;
icmp.icmp_code=0; icmp.icmp_id=GetCurrentProcessId();/* seq and id must be reflected */
icmp.icmp_seq=12345;
/* compute ICMP checksum here */
icmp.icmp_chsum=checksum((unsigned short *)&icmp,ICMP_MASKLEN);
int iret=sendto(sockRaw,
(char *)&icmp,
ICMP_MASKLEN,
0,
(sockaddr *)&dest,
sizeof(sockaddr));
if (iret < 0 || iret != ICMP_MASKLEN)
{
if (iret < 0)
{
ShowError("sendto");
}
cout<<"wrote "<<ICMP_MASKLEN<<" ret="<<iret<<endl;
}
cout<<"wrote = "<<iret<<endl;}
//---------------------------
//
// Function: checksum
//
// Description:
// This function calculates the 16-bit one's complement sum
// of the supplied buffer (ICMP) header
//
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);
}
//--------------------------------------------
void DecodePack(char *recvbuf, int ilen,sockaddr_in *from)
{
IP *ip=NULL;
ICMP *icmp=NULL;
ip=(IP *)recvbuf;
int hlen=ip->h_len * 4; icmp=(ICMP *)(recvbuf+hlen);
if( icmp->icmp_type== ICMP_MASKREPLY)
{
if( ilen-hlen !=ICMP_MASKLEN )
{
cout<<"ilen-hlen = "<<ilen-hlen <<" expected = 12"<<endl;
}
if ( icmp->icmp_seq != 12345)
{
cout<<"received sequence ="<< icmp->icmp_seq<<endl;
}
if( icmp->icmp_id !=GetCurrentProcessId() )
{
cout<< "received id = "<<icmp->icmp_id<<endl;
} cout<<" received mask = "<<hex
<<ntohl(icmp->icmp_mask)
<<inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr)
<<endl;
}
}
//-------------------------------------------
检查了几遍,也没发现有什么错,而且它能接收我发出的ping包。把SDK下的ping程序中改icmp_hdr->i_type = ICMP_MASKREQ一样接收不到数据TCP/IP详解(卷1)53页:
RFC规定,除非系统是地址掩码的授权代理,否则它不能发送地址掩码应答(为了成为授权代理,它必须进行特殊配置,以发送这些应答。参见附录E)。但是,正如我们从本例中看到的那样,大多数主机在收到请求时都发送一个应答,甚至有一些主机还发送差错的应答。这可能会是解释,进一步关注