initial commit

This commit is contained in:
Song Gao 2013-03-25 14:49:39 -05:00
parent a9977e0a62
commit 4a028c3fe3
7 changed files with 377 additions and 0 deletions

71
if.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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:]
}