package clashtcpip import ( "encoding/binary" "net" ) const ( TCPFin uint16 = 1 << 0 TCPSyn uint16 = 1 << 1 TCPRst uint16 = 1 << 2 TCPPuh uint16 = 1 << 3 TCPAck uint16 = 1 << 4 TCPUrg uint16 = 1 << 5 TCPEce uint16 = 1 << 6 TCPEwr uint16 = 1 << 7 TCPNs uint16 = 1 << 8 ) const TCPHeaderSize = 20 type TCPPacket []byte func (p TCPPacket) SourcePort() uint16 { return binary.BigEndian.Uint16(p) } func (p TCPPacket) SetSourcePort(port uint16) { binary.BigEndian.PutUint16(p, port) } func (p TCPPacket) DestinationPort() uint16 { return binary.BigEndian.Uint16(p[2:]) } func (p TCPPacket) SetDestinationPort(port uint16) { binary.BigEndian.PutUint16(p[2:], port) } func (p TCPPacket) Flags() uint16 { return uint16(p[13] | (p[12] & 0x1)) } func (p TCPPacket) Checksum() uint16 { return binary.BigEndian.Uint16(p[16:]) } func (p TCPPacket) SetChecksum(sum [2]byte) { p[16] = sum[0] p[17] = sum[1] } func (p TCPPacket) OffloadChecksum() { p.SetChecksum(zeroChecksum) } func (p TCPPacket) ResetChecksum(psum uint32) { p.SetChecksum(zeroChecksum) p.SetChecksum(Checksum(psum, p)) } func (p TCPPacket) Valid() bool { return len(p) >= TCPHeaderSize } func (p TCPPacket) Verify(sourceAddress net.IP, targetAddress net.IP) error { var checksum [2]byte checksum[0] = p[16] checksum[1] = p[17] // reset checksum p[16] = 0 p[17] = 0 // restore checksum defer func() { p[16] = checksum[0] p[17] = checksum[1] }() // check checksum s := uint32(0) s += Sum(sourceAddress) s += Sum(targetAddress) s += uint32(TCP) s += uint32(len(p)) check := Checksum(s, p) if checksum[0] != check[0] || checksum[1] != check[1] { return ErrInvalidChecksum } return nil }