标签:
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;
标签:
原文地址:http://www.cnblogs.com/moonwind/p/4523765.html