initial: ZeroTier-like P2P mesh VPN server with multi-tenant Web UI
This commit is contained in:
92
internal/vl2/frame.go
Normal file
92
internal/vl2/frame.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package vl2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
MinFrameSize = 14
|
||||
MaxFrameSize = 65535
|
||||
EtherTypeIPv4 = 0x0800
|
||||
EtherTypeARP = 0x0806
|
||||
EtherTypeIPv6 = 0x86DD
|
||||
)
|
||||
|
||||
type EthernetFrame struct {
|
||||
DstMAC net.HardwareAddr
|
||||
SrcMAC net.HardwareAddr
|
||||
EtherType uint16
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
func ParseEthernetFrame(data []byte) (*EthernetFrame, error) {
|
||||
if len(data) < MinFrameSize {
|
||||
return nil, fmt.Errorf("frame too short: %d < %d", len(data), MinFrameSize)
|
||||
}
|
||||
return &EthernetFrame{
|
||||
DstMAC: net.HardwareAddr(data[0:6]),
|
||||
SrcMAC: net.HardwareAddr(data[6:12]),
|
||||
EtherType: binary.BigEndian.Uint16(data[12:14]),
|
||||
Payload: data[14:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *EthernetFrame) Encode() []byte {
|
||||
buf := make([]byte, MinFrameSize+len(f.Payload))
|
||||
copy(buf[0:6], f.DstMAC)
|
||||
copy(buf[6:12], f.SrcMAC)
|
||||
binary.BigEndian.PutUint16(buf[12:14], f.EtherType)
|
||||
copy(buf[14:], f.Payload)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (f *EthernetFrame) IsBroadcast() bool {
|
||||
for _, b := range f.DstMAC {
|
||||
if b != 0xff {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *EthernetFrame) IsMulticast() bool {
|
||||
return len(f.DstMAC) > 0 && f.DstMAC[0]&0x01 == 0x01 && !f.IsBroadcast()
|
||||
}
|
||||
|
||||
func (f *EthernetFrame) IsARP() bool {
|
||||
return f.EtherType == EtherTypeARP
|
||||
}
|
||||
|
||||
func (f *EthernetFrame) IsIPv4() bool {
|
||||
return f.EtherType == EtherTypeIPv4
|
||||
}
|
||||
|
||||
func (f *EthernetFrame) IsIPv6() bool {
|
||||
return f.EtherType == EtherTypeIPv6
|
||||
}
|
||||
|
||||
type MACKey [6]byte
|
||||
|
||||
func MACToKey(mac net.HardwareAddr) MACKey {
|
||||
var key MACKey
|
||||
copy(key[:], mac)
|
||||
return key
|
||||
}
|
||||
|
||||
var frameBufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
buf := make([]byte, MaxFrameSize)
|
||||
return &buf
|
||||
},
|
||||
}
|
||||
|
||||
func GetFrameBuf() *[]byte {
|
||||
return frameBufPool.Get().(*[]byte)
|
||||
}
|
||||
|
||||
func PutFrameBuf(buf *[]byte) {
|
||||
frameBufPool.Put(buf)
|
||||
}
|
||||
Reference in New Issue
Block a user