112 lines
2.7 KiB
Go
112 lines
2.7 KiB
Go
package Atom_Device
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"git.sydch.com/Go-Module/atom-device/utils"
|
|
"golang.org/x/net/ipv4"
|
|
"golang.org/x/net/ipv6"
|
|
"golang.zx2c4.com/wireguard/device"
|
|
"io"
|
|
"net"
|
|
)
|
|
|
|
const (
|
|
InterfaceMTU = 3500
|
|
maxContentSize = InterfaceMTU * 2
|
|
outboundChCap = 50
|
|
tunPacketOffset = 14
|
|
ipv4offsetChecksum = 10
|
|
)
|
|
|
|
type Packet struct {
|
|
Buffer [maxContentSize]byte
|
|
Packet []byte
|
|
Src net.IP
|
|
Dst net.IP
|
|
IsIPv6 bool
|
|
}
|
|
|
|
func (data *Packet) clear() {
|
|
data.Packet = nil
|
|
data.Src = nil
|
|
data.Dst = nil
|
|
data.IsIPv6 = false
|
|
}
|
|
|
|
func (data *Packet) ReadFrom(stream io.Reader) (int64, error) {
|
|
var totalRead = tunPacketOffset
|
|
for {
|
|
n, err := stream.Read(data.Buffer[totalRead:])
|
|
totalRead += n
|
|
if err == io.EOF {
|
|
data.Packet = data.Buffer[tunPacketOffset:totalRead]
|
|
return int64(totalRead - tunPacketOffset), nil
|
|
} else if err != nil {
|
|
return int64(totalRead - tunPacketOffset), err
|
|
}
|
|
}
|
|
}
|
|
|
|
func (data *Packet) Parse() bool {
|
|
packet := data.Packet
|
|
switch version := packet[0] >> 4; version {
|
|
case ipv4.Version:
|
|
if len(packet) < ipv4.HeaderLen {
|
|
return false
|
|
}
|
|
|
|
data.Src = packet[device.IPv4offsetSrc : device.IPv4offsetSrc+net.IPv4len]
|
|
data.Dst = packet[device.IPv4offsetDst : device.IPv4offsetDst+net.IPv4len]
|
|
data.IsIPv6 = false
|
|
case ipv6.Version:
|
|
if len(packet) < ipv6.HeaderLen {
|
|
return false
|
|
}
|
|
|
|
data.Src = packet[device.IPv6offsetSrc : device.IPv6offsetSrc+net.IPv6len]
|
|
data.Dst = packet[device.IPv6offsetDst : device.IPv6offsetDst+net.IPv6len]
|
|
data.IsIPv6 = true
|
|
default:
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (data *Packet) ParseBuffer() {
|
|
var tmp [InterfaceMTU * 2]byte
|
|
for i := 0; i < len(data.Packet) && i+14 < len(tmp); i++ {
|
|
tmp[i+14] = data.Packet[i]
|
|
}
|
|
data.Buffer = tmp
|
|
}
|
|
|
|
func (data *Packet) RecalculateChecksum() {
|
|
const (
|
|
IPProtocolTCP = 6
|
|
IPProtocolUDP = 17
|
|
)
|
|
|
|
if data.IsIPv6 {
|
|
// TODO
|
|
} else {
|
|
ipHeaderLen := int(data.Packet[0]&0x0f) << 2
|
|
copy(data.Packet[ipv4offsetChecksum:], []byte{0, 0})
|
|
ipChecksum := utils.ChecksumIPv4Header(data.Packet[:ipHeaderLen])
|
|
binary.BigEndian.PutUint16(data.Packet[ipv4offsetChecksum:], ipChecksum)
|
|
|
|
switch protocol := data.Packet[9]; protocol {
|
|
case IPProtocolTCP:
|
|
tcpOffsetChecksum := ipHeaderLen + 16
|
|
copy(data.Packet[tcpOffsetChecksum:], []byte{0, 0})
|
|
checksum := utils.ChecksumIPv4TCPUDP(data.Packet[ipHeaderLen:], uint32(protocol), data.Src, data.Dst)
|
|
binary.BigEndian.PutUint16(data.Packet[tcpOffsetChecksum:], checksum)
|
|
case IPProtocolUDP:
|
|
udpOffsetChecksum := ipHeaderLen + 6
|
|
copy(data.Packet[udpOffsetChecksum:], []byte{0, 0})
|
|
checksum := utils.ChecksumIPv4TCPUDP(data.Packet[ipHeaderLen:], uint32(protocol), data.Src, data.Dst)
|
|
binary.BigEndian.PutUint16(data.Packet[udpOffsetChecksum:], checksum)
|
|
}
|
|
}
|
|
}
|