mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-02 19:37:40 +03:00
94 lines
1.7 KiB
Go
94 lines
1.7 KiB
Go
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
|
|
}
|