码迷,mamicode.com
首页 > 其他好文 > 详细

raw socket 发送数据包

时间:2015-05-23 11:18:23      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

TRawSocket = class(TObject)
private
    buf: array[0..BUFLEN - 1] of char;
    FdwNotifyWnd: Cardinal;
    hsocket: Cardinal;
    str: string;
public
    constructor Create;
    destructor Destroy; override;
    function createSocket: Integer;
    procedure destroySocket;
    function IsOk: Boolean;
    //function sendTcpData(srcIP, dstIP: string; srcPort, dstPort: word; data:
      //pchar; dataLen: integer): Integer;
    function sendUdpData(srcIP, dstIP: string; srcPort, dstPort: word; data:
      pchar; dataLen: integer): Integer;
    function sendUdpDataFrag(srcIP, dstIP: string; srcPort, dstPort: word;
      data: pchar; dataLen: integer): Integer;
published
    property dwNotifyWnd: Cardinal read FdwNotifyWnd write FdwNotifyWnd;
end;
constructor TRawSocket.Create;
begin
inherited Create;
hsocket := INVALID_SOCKET;
end;destructor TRawSocket.Destroy;
begin
if IsOk then destroySocket;
inherited Destroy;
end;function TRawSocket.createSocket: Integer;
var
flag: Integer;
ret: Integer;
begin
// 创建raw socket,自己构造ip包头
result := -1; // Create socket
// IPPROTO_RAW 只能用来发送IP包,而不能接收任何数据.
//*发送的数据需要自己填充IP包头,TCP/UDP头并且自己计算校验和
hsocket := Socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (hsocket = INVALID_SOCKET) then begin
    str := Socket() failed:  + IntToStr(WSAGetLastError);
    SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
    exit;
end;flag := 1; // Option: Header Include
ret := SetSockOpt(hsocket, IPPROTO_IP, IP_HDRINCL, @flag, SizeOf(flag));
if ret = SOCKET_ERROR then begin
    str := setsockopt IP_HDRINCL failed:  + IntToStr(WSAGetLastError);
    SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
    exit;
end;flag := 5000; // Option: Send OverTime;
ret := SetSockOpt(hsocket, SOL_SOCKET, SO_SNDTIMEO, @flag, SizeOf(flag));
if ret = SOCKET_ERROR then begin
    str := setsockopt SO_SNDTIMEO failed:  + IntToStr(WSAGetLastError);
    SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
    exit;
end;
result := 1;
end;procedure TRawSocket.destroySocket;
begin
shutdown(hsocket, SD_BOTH);
CloseSocket(hsocket);
hsocket := INVALID_SOCKET;
end;function TRawSocket.IsOk: Boolean;
begin
result := not (hsocket = INVALID_SOCKET);
end;
function TRawSocket.sendUdpData(srcIP, dstIP: string; srcPort, dstPort: word;
data: pchar; dataLen: integer): Integer;
var
ipHdr: _ipHead;
udpHdr: _udpHead;
pseudoHdr: _pseudoHead;
ipSize, udpSize: Word;
iphdrlen, pseudohdrlen, udphdrlen: Word;
lpipHdr: pipHead;
lpudpHdr: pudpHead;
p, p0: PChar;
Local: TSockAddrIn;
Remote: TSockAddrIn;
begin
// 功能:打包发送UDP包
Local.sin_family := AF_INET;
Local.sin_addr.S_addr := inet_Addr(PChar(srcIP));
Local.sin_port := htons(srcPort);Remote.sin_family := AF_INET;
Remote.sin_addr.S_addr := inet_Addr(PChar(dstIP));
Remote.sin_port := htons(dstPort);iphdrlen := sizeof(_ipHead);
udphdrlen := sizeof(_udpHead);
pseudohdrlen := sizeof(pseudoHdr);
ipSize := iphdrlen + udphdrlen + datalen;
udpSize := ipSize - iphdrlen;
inc(idt); // test
// 初始化 IP 头
ipHdr.ver_IHL := (4 shl 4) or (sizeof(ipHdr) div 4);
ipHdr.serverType := 0; // IP type of service
ipHdr.totalLen := htons(ipSize); // Total packet len
ipHdr.ident := htons(idt); // Unique identifier: set to 0
ipHdr.flags_off := 0; // Fragment offset field
ipHdr.ttl := 128; // Time to live
ipHdr.protocol := 17; // Protocol(UDP)
ipHdr.ipchksum := 0; // IP checksum
ipHdr.srcAddr := Local.sin_addr.S_addr; // Source address
ipHdr.dstAddr := Remote.sin_addr.S_addr; // Destination address// 初始化 UDP 头
udpHdr.srcPort := Local.sin_port;
udpHdr.dstPort := Remote.sin_port;
udpHdr.Length := htons(udpSize);
udpHdr.checksum := 0;// 初始化 伪ip 头
pseudoHdr.srcAddr := ipHdr.srcAddr;
pseudoHdr.dstAddr := ipHdr.dstAddr;
pseudoHdr.unused := 0;
pseudoHdr.protocol := ipHdr.protocol;
pseudoHdr.Length := udpHdr.Length;p := buf + iphdrlen - pseudohdrlen;
p0 := P; // 备份伪ip头指针p0,checksum 运算用
move(pseudoHdr, p^, pseudohdrlen);
inc(p, pseudohdrlen);
lpudpHdr := pudpHead(p);
move(udpHdr, p^, udphdrlen);
inc(p, udphdrlen);
move(data^, p^, datalen);
inc(p, datalen);
lpudpHdr^.checksum := checksum(p0, p - p0);
// copy ip头;覆盖伪ip头
p := buf;
lpipHdr := pipHead(p);
move(ipHdr, p^, iphdrlen);
lpipHdr^.ipchksum := checksum(buf, iphdrlen); // ip头// Send the raw socket packet
result := sendto(hsocket, buf, ipSize, 0, @Remote, SizeOf(Remote));
if result = SOCKET_ERROR then
begin
    str := sendto() failed:  + IntToStr(WSAGetLastError);
    SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
    exit;
