function wsagetlasterror: integer; stdcall;
function wsastartup(wversionrequired: word; var wsdata: twsadata): integer; stdcall;
function wsacleanup: integer; stdcall;
const
af_inet = 2; // internetwork: udp, tcp, etc.
ip_hdrincl = 2; // ip header include
sock_raw = 3; // raw-protocol interface
ipproto_ip = 0; // dummy for ip
ipproto_tcp = 6; // tcp
ipproto_udp = 17; // user datagram protocol
ipproto_raw = 255; // raw ip packet
invalid_socket = tsocket(not(0));
socket_error = -1;
var
form1: tform1;
implementation
// import winsock 2 functions
const winsocket = 'ws2_32.dll';
function closesocket; external winsocket name 'closesocket';
function socket; external winsocket name 'socket';
function sendto; external winsocket name 'sendto';
function setsockopt; external winsocket name 'setsockopt';
function inet_addr; external winsocket name 'inet_addr';
function htons; external winsocket name 'htons';
function wsagetlasterror; external winsocket name 'wsagetlasterror';
function wsastartup; external winsocket name 'wsastartup';
function wsacleanup; external winsocket name 'wsacleanup';
{$r *.dfm}
function checksum(var buffer; size : integer) : word;
type
twordarray = array[0..1] of word;
var
chksum : longword;
i : integer;
begin
chksum := 0;
i := 0;
while size > 1 do begin
chksum := chksum + twordarray(buffer);
inc(i);
size := size - sizeof(word);
end;
if size=1 then chksum := chksum + byte(twordarray(buffer));
chksum := (chksum shr 16) + (chksum and $ffff);
chksum := chksum + (chksum shr 16);
result := word(chksum);
end;
procedure buildheaders(
fromip : string;
ifromport : word;
toip : string;
itoport : word;
strmessage : string;
var buf : tpacketbuffer;
var remote : tsockaddr;
var itotalsize : word
);
var
dwfromip : longword;
dwtoip : longword;
iipversion : word;
iipsize : word;
iphdr : t_ip_header;
udphdr : t_udp_header;
iudpsize : word;
iudpchecksumsize : word;
cksum : word;
ptr : ^byte;
procedure incptr(value : integer);
begin
ptr := pointer(integer(ptr) + value);
end;
begin
// convert ip address'ss
dwfromip := inet_addr(pchar(fromip));
dwtoip := inet_addr(pchar(toip));
// 初始化 ip 头
//
itotalsize := sizeof(iphdr) + sizeof(udphdr) + length(strmessage);
iipversion := 4;
iipsize := sizeof(iphdr) div sizeof(longword);
iphdr.ip_verlen := (iipversion shl 4) or iipsize;
iphdr.ip_tos := 0; // ip type of service
iphdr.ip_totallength := htons(itotalsize); // total packet len
iphdr.ip_id := 0; // unique identifier: set to 0
iphdr.ip_offset := 0; // fragment offset field
iphdr.ip_ttl := 128; // time to live
iphdr.ip_protocol := $11; // protocol(udp)
iphdr.ip_checksum := 0 ; // ip checksum
iphdr.ip_srcaddr := dwfromip; // source address
iphdr.ip_destaddr := dwtoip; // destination address
//
// 初始化 udp 头
//
iudpsize := sizeof(udphdr) + length(strmessage);
udphdr.src_portno := htons(ifromport) ;
udphdr.dst_portno := htons(itoport) ;
udphdr.udp_length := htons(iudpsize) ;
udphdr.udp_checksum := 0 ;
iudpchecksumsize := 0;
ptr := @buf[0];
fillchar(buf, sizeof(buf), 0);
move(iphdr.ip_srcaddr, ptr^, sizeof(iphdr.ip_srcaddr));
incptr(sizeof(iphdr.ip_srcaddr));
iudpchecksumsize := iudpchecksumsize + sizeof(iphdr.ip_srcaddr);
move(iphdr.ip_destaddr, ptr^, sizeof(iphdr.ip_destaddr));
incptr(sizeof(iphdr.ip_destaddr));
iudpchecksumsize := iudpchecksumsize + sizeof(iphdr.ip_destaddr);
incptr(1);
inc(iudpchecksumsize);
move(iphdr.ip_protocol, ptr^, sizeof(iphdr.ip_protocol));
incptr(sizeof(iphdr.ip_protocol));
iudpchecksumsize := iudpchecksumsize + sizeof(iphdr.ip_protocol);
move(udphdr.udp_length, ptr^, sizeof(udphdr.udp_length));
incptr(sizeof(udphdr.udp_length));
iudpchecksumsize := iudpchecksumsize + sizeof(udphdr.udp_length);
move(udphdr, ptr^, sizeof(udphdr));
incptr(sizeof(udphdr));
iudpchecksumsize := iudpchecksumsize + sizeof(udphdr);
move(strmessage[1], ptr^, length(strmessage));
incptr(length(strmessage));
iudpchecksumsize := iudpchecksumsize + length(strmessage);
cksum := checksum(buf, iudpchecksumsize);
udphdr.udp_checksum := cksum;
//
// 现在 ip 和 udp 头ok了,我们可以把它发送出去。
//
fillchar(buf, sizeof(buf), 0);
ptr := @buf[0];
move(iphdr, ptr^, sizeof(iphdr)); incptr(sizeof(iphdr));
move(udphdr, ptr^, sizeof(udphdr)); incptr(sizeof(udphdr));
move(strmessage[1], ptr^, length(strmessage));