wx_zzm 2002年05月28日
一个实现伪IP的例子(欢迎讨论,分儿多多)
下面的例子编译通过,WIN2000下执行OK,但在win98下执行不通
报告“fail to set sock option2.10042”--即非法参数

请问:有没有办法在WIN98下实现同样功能?



#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define ICMP_ECHO 8

typedef struct iphdr {
unsigned char verlen; // length and version of the header
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;
unsigned char proto; // protocol (TCP, UDP etc)
unsigned short checksum; // IP checksum
unsigned int sourceIP;
unsigned int destIP;

} IPHDR;

typedef struct icmphdr {
BYTE i_type;
BYTE i_code; // type sub code
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;

} ICMPHDR;

unsigned short cal_checksum( unsigned short *buf, int size);

void main()
{
SOCKET s;
WSADATA WSAData;
BOOL bIphdrIncl;
int iRtn;
IPHDR *pIphdr;
ICMPHDR *pIcmphdr;
unsigned long *pIcmpdata;
char buf[1024];
struct sockaddr_in dest;

int ttl=255;

if ( WSAStartup( MAKEWORD( 2, 2), &WSAData)) {
printf( "fail to start up winsock.\n");
return;
}

// create a raw socket to send fake ICMP_ECHO message ...
s = socket( AF_INET, SOCK_RAW, IPPROTO_IP);
if ( s == INVALID_SOCKET) {
printf( "socket error.\n");
return;
}

bIphdrIncl = TRUE;
iRtn=setsockopt(s,IPPROTO_IP,IP_TTL,(char *)&ttl,sizeof(int));
if(iRtn){
printf( "fail to set sock option1.%ld\n",WSAGetLastError());

return;
}
iRtn =
setsockopt( s, IPPROTO_IP, IP_HDRINCL, (char *)&bIphdrIncl, sizeof(int));
if ( iRtn) {
printf( "fail to set sock option2.%ld\n",WSAGetLastError());
return;
}

// fill in ip header ...
pIphdr = (IPHDR *)buf;
pIphdr->verlen = 0x45;
pIphdr->tos = 0;
pIphdr->total_len = sizeof( IPHDR) + sizeof( ICMPHDR) + sizeof( unsigned long);
pIphdr->ident = htons(0);
pIphdr->frag_and_flags = htons(0);
pIphdr->ttl = 255;
pIphdr->proto = IPPROTO_ICMP;
pIphdr->sourceIP = inet_addr( "192.168.0.7");
pIphdr->destIP = inet_addr( "192.168.0.7");
pIphdr->checksum = 0; // ip checksum is set to 0 temperarily.

// fill in icmp header ...
pIcmphdr = (ICMPHDR *)(buf + sizeof( IPHDR));
pIcmphdr->i_type = ICMP_ECHO;
pIcmphdr->i_code = 0;
pIcmphdr->i_cksum = 0;
pIcmphdr->i_id = ( unsigned short)GetCurrentProcessId();
pIcmphdr->i_seq = 0;

// fill in icmp data ...
pIcmpdata = ( unsigned long *)(buf + sizeof( IPHDR) + sizeof( ICMPHDR));
*pIcmpdata = GetTickCount();

// calculate icmp check sum ...
pIcmphdr->i_cksum = cal_checksum( (unsigned short *)pIcmphdr, sizeof(ICMPHDR) + sizeof(unsigned long));

// calculate ip check sum ...
pIphdr->checksum = cal_checksum( (unsigned short *)pIphdr, pIphdr->total_len);

dest.sin_addr.S_un.S_addr = inet_addr( "192.168.0.7");
dest.sin_family = AF_INET;

iRtn =
sendto( s, buf, pIphdr->total_len, 0, (SOCKADDR *)&dest, sizeof(dest));
if ( iRtn == SOCKET_ERROR) {
printf( "fail to send raw ip packet to destination.%ld\n",WSAGetLastError());
return;
} else {
printf( "success.\n");
}

closesocket( s);
WSACleanup();
}

unsigned short cal_checksum( unsigned short *buf, int size)
{
unsigned long cksum = 0;

while( size > 1) {
cksum += *buf++;
size -= sizeof( unsigned short);
}

if(size) {
cksum += *( unsigned char *)buf;
}

cksum = ( cksum >> 16) + ( cksum & 0xffff);
cksum += (cksum >>16);
return ( unsigned short)(~cksum);
}



...全文
25 点赞 收藏 13
写回复
13 条回复

还没有回复,快来抢沙发~

发动态
发帖子
VC/MFC
创建于2007-09-28

7868

社区成员

42.1w+

社区内容

VC/MFC相关问题讨论
社区公告
暂无公告