不废话上实现:
bool TapTap2Socket::RST(My::Tun::ITap* tap, struct My::Net::Native::ip_hdr* iphdr, struct My::Net::Native::tcp_hdr* pkg, int len) { assert(tap && iphdr && pkg);
uint32_t dstAddr = iphdr->dest;
uint16_t dstPort = pkg->dest;
uint32_t srcAddr = iphdr->src;
uint16_t srcPort = pkg->src;
uint32_t seqNo = pkg->seqno;
uint32_t ackNo = pkg->ackno;
uint32_t hdrlen_bytes = tcp_hdr::TCPH_HDRLEN_BYTES(pkg);
uint32_t tcplen = len - hdrlen_bytes;
if (tcp_hdr::TCPH_FLAGS(pkg) & (TcpFlags::TCP_FIN | TcpFlags::TCP_SYN)) {
tcplen++;
}
len = tcp_hdr::TCP_HLEN; // 1 align sizeof(tcp_hdr)
iphdr->src = dstAddr;
pkg->src = dstPort;
iphdr->dest = srcAddr;
pkg->dest = srcPort;
pkg->ackno = seqNo + tcplen;
pkg->seqno = ackNo;
pkg->hdrlen_rsvd_flags = 0;
pkg->urgp = 0;
tcp_hdr::TCPH_HDRLEN_BYTES_SET(pkg, len);
tcp_hdr::TCPH_FLAGS_SET(pkg, TcpFlags::TCP_RST | TcpFlags::TCP_ACK);
NetworkStatistics::TcpStatistics& tcp_stat = this->_statistics.Tcp;
tcp_stat.IncomingUnicastPacket++;
tcp_stat.IncomingTrafficSize += len;
return this->OPT(false, tap, iphdr, pkg, len);
}
bool TapTap2Socket::OPT(bool lan2wan, My::Tun::ITap* tap, struct My::Net::Native::ip_hdr* iphdr, struct My::Net::Native::tcp_hdr* pkg, int len) { assert(tap && iphdr && pkg);
pkg->chksum = 0;
pkg->chksum = My::Net::Native::inet_chksum_pseudo((unsigned char*)pkg,
(unsigned int)ip_hdr::IP_PROTO_TCP,
(unsigned int)len,
iphdr->src,
iphdr->dest);
if (pkg->chksum == 0) {
pkg->chksum = 0xffff;
}
int iphdr_len = (char*)pkg - (char*)iphdr;
iphdr->chksum = 0;
iphdr->chksum = My::Net::Native::inet_chksum(iphdr, iphdr_len);
if (iphdr->chksum == 0) {
iphdr->chksum = 0xffff;
}
int ippkg_len = ((char*)pkg + len) - (char*)iphdr;
NetworkStatistics::Statistics& ip_stat = this->_statistics.IPv4;
if (lan2wan) {
ip_stat.OutgoingUnicastPacket++;
ip_stat.OutgoingTrafficSize += ippkg_len;
}
else {
ip_stat.IncomingUnicastPacket++;
ip_stat.IncomingTrafficSize += ippkg_len;
}
return tap->Output(iphdr, ippkg_len);
}
tcp_hdr.h
#pragma once
#include <My/Net/Native/ip.h>
#include <My/Net/Native/checksum.h>
namespace My {
namespace Net {
namespace Native {
#pragma pack(push, 1)
/*
* typedef struct _tcp_hdr
* {
* unsigned short src_port; //源端口号
* unsigned short dst_port; //目的端口号
* unsigned int seq_no; //序列号
* unsigned int ack_no; //确认号
* #if LITTLE_ENDIAN
* unsigned char reserved_1:4; //保留6位中的4位首部长度
* unsigned char thl:4; //tcp头部长度
* unsigned char flag:6; //6位标志
* unsigned char reseverd_2:2; //保留6位中的2位
* #else
* unsigned char thl:4; //tcp头部长度
* unsigned char reserved_1:4; //保留6位中的4位首部长度
* unsigned char reseverd_2:2; //保留6位中的2位
* unsigned char flag:6; //6位标志
* #endif
* unsigned short wnd_size; //16位窗口大小
* unsigned short chk_sum; //16位TCP检验和
* unsigned short urgt_p; //16为紧急指针
* }tcp_hdr;
*/
struct tcp_hdr {
public:
enum TcpFlags {
TCP_FIN = 0x01,
TCP_SYN = 0x02,
TCP_RST = 0x04,
TCP_PSH = 0x08,
TCP_ACK = 0x10,
TCP_UGR = 0x20,
TCP_ECE = 0x40,
TCP_CWR = 0x80,
TCP_FLAGS = 0x3f
};
public:
unsigned short src;
unsigned short dest;
unsigned int seqno;
unsigned int ackno;
unsigned short hdrlen_rsvd_flags;
unsigned short wnd;
unsigned short chksum;
unsigned short urgp; // 应用层不可能出现“URGP/UGR or OPT”的协议;这类紧急协议数据报文直接RST链接即可。
public:
inline static unsigned short TCPH_HDRLEN(struct tcp_hdr* phdr) {
return ((unsigned short)(__ntohs((phdr)->hdrlen_rsvd_flags) >> 12));
}
inline static unsigned char TCPH_HDRLEN_BYTES(struct tcp_hdr* phdr) {
return ((unsigned char)(TCPH_HDRLEN(phdr) << 2));
}
inline static unsigned char TCPH_FLAGS(struct tcp_hdr* phdr) {
return ((unsigned char)((__ntohs((phdr)->hdrlen_rsvd_flags) & (unsigned char)TCP_FLAGS)));
}
inline static unsigned short TCPH_HDRLEN_SET(struct tcp_hdr* phdr, int len) {
int u = ((len) << 12) | TCPH_FLAGS(phdr);
return (phdr)->hdrlen_rsvd_flags = __htons((unsigned short)u);
}
inline static unsigned short TCPH_HDRLEN_BYTES_SET(struct tcp_hdr* phdr, int len) {
return TCPH_HDRLEN_SET(phdr, len >> 2);
}
inline static unsigned short PP_HTONS(int x) {
return ((unsigned short)((((x) & (unsigned short)0x00ffU) << 8) | (((x) & (unsigned short)0xff00U) >> 8)));
}
inline static unsigned short TCPH_FLAGS_SET(struct tcp_hdr* phdr, int flags) {
return (phdr)->hdrlen_rsvd_flags = (unsigned short)(((phdr)->hdrlen_rsvd_flags &
PP_HTONS(~(unsigned short)TCP_FLAGS)) | __htons((unsigned short)flags));
}
public:
static struct tcp_hdr* Parse(struct ip_hdr* iphdr, const void* packet, int size);
public:
static const int TCP_HLEN;
};
#pragma pack(pop)
}
}
}