mirror of
https://github.com/yggdrasil-network/water.git
synced 2025-05-19 16:35:10 +03:00
initial commit
This commit is contained in:
parent
a9977e0a62
commit
4a028c3fe3
7 changed files with 377 additions and 0 deletions
71
if.go
Normal file
71
if.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package water
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface is a TUN/TAP interface.
|
||||||
|
type Interface struct {
|
||||||
|
isTAP bool
|
||||||
|
file *os.File
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new TAP interface whose name is ifName.
|
||||||
|
// If ifName is empty, a default name (tap0, tap1, ... ) will be assigned.
|
||||||
|
// ifName should not exceed 16 bytes.
|
||||||
|
func NewTAP(ifName string) (ifce *Interface, err error) {
|
||||||
|
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name, err := createInterface(file.Fd(), ifName, cIFF_TAP|cIFF_NO_PI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ifce = &Interface{isTAP: true, file: file, name: name}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new TUN interface whose name is ifName.
|
||||||
|
// If ifName is empty, a default name (tap0, tap1, ... ) will be assigned.
|
||||||
|
// ifName should not exceed 16 bytes.
|
||||||
|
func NewTUN(ifName string) (ifce *Interface, err error) {
|
||||||
|
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name, err := createInterface(file.Fd(), ifName, cIFF_TUN|cIFF_NO_PI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ifce = &Interface{isTAP: false, file: file, name: name}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if ifce is a TUN interface, otherwise returns false;
|
||||||
|
func (ifce *Interface) IsTUN() bool {
|
||||||
|
return !ifce.isTAP
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if ifce is a TAP interface, otherwise returns false;
|
||||||
|
func (ifce *Interface) IsTAP() bool {
|
||||||
|
return ifce.isTAP
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the interface name of ifce, e.g. tun0, tap1, etc..
|
||||||
|
func (ifce *Interface) Name() string {
|
||||||
|
return ifce.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement io.Writer interface.
|
||||||
|
func (ifce *Interface) Write(p []byte) (n int, err error) {
|
||||||
|
n, err = ifce.file.Write(p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement io.Reader interface.
|
||||||
|
func (ifce *Interface) Read(p []byte) (n int, err error) {
|
||||||
|
n, err = ifce.file.Read(p)
|
||||||
|
return
|
||||||
|
}
|
34
syscalls_linux.go
Normal file
34
syscalls_linux.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package water
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cIFF_TUN = 0x0001
|
||||||
|
cIFF_TAP = 0x0002
|
||||||
|
cIFF_NO_PI = 0x1000
|
||||||
|
)
|
||||||
|
|
||||||
|
type ifReq struct {
|
||||||
|
Name [0x10]byte
|
||||||
|
Flags uint16
|
||||||
|
pad [0x28 - 0x10 - 2]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
|
||||||
|
var req ifReq
|
||||||
|
req.Flags = flags
|
||||||
|
copy(req.Name[:], ifName)
|
||||||
|
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
|
||||||
|
if errno != 0 {
|
||||||
|
err = errno
|
||||||
|
return
|
||||||
|
}
|
||||||
|
createdIFName = strings.Trim(string(req.Name[:]), "\x00")
|
||||||
|
return
|
||||||
|
}
|
46
waterutil/ethertypes.go
Normal file
46
waterutil/ethertypes.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package waterutil
|
||||||
|
|
||||||
|
type Ethertype [2]byte
|
||||||
|
|
||||||
|
// Ethertype values. From: http://en.wikipedia.org/wiki/Ethertype
|
||||||
|
var (
|
||||||
|
IPv4 = Ethertype{0x08, 0x00}
|
||||||
|
ARP = Ethertype{0x08, 0x06}
|
||||||
|
WakeOnLAN = Ethertype{0x08, 0x42}
|
||||||
|
TRILL = Ethertype{0x22, 0xF3}
|
||||||
|
DECnetPhase4 = Ethertype{0x60, 0x03}
|
||||||
|
RARP = Ethertype{0x80, 0x35}
|
||||||
|
AppleTalk = Ethertype{0x80, 0x9B}
|
||||||
|
AARP = Ethertype{0x80, 0xF3}
|
||||||
|
IPX1 = Ethertype{0x81, 0x37}
|
||||||
|
IPX2 = Ethertype{0x81, 0x38}
|
||||||
|
QNXQnet = Ethertype{0x82, 0x04}
|
||||||
|
IPv6 = Ethertype{0x86, 0xDD}
|
||||||
|
EthernetFlowControl = Ethertype{0x88, 0x08}
|
||||||
|
IEEE802_3 = Ethertype{0x88, 0x09}
|
||||||
|
CobraNet = Ethertype{0x88, 0x19}
|
||||||
|
MPLSUnicast = Ethertype{0x88, 0x47}
|
||||||
|
MPLSMulticast = Ethertype{0x88, 0x48}
|
||||||
|
PPPoEDiscovery = Ethertype{0x88, 0x63}
|
||||||
|
PPPoESession = Ethertype{0x88, 0x64}
|
||||||
|
JumboFrames = Ethertype{0x88, 0x70}
|
||||||
|
HomePlug1_0MME = Ethertype{0x88, 0x7B}
|
||||||
|
IEEE802_1X = Ethertype{0x88, 0x8E}
|
||||||
|
PROFINET = Ethertype{0x88, 0x92}
|
||||||
|
HyperSCSI = Ethertype{0x88, 0x9A}
|
||||||
|
AoE = Ethertype{0x88, 0xA2}
|
||||||
|
EtherCAT = Ethertype{0x88, 0xA4}
|
||||||
|
EthernetPowerlink = Ethertype{0x88, 0xAB}
|
||||||
|
LLDP = Ethertype{0x88, 0xCC}
|
||||||
|
SERCOS3 = Ethertype{0x88, 0xCD}
|
||||||
|
HomePlugAVMME = Ethertype{0x88, 0xE1}
|
||||||
|
MRP = Ethertype{0x88, 0xE3}
|
||||||
|
IEEE802_1AE = Ethertype{0x88, 0xE5}
|
||||||
|
IEEE1588 = Ethertype{0x88, 0xF7}
|
||||||
|
IEEE802_1ag = Ethertype{0x89, 0x02}
|
||||||
|
FCoE = Ethertype{0x89, 0x06}
|
||||||
|
FCoEInit = Ethertype{0x89, 0x14}
|
||||||
|
RoCE = Ethertype{0x89, 0x15}
|
||||||
|
CTP = Ethertype{0x90, 0x00}
|
||||||
|
VeritasLLT = Ethertype{0xCA, 0xFE}
|
||||||
|
)
|
139
waterutil/ip_protocols.go
Normal file
139
waterutil/ip_protocols.go
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
package waterutil
|
||||||
|
|
||||||
|
type IPProtocol byte
|
||||||
|
|
||||||
|
// IP Protocols. From: http://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
|
||||||
|
const (
|
||||||
|
HOPOPT = 0x00
|
||||||
|
ICMP = 0x01
|
||||||
|
IGMP = 0x02
|
||||||
|
GGP = 0x03
|
||||||
|
IPv4Encapsulation = 0x04
|
||||||
|
ST = 0x05
|
||||||
|
TCP = 0x06
|
||||||
|
CBT = 0x07
|
||||||
|
EGP = 0x08
|
||||||
|
IGP = 0x09
|
||||||
|
BBN_RCC_MON = 0x0A
|
||||||
|
NVP_II = 0x0B
|
||||||
|
PUP = 0x0C
|
||||||
|
ARGUS = 0x0D
|
||||||
|
EMCON = 0x0E
|
||||||
|
XNET = 0x0F
|
||||||
|
CHAOS = 0x10
|
||||||
|
UDP = 0x11
|
||||||
|
MUX = 0x12
|
||||||
|
DCN_MEAS = 0x13
|
||||||
|
HMP = 0x14
|
||||||
|
PRM = 0x15
|
||||||
|
XNS_IDP = 0x16
|
||||||
|
TRUNK_1 = 0x17
|
||||||
|
TRUNK_2 = 0x18
|
||||||
|
LEAF_1 = 0x19
|
||||||
|
LEAF_2 = 0x1A
|
||||||
|
RDP = 0x1B
|
||||||
|
IRTP = 0x1C
|
||||||
|
ISO_TP4 = 0x1D
|
||||||
|
NETBLT = 0x1E
|
||||||
|
MFE_NSP = 0x1F
|
||||||
|
MERIT_INP = 0x20
|
||||||
|
DCCP = 0x21
|
||||||
|
ThirdPC = 0x22
|
||||||
|
IDPR = 0x23
|
||||||
|
XTP = 0x24
|
||||||
|
DDP = 0x25
|
||||||
|
IDPR_CMTP = 0x26
|
||||||
|
TPxx = 0x27
|
||||||
|
IL = 0x28
|
||||||
|
IPv6Encapsulation = 0x29
|
||||||
|
SDRP = 0x2A
|
||||||
|
IPv6_Route = 0x2B
|
||||||
|
IPv6_Frag = 0x2C
|
||||||
|
IDRP = 0x2D
|
||||||
|
RSVP = 0x2E
|
||||||
|
GRE = 0x2F
|
||||||
|
MHRP = 0x30
|
||||||
|
BNA = 0x31
|
||||||
|
ESP = 0x32
|
||||||
|
AH = 0x33
|
||||||
|
I_NLSP = 0x34
|
||||||
|
SWIPE = 0x35
|
||||||
|
NARP = 0x36
|
||||||
|
MOBILE = 0x37
|
||||||
|
TLSP = 0x38
|
||||||
|
SKIP = 0x39
|
||||||
|
IPv6_ICMP = 0x3A
|
||||||
|
IPv6_NoNxt = 0x3B
|
||||||
|
IPv6_Opts = 0x3C
|
||||||
|
CFTP = 0x3E
|
||||||
|
SAT_EXPAK = 0x40
|
||||||
|
KRYPTOLAN = 0x41
|
||||||
|
RVD = 0x42
|
||||||
|
IPPC = 0x43
|
||||||
|
SAT_MON = 0x45
|
||||||
|
VISA = 0x46
|
||||||
|
IPCV = 0x47
|
||||||
|
CPNX = 0x48
|
||||||
|
CPHB = 0x49
|
||||||
|
WSN = 0x4A
|
||||||
|
PVP = 0x4B
|
||||||
|
BR_SAT_MON = 0x4C
|
||||||
|
SUN_ND = 0x4D
|
||||||
|
WB_MON = 0x4E
|
||||||
|
WB_EXPAK = 0x4F
|
||||||
|
ISO_IP = 0x50
|
||||||
|
VMTP = 0x51
|
||||||
|
SECURE_VMTP = 0x52
|
||||||
|
VINES = 0x53
|
||||||
|
TTP = 0x54
|
||||||
|
IPTM = 0x54
|
||||||
|
NSFNET_IGP = 0x55
|
||||||
|
DGP = 0x56
|
||||||
|
TCF = 0x57
|
||||||
|
EIGRP = 0x58
|
||||||
|
OSPF = 0x59
|
||||||
|
Sprite_RPC = 0x5A
|
||||||
|
LARP = 0x5B
|
||||||
|
MTP = 0x5C
|
||||||
|
AX_25 = 0x5D
|
||||||
|
IPIP = 0x5E
|
||||||
|
MICP = 0x5F
|
||||||
|
SCC_SP = 0x60
|
||||||
|
ETHERIP = 0x61
|
||||||
|
ENCAP = 0x62
|
||||||
|
GMTP = 0x64
|
||||||
|
IFMP = 0x65
|
||||||
|
PNNI = 0x66
|
||||||
|
PIM = 0x67
|
||||||
|
ARIS = 0x68
|
||||||
|
SCPS = 0x69
|
||||||
|
QNX = 0x6A
|
||||||
|
A_N = 0x6B
|
||||||
|
IPComp = 0x6C
|
||||||
|
SNP = 0x6D
|
||||||
|
Compaq_Peer = 0x6E
|
||||||
|
IPX_in_IP = 0x6F
|
||||||
|
VRRP = 0x70
|
||||||
|
PGM = 0x71
|
||||||
|
L2TP = 0x73
|
||||||
|
DDX = 0x74
|
||||||
|
IATP = 0x75
|
||||||
|
STP = 0x76
|
||||||
|
SRP = 0x77
|
||||||
|
UTI = 0x78
|
||||||
|
SMP = 0x79
|
||||||
|
SM = 0x7A
|
||||||
|
PTP = 0x7B
|
||||||
|
FIRE = 0x7D
|
||||||
|
CRTP = 0x7E
|
||||||
|
CRUDP = 0x7F
|
||||||
|
SSCOPMCE = 0x80
|
||||||
|
IPLT = 0x81
|
||||||
|
SPS = 0x82
|
||||||
|
PIPE = 0x83
|
||||||
|
SCTP = 0x84
|
||||||
|
FC = 0x85
|
||||||
|
manet = 0x8A
|
||||||
|
HIP = 0x8B
|
||||||
|
Shim6 = 0x8C
|
||||||
|
)
|
40
waterutil/tap.go
Normal file
40
waterutil/tap.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package waterutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tagging int
|
||||||
|
|
||||||
|
// Indicating whether/how a MAC frame is tagged. The value is number of bytes taken by tagging.
|
||||||
|
const (
|
||||||
|
NotTagged Tagging = 0
|
||||||
|
Tagged Tagging = 4
|
||||||
|
DoubleTagged Tagging = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
func MACDestination(macFrame []byte) net.HardwareAddr {
|
||||||
|
return net.HardwareAddr(macFrame[:6])
|
||||||
|
}
|
||||||
|
|
||||||
|
func MACSource(macFrame []byte) net.HardwareAddr {
|
||||||
|
return net.HardwareAddr(macFrame[6:12])
|
||||||
|
}
|
||||||
|
|
||||||
|
func MACTagging(macFrame []byte) Tagging {
|
||||||
|
if macFrame[12] == 0x81 && macFrame[13] == 0x00 {
|
||||||
|
return Tagged
|
||||||
|
} else if macFrame[12] == 0x88 && macFrame[13] == 0xa8 {
|
||||||
|
return DoubleTagged
|
||||||
|
}
|
||||||
|
return NotTagged
|
||||||
|
}
|
||||||
|
|
||||||
|
func MACEthertype(macFrame []byte) Ethertype {
|
||||||
|
ethertypePos := 12 + MACTagging(macFrame)
|
||||||
|
return Ethertype{macFrame[ethertypePos], macFrame[ethertypePos+1]}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MACPayload(macFrame []byte) []byte {
|
||||||
|
return macFrame[12+MACTagging(macFrame)+2:]
|
||||||
|
}
|
9
waterutil/tun.go
Normal file
9
waterutil/tun.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package waterutil
|
||||||
|
|
||||||
|
func IsIPv4(packet []byte) bool {
|
||||||
|
return 4 == (packet[0] >> 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsIPv6(packet []byte) bool {
|
||||||
|
return 6 == (packet[0] >> 4)
|
||||||
|
}
|
38
waterutil/tun_ipv4.go
Normal file
38
waterutil/tun_ipv4.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package waterutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IPv4DSCP(packet []byte) byte {
|
||||||
|
return packet[1] >> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4ECN(packet []byte) byte {
|
||||||
|
return packet[1] & 0x03
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4Identification(packet []byte) [2]byte {
|
||||||
|
return [2]byte{packet[4], packet[5]}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4TTL(packet []byte) byte {
|
||||||
|
return packet[8]
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4Protocol(packet []byte) IPProtocol {
|
||||||
|
return IPProtocol(packet[9])
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4Source(packet []byte) net.IP {
|
||||||
|
return net.IPv4(packet[12], packet[13], packet[14], packet[15])
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4Destination(packet []byte) net.IP {
|
||||||
|
return net.IPv4(packet[16], packet[17], packet[18], packet[19])
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPv4Payload(packet []byte) []byte {
|
||||||
|
ihl := packet[0] & 0x0F
|
||||||
|
return packet[ihl*4:]
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue