Author:zfive5(zhaozidong)
Email :zfive5@yahoo.com.cn
连续两天,终于完成了Z5NTS imcp部分-可以发送所有imcp类型数据,对icmp协议也有了近一步的熟悉,IMCP类型说明如下(主要是参见stevens的TCP/ip三卷,这几本读三遍也不为过):
点击查看大图
类型 代码 描述
0 0 回显应答
3 目的不可达
0 网络不可达
1 主机不可达
2 协议不可达
3 端口不可达
4 需要进行分片但设置了不分片比特
5 源站选路失败
6 目的网络不熟悉
7 目的主机不熟悉
8 源主机被隔离(作废不用)
9 目的网络被强制禁止
10 目的主机被强制禁止
11 由于服务类型TOS,网络不可达
12 由于服务类型TOS,主机不可达
13 由于过滤,通信被强制禁止
14 主机越权
15 优先权中止生效
4 0 源端被关闭
5 重定向
0 对网络重定向
1 对主机重定向
2 对服务类型和网络重定向
3 对服务类型和主机重定向
8 0 请求回显(Ping请求)
9 0 路由器通告
10 0 路由器请求
11 超时
0 传输期间生存时间为0
1 在数据报组装期间生存时间为0
12 参数问题
0 坏的IP首部(包括各种差错)
1 缺少必需的选项
13 0 时间戳请求
14 0 时间戳应答
15 0 信息请求(作废不用)
16 0 信息应答(作废不用)
17 0 地址掩码请求
18 0 地址掩码应答
功能界面如下:
功能介绍:
根据所选类型生成对应的格式图样,然后用户在参照对应的格式图样形成对应的协议数据,例如回送请求类型的十六进制数据如下:
类型:08,
代码:00,
校验和:00,00,(这里需要使用CheckSum函数来计算)
标识符:01,02,
序号:02,01,
数据:00,00,00,00
核心代码如下:
typedef strUCt ICMPHeader {
UCHAR icmp_type; // icmp type
UCHAR icmp_code; // icmp code
USHORT icmp_checksum; // icmp checksum
unsigned char szBUF[1];
} ICMPHDR;
int Open()
{
hSock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(hSock==INVALID_SOCKET)
{
return -1;
}
int iTimeOut=15000;
setsockopt(hSock,SOL_SOCKET,SO_RCVTIMEO,(char *)&iTimeOut,sizeof(iTimeOut));
return 0;
}
int Close()
{
if(hSock!=INVALID_SOCKET)
closesocket(hSock);
hSock=NULL;
return 0;
}
int IcmpSend(char *szAddr,char *szInBUF,int iInLen,int iType)
{
struct hostent *phs;
struct sockaddr_in in;
in.sin_family =AF_INET;
in.sin_port=htons(0);
in.sin_addr.S_un.S_addr =inet_addr(szAddr);
if(in.sin_addr.S_un.S_addr==INADDR_NONE)
{
phs=gethostbyname(szAddr);
in.sin_addr.s_addr=*((u_long *)&(phs->h_addr_list[0]));
}
if(iType==0)
{
ICMPHDR *pICMPHDR=(ICMPHDR *)(szInBUF);
pICMPHDR->icmp_checksum=0;
pICMPHDR->icmp_checksum=CheckSum((unsigned short *)szInBUF,iInLen);
}
int iRet;
iRet=sendto(hSock,szInBUF,iInLen,0,(struct sockaddr *)&in,sizeof(struct sockaddr_in));
if(iRet==SOCKET_ERROR)
{
return -1;
}
if(iRet!=iInLen)
{
return -2;
}
return 0;
}
unsigned short CheckSum(unsigned short *szBUF,int iSize)
{
unsigned long ckSum=0;
for(;iSize>1;iSize-=sizeof(unsigned short))
{
ckSum+=*szBUF++;
}
if(iSize==1)
{
ckSum+=*(unsigned char *)szBUF;
}
ckSum=(ckSum>>16)+(ckSum&0xffff);
ckSum+=(ckSum>>16);
return(unsigned short )(~ckSum);
}