1,593
社区成员
发帖
与我相关
我的任务
分享
const
IP_OPTIONS = 1 ;{ set/get IP options }
IP_HDRINCL = 2 ;{ header is included with data }
IP_TOS = 3 ;{ IP type of service and preced}
IP_TTL = 4 ;{ IP time to live }
type
IPHeader=record // 20字节的IP头
iphVerLen :byte; // 版本号和头长度(各占4位)
ipTOS :byte; // 服务类型
ipLength :WORD; // 封包总长度,即整个IP报的长度
ipID :WORD; // 封包标识,惟一标识发送的每一个数据报
ipFlags :WORD; // 标志
ipTTL :byte; // 生存时间,就是TTL
ipProtocol :byte; // 协议,可能是TCP、UDP、ICMP等
ipChecksum :WORD; // 校验和
ipSource :Cardinal; // 源IP地址
ipDestination :Cardinal; // 目标IP地址
end;
PIPHeader=^IPHeader;
UDPHeader = record
sourcePort :WORD; // 源端口号
destinationPort :WORD; // 目的端口号
len :WORD; // 封包长度
checksum :WORD; // 校验和
end;
PUDPHeader=^UDPHeader;
....
function checksum(const Apc:PChar;Asize:integer):WORD;
var cksum:Cardinal;
buff:array of char;
Index:integer;
W:WORD;
b:byte;
begin
Result:=0;
SetLength(buff,Asize);
CopyMemory(buff,Apc,Asize);
cksum := 0;
Index:=0;
while (Asize>1) do
begin
CopyMemory(@W,@buff[Index],sizeof(W));
cksum := cksum + W;
Asize := Asize - sizeof(WORD);
Index := Index + sizeof(WORD);
end;
// 是奇数
if (Asize mod 2)<>0 then
begin
CopyMemory(@b,@buff[Index],sizeof(b));
cksum:=cksum + b;
end;
// 将32位的chsum高16位和低16位相加,然后取反
cksum:=HIWORD(cksum)+LOWORD(cksum);
cksum:=not cksum;
Result:=cksum;
end;
{
计算UDP伪头校验和。UDP校验和基于如下几个域:
源IP地址
目的IP地址
8位0域
8位协议域
16位UDP长度
16位源端口号
16位目的端口号
16位UDP封包长度
16位UDP校验和(0)
UDP净荷
}
procedure ComputeUdpPseudoHeaderChecksum(
pIphdr:PIPHeader;
pUdphdr:PUDPHeader;
payload:PChar;
payloadlen:integer);
var buff:array[0..1023] of char;
ptr:PChar;
chksumlen:integer;
zero:ULONG;
i:integer;
begin
ptr:=@buff;
chksumlen := 0;
zero := 0;
// 包含源IP地址和目的IP地址
CopyMemory(ptr,@pIpHdr.ipSource,sizeof(pIpHdr.ipSource));
ptr:=ptr+sizeof(pIphdr.ipSource);
chksumlen :=chksumlen+ sizeof(pIphdr.ipSource);
CopyMemory(ptr, @pIphdr.ipDestination, sizeof(pIphdr.ipDestination));
ptr :=ptr + sizeof(pIphdr.ipDestination);
chksumlen :=chksumlen + sizeof(pIphdr.ipDestination);
// 包含8位0域
CopyMemory(ptr, @zero, 1);
ptr :=ptr + 1;
chksumlen := chksumlen + 1;
// 协议
CopyMemory(ptr, @pIphdr.ipProtocol, sizeof(pIphdr.ipProtocol));
ptr := ptr + sizeof(pIphdr.ipProtocol);
chksumlen := chksumlen + sizeof(pIphdr.ipProtocol);
// UDP长度
CopyMemory(ptr, @pUdphdr.len, sizeof(pUdphdr.len));
ptr :=ptr + sizeof(pUdphdr.len);
chksumlen :=chksumlen + sizeof(pUdphdr.len);
// UDP源端口号
CopyMemory(ptr, @pUdphdr.sourcePort, sizeof(pUdphdr.sourcePort));
ptr := ptr + sizeof(pUdphdr.sourcePort);
chksumlen := chksumlen + sizeof(pUdphdr.sourcePort);
// UDP目的端口号
CopyMemory(ptr, @pUdphdr.destinationPort, sizeof(pUdphdr.destinationPort));
ptr :=ptr + sizeof(pUdphdr.destinationPort);
chksumlen := chksumlen + sizeof(pUdphdr.destinationPort);
// 又是UDP长度
CopyMemory(ptr, @pUdphdr.len, sizeof(pUdphdr.len));
ptr := ptr + sizeof(pUdphdr.len);
chksumlen := chksumlen + sizeof(pUdphdr.len);
// 16位的UDP校验和,置为0
CopyMemory(ptr, @zero, sizeof(WORD));
ptr :=ptr + sizeof(WORD);
chksumlen :=chksumlen + sizeof(WORD);
// 净荷
CopyMemory(ptr, payload, payloadlen);
ptr :=ptr + payloadlen;
chksumlen :=chksumlen + payloadlen;
// 补齐到下一个16位边界
for i:=0 to payloadlen div 2 do
begin
ptr^ := chr(0);
ptr:=ptr + 1;
chksumlen:=chksumlen+1;
end;
// 计算这个校验和,将结果填充到UDP头
pUdphdr.checksum := checksum(PChar(@buff), chksumlen);
end;
procedure TForm1.Button10Click(Sender: TObject);
var bIncl:bool;// 即 longbool;
buff:array[0..1023] of char;
pIpHdr:PIPHeader;
pUdpHdr:PUDPHeader;
destAddr:SOCKADDR_IN;
nRet:integer;
s,szSourceIp,szDestIp:string;
nDestPort,nSourcePort:WORD;
pData:PChar;
begin
ZeroMemory(@buff,1024);
szSourceIp:='192.168.2.137';
szDestIp:='192.168.2.1';
nDestPort:=53;
nSourcePort:=1101;
s:=#$00+#$02 +#$01+#$00 +#$00+#$01 +#$00+#$00 +#$00+#$00 +#$00+#$00
+#$03 +'www' +#$03 +'163' +#$03 +'com' +#$00+#$00 +#$01+#$00 +#$01;
Memo1.Lines.Add('length(s) : '+inttostr(length(s)));
rawSocket:=socket(AF_INET,SOCK_RAW,IPPROTO_UDP);
bIncl:=true;
setsockopt(rawSocket,IPPROTO_IP,IP_HDRINCL,PChar(@bIncl),sizeof(bIncl));
pIpHdr:=PIPHeader(@buff);
pIpHdr.iphVerLen:= 4 shl 4 or (sizeof(IPHeader) div sizeof(ULONG));
pIpHdr.ipLength:=htons(sizeof(IPHeader)+sizeof(UDPHeader)+length(s));
pIpHdr.ipTTL:=128;
pIpHdr.ipProtocol:=IPPROTO_UDP;
pIpHdr.ipSource:=inet_addr(PChar(szSourceIp));
pIpHdr.ipDestination:=inet_addr(PChar(szDestIp));
pIpHdr.ipChecksum:=checksum(PChar(pIpHdr),sizeof(IPHeader));
Memo1.Lines.Add('pIpHdr.ipChecksum : '+inttostr(pIpHdr.ipChecksum));
pUdpHdr:=PUDPHeader(@buff[sizeof(IPHeader)]);
pUdpHdr.sourcePort:=htons(nSourcePort);
pUdpHdr.destinationPort:=htons(nDestPort);
pUdpHdr.len:=htons(sizeof(UDPHeader)+length(s));
pUdpHdr.checksum:=0;
pData:=@buff[sizeof(IPHeader)+sizeof(UDPHeader)];
CopyMemory(pData,PChar(s),length(s));
ComputeUdpPseudoHeaderChecksum(pIpHdr,pUdpHdr,pData,length(s));
Memo1.Lines.Add('pUdpHdr.checksum : '+inttostr(pUdpHdr.checksum));
ZeroMemory(@destAddr,sizeof(SOCKADDR_IN));
destAddr.sin_family:=AF_INET;
destAddr.sin_port:=htons(nDestPort);
destAddr.sin_addr.S_addr:=inet_addr(PChar(szDestIp));
nRet:=sendto(rawSocket,buff,sizeof(IPHeader)+sizeof(UDPHeader)+length
(s),0,destAddr,sizeof(destAddr));
if nRet=SOCKET_ERROR then
begin
nRet:=WSAGetLastError;
memo1.Lines.Add('Send failed : '+inttostr(nRet));
end
else
Memo1.Lines.Add('Send '+inttostr(nRet)+' bytes');
CloseSocket(rawSocket);
end;
length(s) : 29
pIpHdr.ipChecksum : 55732
pUdpHdr.checksum : 8523
Send failed : 10049
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Winsock2;
const
IP_OPTIONS = 1 ;{ set/get IP options }
IP_HDRINCL = 2 ;{ header is included with data }
IP_TOS = 3 ;{ IP type of service and preced}
IP_TTL = 4 ;{ IP time to live }
type
IPHeader=record // 20字节的IP头
iphVerLen :byte; // 版本号和头长度(各占4位)
ipTOS :byte; // 服务类型
ipLength :WORD; // 封包总长度,即整个IP报的长度
ipID :WORD; // 封包标识,惟一标识发送的每一个数据报
ipFlags :WORD; // 标志
ipTTL :byte; // 生存时间,就是TTL
ipProtocol :byte; // 协议,可能是TCP、UDP、ICMP等
ipChecksum :WORD; // 校验和
ipSource :Cardinal; // 源IP地址
ipDestination :Cardinal; // 目标IP地址
end;
PIPHeader=^IPHeader;
UDPHeader = record
sourcePort :WORD; // 源端口号
destinationPort :WORD; // 目的端口号
len :WORD; // 封包长度
checksum :WORD; // 校验和
end;
PUDPHeader=^UDPHeader;
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var wVersionRequested:DWORD;
wsaData1:tWSADATA;
err:integer;
begin
wVersionRequested:=MAKEWORD(2,2);
err:=WSAStartup(wVersionRequested,wsaData1);
if err<>0 then
begin
showmessage('WSAStartup failed');
exit;
end;
if (HIBYTE(wsaData1.wVersion)<>2)or(LOBYTE(wsaData1.wVersion)<>2) then
begin
showmessage('(HIBYTE(wsaData1.wVersion)<>2)||(LOBYTE(wsaData1.wVersion)');
exit;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
WSACleanup();
end;
function checksum(const Apc:PChar;Asize:integer):WORD;
var cksum:Cardinal;
buff:array of char;
Index:integer;
W:WORD;
b:byte;
begin
Result:=0;
SetLength(buff,Asize);
CopyMemory(buff,Apc,Asize);
cksum := 0;
Index:=0;
while (Asize>1) do
begin
CopyMemory(@W,@buff[Index],sizeof(W));
cksum := cksum + W;
Asize := Asize - sizeof(WORD);
Index := Index + sizeof(WORD);
end;
// 是奇数
if (Asize mod 2)<>0 then
begin
CopyMemory(@b,@buff[Index],sizeof(b));
cksum:=cksum + b;
end;
// 将32位的chsum高16位和低16位相加,然后取反
cksum:=HIWORD(cksum)+LOWORD(cksum);
cksum:=not cksum;
Result:=cksum;
end;
{
计算UDP伪头校验和。UDP校验和基于如下几个域:
源IP地址
目的IP地址
8位0域
8位协议域
16位UDP长度
16位源端口号
16位目的端口号
16位UDP封包长度
16位UDP校验和(0)
UDP净荷
}
procedure ComputeUdpPseudoHeaderChecksum(
pIphdr:PIPHeader;
pUdphdr:PUDPHeader;
payload:PChar;
payloadlen:integer);
var buff:array[0..1023] of char;
ptr:PChar;
chksumlen:integer;
zero:ULONG;
i:integer;
begin
ptr:=@buff;
chksumlen := 0;
zero := 0;
// 包含源IP地址和目的IP地址
CopyMemory(ptr,@pIpHdr.ipSource,sizeof(pIpHdr.ipSource));
ptr:=ptr+sizeof(pIphdr.ipSource);
chksumlen :=chksumlen+ sizeof(pIphdr.ipSource);
CopyMemory(ptr, @pIphdr.ipDestination, sizeof(pIphdr.ipDestination));
ptr :=ptr + sizeof(pIphdr.ipDestination);
chksumlen :=chksumlen + sizeof(pIphdr.ipDestination);
// 包含8位0域
CopyMemory(ptr, @zero, 1);
ptr :=ptr + 1;
chksumlen := chksumlen + 1;
// 协议
CopyMemory(ptr, @pIphdr.ipProtocol, sizeof(pIphdr.ipProtocol));
ptr := ptr + sizeof(pIphdr.ipProtocol);
chksumlen := chksumlen + sizeof(pIphdr.ipProtocol);
// UDP长度
CopyMemory(ptr, @pUdphdr.len, sizeof(pUdphdr.len));
ptr :=ptr + sizeof(pUdphdr.len);
chksumlen :=chksumlen + sizeof(pUdphdr.len);
// UDP源端口号
CopyMemory(ptr, @pUdphdr.sourcePort, sizeof(pUdphdr.sourcePort));
ptr := ptr + sizeof(pUdphdr.sourcePort);
chksumlen := chksumlen + sizeof(pUdphdr.sourcePort);
// UDP目的端口号
CopyMemory(ptr, @pUdphdr.destinationPort, sizeof(pUdphdr.destinationPort));
ptr :=ptr + sizeof(pUdphdr.destinationPort);
chksumlen := chksumlen + sizeof(pUdphdr.destinationPort);
// 又是UDP长度
CopyMemory(ptr, @pUdphdr.len, sizeof(pUdphdr.len));
ptr := ptr + sizeof(pUdphdr.len);
chksumlen := chksumlen + sizeof(pUdphdr.len);
// 16位的UDP校验和,置为0
CopyMemory(ptr, @zero, sizeof(WORD));
ptr :=ptr + sizeof(WORD);
chksumlen :=chksumlen + sizeof(WORD);
// 净荷
CopyMemory(ptr, payload, payloadlen);
ptr :=ptr + payloadlen;
chksumlen :=chksumlen + payloadlen;
// 补齐到下一个16位边界
for i:=0 to payloadlen div 2 do
begin
ptr^ := chr(0);
ptr:=ptr + 1;
chksumlen:=chksumlen+1;
end;
// 计算这个校验和,将结果填充到UDP头
pUdphdr.checksum := checksum(PChar(@buff), chksumlen);
end;
procedure TForm1.Button1Click(Sender: TObject);
var bIncl:bool;// 即 longbool;
buff:array[0..1023] of char;
pIpHdr:PIPHeader;
pUdpHdr:PUDPHeader;
destAddr: TSOCKADDRIN;
nRet:integer;
s,szSourceIp,szDestIp:string;
nDestPort,nSourcePort:WORD;
pData:PChar;
rawSocket:TSocket;
begin
ZeroMemory(@buff,1024);
szSourceIp:='10.0.0.138';
szDestIp:='10.0.0.138';
nDestPort:=53;
nSourcePort:=1101;
s:=#$00+#$02 +#$01+#$00 +#$00+#$01 +#$00+#$00 +#$00+#$00 +#$00+#$00
+#$03 +'www' +#$03 +'163' +#$03 +'com' +#$00+#$00 +#$01+#$00 +#$01;
{
s:=#$00+#$02+#$01+#$00+#$00+#$01+#$00+#$00+#$00+#$00+#$00+#$00+#$03+#$77+#$77+#$77+#$03+#$31
+#$6+#$33+#$03+#$63+#$6f+#$6d+#$00+#$00+#$01+#$00+#$01;
}
Memo1.Lines.Add('length(s) : '+inttostr(length(s)));
rawSocket:=socket(AF_INET,SOCK_RAW,IPPROTO_UDP);
bIncl:=true;
setsockopt(rawSocket,IPPROTO_IP,IP_HDRINCL,PChar(@bIncl),sizeof(bIncl));
pIpHdr:=PIPHeader(@buff);
pIpHdr.iphVerLen:= 4 shl 4 or (sizeof(IPHeader) div sizeof(ULONG));
pIpHdr.ipLength:=htons(sizeof(IPHeader)+sizeof(UDPHeader)+length(s));
pIpHdr.ipTTL:=128;
pIpHdr.ipProtocol:=IPPROTO_UDP;
pIpHdr.ipSource:=inet_addr(PChar(szSourceIp));
pIpHdr.ipDestination:=inet_addr(PChar(szDestIp));
pIpHdr.ipChecksum:=checksum(PChar(pIpHdr),sizeof(IPHeader));
Memo1.Lines.Add('pIpHdr.ipChecksum : '+inttostr(pIpHdr.ipChecksum));
pUdpHdr:=PUDPHeader(@buff[sizeof(IPHeader)]);
pUdpHdr.sourcePort:=htons(nSourcePort);
pUdpHdr.destinationPort:=htons(nDestPort);
pUdpHdr.len:=htons(sizeof(UDPHeader)+length(s));
pUdpHdr.checksum:=0;
pData:=@buff[sizeof(IPHeader)+sizeof(UDPHeader)];
CopyMemory(pData,PChar(s),length(s));
ComputeUdpPseudoHeaderChecksum(pIpHdr,pUdpHdr,pData,length(s));
Memo1.Lines.Add('pUdpHdr.checksum : '+inttostr(pUdpHdr.checksum));
ZeroMemory(@destAddr,sizeof(TSOCKADDRIN));
destAddr.sin_family:=AF_INET;
destAddr.sin_port:=htons(nDestPort);
destAddr.sin_addr.S_addr:=inet_addr(PChar(szDestIp));
nRet:=sendto(rawSocket,buff,sizeof(IPHeader)+sizeof(UDPHeader)+length(s),0, PSockAddr(@destAddr), sizeof(destAddr));
if nRet=SOCKET_ERROR then
begin
nRet:=WSAGetLastError;
memo1.Lines.Add('Send failed : '+inttostr(nRet));
end
else
Memo1.Lines.Add('Send '+inttostr(nRet)+' bytes');
CloseSocket(rawSocket);
end;
end.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
WinSock;
const
IP_OPTIONS = 1 ;{ set/get IP options }
IP_HDRINCL = 2 ;{ header is included with data }
IP_TOS = 3 ;{ IP type of service and preced}
IP_TTL = 4 ;{ IP time to live }
type
IPHeader=record // 20字节的IP头
iphVerLen :byte; // 版本号和头长度(各占4位)
ipTOS :byte; // 服务类型
ipLength :WORD; // 封包总长度,即整个IP报的长度
ipID :WORD; // 封包标识,惟一标识发送的每一个数据报
ipFlags :WORD; // 标志
ipTTL :byte; // 生存时间,就是TTL
ipProtocol :byte; // 协议,可能是TCP、UDP、ICMP等
ipChecksum :WORD; // 校验和
ipSource :Cardinal; // 源IP地址
ipDestination :Cardinal; // 目标IP地址
end;
PIPHeader=^IPHeader;
UDPHeader = record
sourcePort :WORD; // 源端口号
destinationPort :WORD; // 目的端口号
len :WORD; // 封包长度
checksum :WORD; // 校验和
end;
PUDPHeader=^UDPHeader;
function checksum(const Apc:PChar;Asize:integer):WORD;
var cksum:Cardinal;
buff:array of char;
Index:integer;
W:WORD;
b:byte;
begin
Result:=0;
SetLength(buff,Asize);
CopyMemory(buff,Apc,Asize);
cksum := 0;
Index:=0;
while (Asize>1) do
begin
CopyMemory(@W,@buff[Index],sizeof(W));
cksum := cksum + W;
Asize := Asize - sizeof(WORD);
Index := Index + sizeof(WORD);
end;
// 是奇数
if (Asize mod 2)<>0 then
begin
CopyMemory(@b,@buff[Index],sizeof(b));
cksum:=cksum + b;
end;
// 将32位的chsum高16位和低16位相加,然后取反
cksum:=HIWORD(cksum)+LOWORD(cksum);
cksum:=not cksum;
Result:=cksum;
end;
{
计算UDP伪头校验和。UDP校验和基于如下几个域:
源IP地址
目的IP地址
8位0域
8位协议域
16位UDP长度
16位源端口号
16位目的端口号
16位UDP封包长度
16位UDP校验和(0)
UDP净荷
}
procedure ComputeUdpPseudoHeaderChecksum(
pIphdr:PIPHeader;
pUdphdr:PUDPHeader;
payload:PChar;
payloadlen:integer);
var buff:array[0..1023] of char;
ptr:PChar;
chksumlen:integer;
zero:ULONG;
i:integer;
begin
ptr:=@buff;
chksumlen := 0;
zero := 0;
// 包含源IP地址和目的IP地址
CopyMemory(ptr,@pIpHdr.ipSource,sizeof(pIpHdr.ipSource));
ptr:=ptr+sizeof(pIphdr.ipSource);
chksumlen :=chksumlen+ sizeof(pIphdr.ipSource);
CopyMemory(ptr, @pIphdr.ipDestination, sizeof(pIphdr.ipDestination));
ptr :=ptr + sizeof(pIphdr.ipDestination);
chksumlen :=chksumlen + sizeof(pIphdr.ipDestination);
// 包含8位0域
CopyMemory(ptr, @zero, 1);
ptr :=ptr + 1;
chksumlen := chksumlen + 1;
// 协议
CopyMemory(ptr, @pIphdr.ipProtocol, sizeof(pIphdr.ipProtocol));
ptr := ptr + sizeof(pIphdr.ipProtocol);
chksumlen := chksumlen + sizeof(pIphdr.ipProtocol);
// UDP长度
CopyMemory(ptr, @pUdphdr.len, sizeof(pUdphdr.len));
ptr :=ptr + sizeof(pUdphdr.len);
chksumlen :=chksumlen + sizeof(pUdphdr.len);
// UDP源端口号
CopyMemory(ptr, @pUdphdr.sourcePort, sizeof(pUdphdr.sourcePort));
ptr := ptr + sizeof(pUdphdr.sourcePort);
chksumlen := chksumlen + sizeof(pUdphdr.sourcePort);
// UDP目的端口号
CopyMemory(ptr, @pUdphdr.destinationPort, sizeof(pUdphdr.destinationPort));
ptr :=ptr + sizeof(pUdphdr.destinationPort);
chksumlen := chksumlen + sizeof(pUdphdr.destinationPort);
// 又是UDP长度
CopyMemory(ptr, @pUdphdr.len, sizeof(pUdphdr.len));
ptr := ptr + sizeof(pUdphdr.len);
chksumlen := chksumlen + sizeof(pUdphdr.len);
// 16位的UDP校验和,置为0
CopyMemory(ptr, @zero, sizeof(WORD));
ptr :=ptr + sizeof(WORD);
chksumlen :=chksumlen + sizeof(WORD);
// 净荷
CopyMemory(ptr, payload, payloadlen);
ptr :=ptr + payloadlen;
chksumlen :=chksumlen + payloadlen;
// 补齐到下一个16位边界
for i:=0 to payloadlen div 2 do
begin
ptr^ := chr(0);
ptr:=ptr + 1;
chksumlen:=chksumlen+1;
end;
// 计算这个校验和,将结果填充到UDP头
pUdphdr.checksum := checksum(PChar(@buff), chksumlen);
end;
var bIncl:Integer;// 即 longbool;
buff:array[0..1023] of char;
pIpHdr:PIPHeader;
pUdpHdr:PUDPHeader;
destAddr:SOCKADDR_IN;
nRet:integer;
s,szSourceIp,szDestIp:string;
nDestPort,nSourcePort:WORD;
rawSocket:TSocket;
pData:PChar;
WSData: TWSAData;
begin
ZeroMemory(@buff,1024);
WSAStartup(MakeWord(1,1),WSData);
szSourceIp:='192.168.2.137';
szDestIp:='192.168.2.1';
nDestPort:=53;
nSourcePort:=1101;
s:=#$00+#$02 +#$01+#$00 +#$00+#$01 +#$00+#$00 +#$00+#$00 +#$00+#$00
+#$03 +'www' +#$03 +'163' +#$03 +'com' +#$00+#$00 +#$01+#$00 +#$01;
Writeln('length(s) : '+inttostr(length(s)));
rawSocket:=socket(AF_INET,SOCK_RAW,IPPROTO_UDP);
bIncl:=1;
//nRet:=setsockopt(rawSocket,IPPROTO_IP,IP_HDRINCL,@bIncl,4);
if nRet=SOCKET_ERROR then
begin
nRet:=WSAGetLastError;
Writeln('setsockopt failed : '+inttostr(nRet));
end
else
Writeln('setsockopt '+inttostr(nRet)+'');
pIpHdr:=PIPHeader(@buff);
pIpHdr.iphVerLen:= 4 shl 4 or (sizeof(IPHeader) div sizeof(ULONG));
pIpHdr.ipLength:=htons(sizeof(IPHeader)+sizeof(UDPHeader)+length(s));
pIpHdr.ipTTL:=128;
pIpHdr.ipProtocol:=IPPROTO_UDP;
pIpHdr.ipSource:=inet_addr(PChar(szSourceIp));
pIpHdr.ipDestination:=inet_addr(PChar(szDestIp));
pIpHdr.ipChecksum:=checksum(PChar(pIpHdr),sizeof(IPHeader));
Writeln('pIpHdr.ipChecksum : '+inttostr(pIpHdr.ipChecksum));
pUdpHdr:=PUDPHeader(@buff[sizeof(IPHeader)]);
pUdpHdr.sourcePort:=htons(nSourcePort);
pUdpHdr.destinationPort:=htons(nDestPort);
pUdpHdr.len:=htons(sizeof(UDPHeader)+length(s));
pUdpHdr.checksum:=0;
pData:=@buff[sizeof(IPHeader)+sizeof(UDPHeader)];
CopyMemory(pData,PChar(s),length(s));
ComputeUdpPseudoHeaderChecksum(pIpHdr,pUdpHdr,pData,length(s));
Writeln('pUdpHdr.checksum : '+inttostr(pUdpHdr.checksum));
ZeroMemory(@destAddr,sizeof(SOCKADDR_IN));
destAddr.sin_family:=AF_INET;
destAddr.sin_port:=htons(nDestPort);
destAddr.sin_addr.S_addr:=inet_addr(PChar(szDestIp));
nRet:=sendto(rawSocket,buff,sizeof(IPHeader)+sizeof(UDPHeader)+length(s),0,destAddr,sizeof(destAddr));
if nRet=SOCKET_ERROR then
begin
nRet:=WSAGetLastError;
Writeln('Send failed : '+inttostr(nRet));
end
else
Writeln('Send '+inttostr(nRet)+' bytes');
CloseSocket(rawSocket);
Readln(rawSocket);
WSACleanup;
end.