end;
end;
function TRawSocket.sendUdpDataFrag(srcIP, dstIP: string; srcPort, dstPort:
word; data: pchar; dataLen: integer): Integer;
const
fraglen = 1472; // 分片的数据长度 1500(以太网MTU)-20(IP头长)-8(UDP头长)
var
ipHdr: _ipHead;
udpHdr: _udpHead;
pseudoHdr: _pseudoHead;
ipSize, udpSize: Word;
iphdrlen, pseudohdrlen, udphdrlen: Word;
lpipHdr: pipHead;
lpudpHdr: pudpHead;
p, p0: PChar;
Local: TSockAddrIn;
Remote: TSockAddrIn;
i, j, k: integer;
begin
inc(idt); // test
// 功能:分片发送ip 分片包UDP协议
Local.sin_family := AF_INET;
Local.sin_addr.S_addr := inet_Addr(PChar(srcIP));
Local.sin_port := htons(srcPort);Remote.sin_family := AF_INET;
Remote.sin_addr.S_addr := inet_Addr(PChar(dstIP));
Remote.sin_port := htons(dstPort);iphdrlen := sizeof(_ipHead);
udphdrlen := sizeof(_udpHead);
pseudohdrlen := sizeof(pseudoHdr);j := datalen div fraglen;
if (datalen mod fraglen) = 0 then j := j - 1;
for i := 0 to j do
begin
    if datalen > (i + 1) * fraglen then k := fraglen + udpHdrLen
    else k := datalen - i * fraglen;
    ipSize := iphdrlen + udphdrlen + k;
    udpSize := ipSize - iphdrlen;
// 初始化 IP 头
    ipHdr.ver_IHL := (4 shl 4) or (sizeof(ipHdr) div 4);
    ipHdr.serverType := 0; // IP type of service
    ipHdr.totalLen := htons(ipSize); // Total packet len
    ipHdr.ident := htons(idt); // Unique identifier: set to 0
    // Fragment offset field
    if i = 0 then ipHdr.flags_off := htons($2000) // 第一片
    else if i < j then ipHdr.flags_off := htons($2000 or (fraglen + udpHdrLen) * i) // 中间片
    else ipHdr.flags_off := htons((fraglen + udpHdrLen) * i); // 最后一片
    ipHdr.ttl := 128; // Time to live
    ipHdr.protocol := 17; // Protocol(UDP)
    ipHdr.ipchksum := 0; // IP checksum
    ipHdr.srcAddr := Local.sin_addr.S_addr; // Source address
    ipHdr.dstAddr := Remote.sin_addr.S_addr; // Destination address// 初始化 UDP 头
    udpHdr.srcPort := Local.sin_port;
    udpHdr.dstPort := Remote.sin_port;
    udpHdr.Length := htons(udpSize);
    udpHdr.checksum := 0;// 初始化 伪ip 头
    pseudoHdr.srcAddr := ipHdr.srcAddr;
    pseudoHdr.dstAddr := ipHdr.dstAddr;
    pseudoHdr.unused := 0;
    pseudoHdr.protocol := ipHdr.protocol;
    pseudoHdr.Length := udpHdr.Length;    p := buf + iphdrlen - pseudohdrlen;
    p0 := P; // 备份伪ip头指针p0,checksum 运算用
    move(pseudoHdr, p^, pseudohdrlen);
    inc(p, pseudohdrlen);
    lpudpHdr := pudpHead(p);
    move(udpHdr, p^, udphdrlen);
    inc(p, udphdrlen);
    move(data^, p^, k);
    inc(p, k);
    lpudpHdr^.checksum := checksum(p0, p - p0);
// copy ip头;覆盖伪ip头
    p := buf;
    lpipHdr := pipHead(p);
    move(ipHdr, p^, iphdrlen);
    lpipHdr^.ipchksum := checksum(buf, iphdrlen); // ip头// Send the raw socket packet
    result := sendto(hsocket, buf, ipSize, 0, @Remote, SizeOf(Remote));
    if result = SOCKET_ERROR then
    begin
      str := sendto() failed:  + IntToStr(WSAGetLastError);
      SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
      exit;
    end;end;
result := datalen;
end;

 

raw socket 发送数据包

标签:

原文地址:http://www.cnblogs.com/moonwind/p/4523765.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!