mirror of
https://github.com/KusakabeShi/EtherGuard-VPN.git
synced 2024-12-24 14:58:47 +01:00
TAP and routeing
This commit is contained in:
parent
1fa36f77ac
commit
87a62f873b
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,2 @@
|
||||
wireguard-go
|
||||
go.sum
|
||||
etherguard-go
|
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${workspaceFolder}",
|
||||
"args":["-config","example_config/n1.yaml","-mode","edge"],
|
||||
}
|
||||
]
|
||||
}
|
10
Makefile
10
Makefile
@ -14,18 +14,18 @@ generate-version-and-build:
|
||||
[ "$$(cat version.go 2>/dev/null)" != "$$ver" ] && \
|
||||
echo "$$ver" > version.go && \
|
||||
git update-index --assume-unchanged version.go || true
|
||||
@$(MAKE) wireguard-go
|
||||
@$(MAKE) etherguard-go
|
||||
|
||||
wireguard-go: $(wildcard *.go) $(wildcard */*.go)
|
||||
etherguard-go: $(wildcard *.go) $(wildcard */*.go)
|
||||
go build -v -o "$@"
|
||||
|
||||
install: wireguard-go
|
||||
@install -v -d "$(DESTDIR)$(BINDIR)" && install -v -m 0755 "$<" "$(DESTDIR)$(BINDIR)/wireguard-go"
|
||||
install: etherguard-go
|
||||
@install -v -d "$(DESTDIR)$(BINDIR)" && install -v -m 0755 "$<" "$(DESTDIR)$(BINDIR)/etherguard-go"
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
clean:
|
||||
rm -f wireguard-go
|
||||
rm -f etherguard-go
|
||||
|
||||
.PHONY: all clean test install generate-version-and-build
|
||||
|
@ -60,10 +60,15 @@ type LinuxSocketBind struct {
|
||||
mu sync.RWMutex
|
||||
sock4 int
|
||||
sock6 int
|
||||
use4 bool
|
||||
use6 bool
|
||||
}
|
||||
|
||||
func NewLinuxSocketBind() Bind { return &LinuxSocketBind{sock4: -1, sock6: -1} }
|
||||
func NewLinuxSocketBind() Bind { return &LinuxSocketBind{sock4: -1, sock6: -1, use4: true, use6: true} }
|
||||
func NewDefaultBind() Bind { return NewLinuxSocketBind() }
|
||||
func NewCustomBind(use4 bool, use6 bool) Bind {
|
||||
return &LinuxSocketBind{sock4: -1, sock6: -1, use4: use4, use6: use6}
|
||||
}
|
||||
|
||||
var _ Endpoint = (*LinuxSocketEndpoint)(nil)
|
||||
var _ Bind = (*LinuxSocketBind)(nil)
|
||||
@ -120,32 +125,35 @@ func (bind *LinuxSocketBind) Open(port uint16) ([]ReceiveFunc, uint16, error) {
|
||||
again:
|
||||
port = originalPort
|
||||
var sock4, sock6 int
|
||||
// Attempt ipv6 bind, update port if successful.
|
||||
sock6, newPort, err = create6(port)
|
||||
if err != nil {
|
||||
if !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
return nil, 0, err
|
||||
if bind.use6 {
|
||||
// Attempt ipv6 bind, update port if successful.
|
||||
sock6, newPort, err = create6(port)
|
||||
if err != nil {
|
||||
if !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
port = newPort
|
||||
}
|
||||
} else {
|
||||
port = newPort
|
||||
}
|
||||
|
||||
// Attempt ipv4 bind, update port if successful.
|
||||
sock4, newPort, err = create4(port)
|
||||
if err != nil {
|
||||
if originalPort == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 {
|
||||
unix.Close(sock6)
|
||||
tries++
|
||||
goto again
|
||||
if bind.use4 {
|
||||
// Attempt ipv4 bind, update port if successful.
|
||||
sock4, newPort, err = create4(port)
|
||||
if err != nil {
|
||||
if originalPort == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 {
|
||||
unix.Close(sock6)
|
||||
tries++
|
||||
goto again
|
||||
}
|
||||
if !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
unix.Close(sock6)
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
port = newPort
|
||||
}
|
||||
if !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
unix.Close(sock6)
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
port = newPort
|
||||
}
|
||||
|
||||
var fns []ReceiveFunc
|
||||
if sock4 != -1 {
|
||||
bind.sock4 = sock4
|
||||
|
@ -12,9 +12,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ratelimiter"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/rwcancel"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tun"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
@ -60,12 +61,17 @@ type Device struct {
|
||||
peers struct {
|
||||
sync.RWMutex // protects keyMap
|
||||
keyMap map[NoisePublicKey]*Peer
|
||||
IDMap map[path.Vertex]*Peer
|
||||
}
|
||||
|
||||
allowedips AllowedIPs
|
||||
indexTable IndexTable
|
||||
cookieChecker CookieChecker
|
||||
|
||||
ID path.Vertex
|
||||
NhTable path.NextHopTable
|
||||
l2fib map[tap.MacAddress]path.Vertex
|
||||
LogTransit bool
|
||||
|
||||
pool struct {
|
||||
messageBuffers *WaitPool
|
||||
inboundElements *WaitPool
|
||||
@ -78,8 +84,8 @@ type Device struct {
|
||||
handshake *handshakeQueue
|
||||
}
|
||||
|
||||
tun struct {
|
||||
device tun.Device
|
||||
tap struct {
|
||||
device tap.Device
|
||||
mtu int32
|
||||
}
|
||||
|
||||
@ -126,7 +132,6 @@ func (device *Device) isUp() bool {
|
||||
// Must hold device.peers.Lock()
|
||||
func removePeerLocked(device *Device, peer *Peer, key NoisePublicKey) {
|
||||
// stop routing and processing of packets
|
||||
device.allowedips.RemoveByPeer(peer)
|
||||
peer.Stop()
|
||||
|
||||
// remove from peer map
|
||||
@ -274,20 +279,23 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewDevice(tunDevice tun.Device, bind conn.Bind, logger *Logger) *Device {
|
||||
func NewDevice(tapDevice tap.Device, id path.Vertex, bind conn.Bind, logger *Logger) *Device {
|
||||
device := new(Device)
|
||||
device.state.state = uint32(deviceStateDown)
|
||||
device.closed = make(chan struct{})
|
||||
device.log = logger
|
||||
device.net.bind = bind
|
||||
device.tun.device = tunDevice
|
||||
mtu, err := device.tun.device.MTU()
|
||||
device.tap.device = tapDevice
|
||||
mtu, err := device.tap.device.MTU()
|
||||
if err != nil {
|
||||
device.log.Errorf("Trouble determining MTU, assuming default: %v", err)
|
||||
mtu = DefaultMTU
|
||||
}
|
||||
device.tun.mtu = int32(mtu)
|
||||
device.tap.mtu = int32(mtu)
|
||||
device.peers.keyMap = make(map[NoisePublicKey]*Peer)
|
||||
device.peers.IDMap = make(map[path.Vertex]*Peer)
|
||||
device.ID = id
|
||||
device.l2fib = make(map[tap.MacAddress]path.Vertex)
|
||||
device.rate.limiter.Init()
|
||||
device.indexTable.Init()
|
||||
device.PopulatePools()
|
||||
@ -344,6 +352,7 @@ func (device *Device) RemoveAllPeers() {
|
||||
}
|
||||
|
||||
device.peers.keyMap = make(map[NoisePublicKey]*Peer)
|
||||
device.peers.IDMap = make(map[path.Vertex]*Peer)
|
||||
}
|
||||
|
||||
func (device *Device) Close() {
|
||||
@ -355,7 +364,7 @@ func (device *Device) Close() {
|
||||
atomic.StoreUint32(&device.state.state, uint32(deviceStateClosed))
|
||||
device.log.Verbosef("Device closing")
|
||||
|
||||
device.tun.device.Close()
|
||||
device.tap.device.Close()
|
||||
device.downLocked()
|
||||
|
||||
// Remove peers before closing queues,
|
||||
|
@ -8,11 +8,13 @@ package device
|
||||
import (
|
||||
"container/list"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
type Peer struct {
|
||||
@ -24,6 +26,8 @@ type Peer struct {
|
||||
endpoint conn.Endpoint
|
||||
stopping sync.WaitGroup // routines pending stop
|
||||
|
||||
ID path.Vertex
|
||||
|
||||
// These fields are accessed with atomic operations, which must be
|
||||
// 64-bit aligned even on 32-bit platforms. Go guarantees that an
|
||||
// allocated struct will be 64-bit aligned. So we place
|
||||
@ -63,7 +67,7 @@ type Peer struct {
|
||||
persistentKeepaliveInterval uint32 // accessed atomically
|
||||
}
|
||||
|
||||
func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
|
||||
func (device *Device) NewPeer(pk NoisePublicKey, id path.Vertex) (*Peer, error) {
|
||||
if device.isClosed() {
|
||||
return nil, errors.New("device closed")
|
||||
}
|
||||
@ -94,8 +98,13 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
|
||||
// map public key
|
||||
_, ok := device.peers.keyMap[pk]
|
||||
if ok {
|
||||
return nil, errors.New("adding existing peer")
|
||||
return nil, errors.New("adding existing peer pubkey:" + fmt.Sprint(pk))
|
||||
}
|
||||
_, ok = device.peers.IDMap[id]
|
||||
if ok {
|
||||
return nil, errors.New("adding existing peer id:" + fmt.Sprint(id))
|
||||
}
|
||||
peer.ID = id
|
||||
|
||||
// pre-compute DH
|
||||
handshake := &peer.handshake
|
||||
@ -109,6 +118,7 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
|
||||
|
||||
// add
|
||||
device.peers.keyMap[pk] = peer
|
||||
device.peers.IDMap[id] = peer
|
||||
|
||||
// start peer
|
||||
peer.timersInit()
|
||||
|
@ -9,16 +9,17 @@ import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
)
|
||||
|
||||
type QueueHandshakeElement struct {
|
||||
@ -397,6 +398,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||
|
||||
func (peer *Peer) RoutineSequentialReceiver() {
|
||||
device := peer.device
|
||||
var peer_out *Peer
|
||||
defer func() {
|
||||
device.log.Verbosef("%v - Routine: sequential receiver - stopped", peer)
|
||||
peer.stopping.Done()
|
||||
@ -407,7 +409,12 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
if elem == nil {
|
||||
return
|
||||
}
|
||||
var EgBody path.EgHeader
|
||||
var err error
|
||||
var src_nodeID path.Vertex
|
||||
var dst_nodeID path.Vertex
|
||||
should_receive := false
|
||||
should_transfer := false
|
||||
elem.Lock()
|
||||
if elem.packet == nil {
|
||||
// decryption failed
|
||||
@ -435,55 +442,64 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
}
|
||||
peer.timersDataReceived()
|
||||
|
||||
switch elem.packet[0] >> 4 {
|
||||
case ipv4.Version:
|
||||
if len(elem.packet) < ipv4.HeaderLen {
|
||||
goto skip
|
||||
}
|
||||
field := elem.packet[IPv4offsetTotalLength : IPv4offsetTotalLength+2]
|
||||
length := binary.BigEndian.Uint16(field)
|
||||
if int(length) > len(elem.packet) || int(length) < ipv4.HeaderLen {
|
||||
goto skip
|
||||
}
|
||||
elem.packet = elem.packet[:length]
|
||||
src := elem.packet[IPv4offsetSrc : IPv4offsetSrc+net.IPv4len]
|
||||
if device.allowedips.Lookup(src) != peer {
|
||||
device.log.Verbosef("IPv4 packet with disallowed source address from %v", peer)
|
||||
goto skip
|
||||
}
|
||||
EgBody, err = path.NewEgHeader(elem.packet[0:path.EgHeaderLen])
|
||||
src_nodeID = EgBody.GetSrc()
|
||||
dst_nodeID = EgBody.GetDst()
|
||||
//elem.packet = elem.packet[:EgBody.GetPacketLength()]
|
||||
|
||||
case ipv6.Version:
|
||||
if len(elem.packet) < ipv6.HeaderLen {
|
||||
goto skip
|
||||
}
|
||||
field := elem.packet[IPv6offsetPayloadLength : IPv6offsetPayloadLength+2]
|
||||
length := binary.BigEndian.Uint16(field)
|
||||
length += ipv6.HeaderLen
|
||||
if int(length) > len(elem.packet) {
|
||||
goto skip
|
||||
}
|
||||
elem.packet = elem.packet[:length]
|
||||
src := elem.packet[IPv6offsetSrc : IPv6offsetSrc+net.IPv6len]
|
||||
if device.allowedips.Lookup(src) != peer {
|
||||
device.log.Verbosef("IPv6 packet with disallowed source address from %v", peer)
|
||||
goto skip
|
||||
}
|
||||
|
||||
default:
|
||||
device.log.Verbosef("Packet with invalid IP version from %v", peer)
|
||||
if dst_nodeID == device.ID {
|
||||
should_receive = true
|
||||
} else if dst_nodeID == path.Boardcast {
|
||||
should_receive = true
|
||||
should_transfer = true
|
||||
} else if device.NhTable[device.ID][dst_nodeID] != nil {
|
||||
should_transfer = true
|
||||
} else {
|
||||
device.log.Verbosef("No route to peer ID %v", dst_nodeID)
|
||||
goto skip
|
||||
}
|
||||
|
||||
_, err = device.tun.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent)
|
||||
if err != nil && !device.isClosed() {
|
||||
device.log.Errorf("Failed to write packet to TUN device: %v", err)
|
||||
}
|
||||
if len(peer.queue.inbound.c) == 0 {
|
||||
err = device.tun.device.Flush()
|
||||
if err != nil {
|
||||
peer.device.log.Errorf("Unable to flush packets: %v", err)
|
||||
if should_transfer { //Send to another peer
|
||||
l2ttl := EgBody.GetTTL()
|
||||
if l2ttl == 0 {
|
||||
device.log.Verbosef("TTL is 0 %v", dst_nodeID)
|
||||
} else {
|
||||
EgBody.SetTTL(l2ttl - 1)
|
||||
if dst_nodeID != path.Boardcast {
|
||||
next_id := *device.NhTable[device.ID][dst_nodeID]
|
||||
peer_out = device.peers.IDMap[next_id]
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID)
|
||||
}
|
||||
device.SendPacket(peer_out, elem.packet, MessageTransportOffsetContent)
|
||||
} else {
|
||||
node_boardcast_list := path.GetBoardcastThroughList(device.ID, src_nodeID, device.NhTable)
|
||||
for peer_id := range node_boardcast_list {
|
||||
peer_out = device.peers.IDMap[peer_id]
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID)
|
||||
}
|
||||
device.SendPacket(peer_out, elem.packet, MessageTransportOffsetContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if should_receive {
|
||||
src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:])
|
||||
device.l2fib[src_macaddr] = src_nodeID // Write to l2fib table
|
||||
_, err = device.tap.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent+path.EgHeaderLen)
|
||||
if err != nil && !device.isClosed() {
|
||||
device.log.Errorf("Failed to write packet to TUN device: %v", err)
|
||||
}
|
||||
if len(peer.queue.inbound.c) == 0 {
|
||||
err = device.tap.device.Flush()
|
||||
if err != nil {
|
||||
peer.device.log.Errorf("Unable to flush packets: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutInboundElement(elem)
|
||||
|
@ -9,15 +9,14 @@ import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
/* Outbound flow
|
||||
@ -225,7 +224,7 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
// read packet
|
||||
|
||||
offset := MessageTransportHeaderSize
|
||||
size, err := device.tun.device.Read(elem.buffer[:], offset)
|
||||
size, err := device.tap.device.Read(elem.buffer[:], offset+path.EgHeaderLen)
|
||||
|
||||
if err != nil {
|
||||
if !device.isClosed() {
|
||||
@ -239,42 +238,62 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
return
|
||||
}
|
||||
|
||||
if size == 0 || size > MaxContentSize {
|
||||
if size == 0 || (size+path.EgHeaderLen) > MaxContentSize {
|
||||
continue
|
||||
}
|
||||
|
||||
//add custom header dst_node, src_node, ttl
|
||||
size += path.EgHeaderLen
|
||||
elem.packet = elem.buffer[offset : offset+size]
|
||||
|
||||
EgBody, err := path.NewEgHeader(elem.packet[0:path.EgHeaderLen])
|
||||
dst_nodeID := EgBody.GetDst()
|
||||
dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:])
|
||||
// lookup peer
|
||||
if tap.IsBoardCast(dstMacAddr) {
|
||||
dst_nodeID = path.Boardcast
|
||||
} else if val, ok := device.l2fib[dstMacAddr]; !ok { //Lookup failed
|
||||
dst_nodeID = path.Boardcast
|
||||
} else {
|
||||
dst_nodeID = val
|
||||
}
|
||||
EgBody.SetSrc(device.ID)
|
||||
EgBody.SetDst(dst_nodeID)
|
||||
//EgBody.SetPacketLength(uint16(len(elem.packet)))
|
||||
EgBody.SetTTL(200)
|
||||
|
||||
var peer *Peer
|
||||
switch elem.packet[0] >> 4 {
|
||||
case ipv4.Version:
|
||||
if len(elem.packet) < ipv4.HeaderLen {
|
||||
if dst_nodeID != path.Boardcast {
|
||||
var peer_out *Peer
|
||||
next_id := *device.NhTable[device.ID][dst_nodeID]
|
||||
peer_out = device.peers.IDMap[next_id]
|
||||
if peer_out == nil {
|
||||
continue
|
||||
}
|
||||
dst := elem.packet[IPv4offsetDst : IPv4offsetDst+net.IPv4len]
|
||||
peer = device.allowedips.Lookup(dst)
|
||||
|
||||
case ipv6.Version:
|
||||
if len(elem.packet) < ipv6.HeaderLen {
|
||||
continue
|
||||
if peer_out.isRunning.Get() {
|
||||
peer_out.StagePacket(elem)
|
||||
elem = nil
|
||||
peer_out.SendStagedPackets()
|
||||
}
|
||||
} else {
|
||||
for key, _ := range path.GetBoardcastList(device.ID, device.NhTable) {
|
||||
device.SendPacket(device.peers.IDMap[key], elem.packet, offset)
|
||||
}
|
||||
dst := elem.packet[IPv6offsetDst : IPv6offsetDst+net.IPv6len]
|
||||
peer = device.allowedips.Lookup(dst)
|
||||
|
||||
default:
|
||||
device.log.Verbosef("Received packet with unknown IP version")
|
||||
}
|
||||
|
||||
if peer == nil {
|
||||
continue
|
||||
}
|
||||
if peer.isRunning.Get() {
|
||||
peer.StagePacket(elem)
|
||||
elem = nil
|
||||
peer.SendStagedPackets()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) SendPacket(peer *Peer, packet []byte, offset int) {
|
||||
if peer == nil {
|
||||
return
|
||||
}
|
||||
var elem *QueueOutboundElement
|
||||
elem = device.NewOutboundElement()
|
||||
copy(elem.buffer[offset:offset+len(packet)], packet)
|
||||
elem.packet = elem.buffer[offset : offset+len(packet)]
|
||||
if peer.isRunning.Get() {
|
||||
peer.StagePacket(elem)
|
||||
elem = nil
|
||||
peer.SendStagedPackets()
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,7 +405,7 @@ func (device *Device) RoutineEncryption(id int) {
|
||||
binary.LittleEndian.PutUint64(fieldNonce, elem.nonce)
|
||||
|
||||
// pad content to multiple of 16
|
||||
paddingSize := calculatePaddingSize(len(elem.packet), int(atomic.LoadInt32(&device.tun.mtu)))
|
||||
paddingSize := calculatePaddingSize(len(elem.packet), int(atomic.LoadInt32(&device.tap.mtu)))
|
||||
elem.packet = append(elem.packet, paddingZeros[:paddingSize]...)
|
||||
|
||||
// encrypt content and release to consumer
|
||||
|
54
device/tap.go
Normal file
54
device/tap.go
Normal file
@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package device
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
)
|
||||
|
||||
const DefaultMTU = 1420
|
||||
|
||||
func (device *Device) RoutineTUNEventReader() {
|
||||
device.log.Verbosef("Routine: event worker - started")
|
||||
|
||||
for event := range device.tap.device.Events() {
|
||||
if event&tap.EventMTUUpdate != 0 {
|
||||
mtu, err := device.tap.device.MTU()
|
||||
if err != nil {
|
||||
device.log.Errorf("Failed to load updated MTU of device: %v", err)
|
||||
continue
|
||||
}
|
||||
if mtu < 0 {
|
||||
device.log.Errorf("MTU not updated to negative value: %v", mtu)
|
||||
continue
|
||||
}
|
||||
var tooLarge string
|
||||
if mtu > MaxContentSize {
|
||||
tooLarge = fmt.Sprintf(" (too large, capped at %v)", MaxContentSize)
|
||||
mtu = MaxContentSize
|
||||
}
|
||||
old := atomic.SwapInt32(&device.tap.mtu, int32(mtu))
|
||||
if int(old) != mtu {
|
||||
device.log.Verbosef("MTU updated: %v%s", mtu, tooLarge)
|
||||
}
|
||||
}
|
||||
|
||||
if event&tap.EventUp != 0 {
|
||||
device.log.Verbosef("Interface up requested")
|
||||
device.Up()
|
||||
}
|
||||
|
||||
if event&tap.EventDown != 0 {
|
||||
device.log.Verbosef("Interface down requested")
|
||||
device.Down()
|
||||
}
|
||||
}
|
||||
|
||||
device.log.Verbosef("Routine: event worker - stopped")
|
||||
}
|
@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
@ -19,6 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ipc"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
type IPCError struct {
|
||||
@ -120,11 +122,8 @@ func (device *Device) IpcGetOperation(w io.Writer) error {
|
||||
sendf("tx_bytes=%d", atomic.LoadUint64(&peer.stats.txBytes))
|
||||
sendf("rx_bytes=%d", atomic.LoadUint64(&peer.stats.rxBytes))
|
||||
sendf("persistent_keepalive_interval=%d", atomic.LoadUint32(&peer.persistentKeepaliveInterval))
|
||||
|
||||
device.allowedips.EntriesForPeer(peer, func(ip net.IP, cidr uint8) bool {
|
||||
sendf("allowed_ip=%s/%d", ip.String(), cidr)
|
||||
return true
|
||||
})
|
||||
sendf("allowed_ip=%s/%d", net.IPv4zero.String(), 0)
|
||||
sendf("allowed_ip=%s/%d", net.IPv6zero.String(), 0)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -269,6 +268,8 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error
|
||||
if err != nil {
|
||||
return ipcErrorf(ipc.IpcErrorInvalid, "failed to get peer by public key: %w", err)
|
||||
}
|
||||
h := crc32.NewIEEE()
|
||||
h.Write(publicKey[:])
|
||||
|
||||
// Ignore peer with the same public key as this device.
|
||||
device.staticIdentity.RLock()
|
||||
@ -283,7 +284,7 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error
|
||||
|
||||
peer.created = peer.Peer == nil
|
||||
if peer.created {
|
||||
peer.Peer, err = device.NewPeer(publicKey)
|
||||
peer.Peer, err = device.NewPeer(publicKey, path.Vertex(h.Sum32()))
|
||||
if err != nil {
|
||||
return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err)
|
||||
}
|
||||
@ -366,7 +367,6 @@ func (device *Device) handlePeerLine(peer *ipcSetPeer, key, value string) error
|
||||
if peer.dummy {
|
||||
return nil
|
||||
}
|
||||
device.allowedips.RemoveByPeer(peer.Peer)
|
||||
|
||||
case "allowed_ip":
|
||||
device.log.Verbosef("%v - UAPI: Adding allowedip", peer.Peer)
|
||||
@ -378,8 +378,7 @@ func (device *Device) handlePeerLine(peer *ipcSetPeer, key, value string) error
|
||||
if peer.dummy {
|
||||
return nil
|
||||
}
|
||||
ones, _ := network.Mask.Size()
|
||||
device.allowedips.Insert(network.IP, uint8(ones), peer.Peer)
|
||||
_, _ = network.Mask.Size()
|
||||
|
||||
case "protocol_version":
|
||||
if value != "1" {
|
||||
|
65
example_config/n1.yaml
Normal file
65
example_config/n1.yaml
Normal file
@ -0,0 +1,65 @@
|
||||
interface:
|
||||
itype: 'stdio'
|
||||
ifaceid: 1
|
||||
name: 'netcat1'
|
||||
macaddr: 'BB:AA:CC:DD:EE:01'
|
||||
mtu: 1500
|
||||
recvaddr: '127.0.0.1:4001'
|
||||
sendaddr: '127.0.0.1:5001'
|
||||
humanfriendly: true
|
||||
nodeid: 1
|
||||
nodename: 'Node1'
|
||||
privkey: 'SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng='
|
||||
listenport: 3001
|
||||
loglevel:
|
||||
loglevel: "error"
|
||||
logtransit: true
|
||||
supernode:
|
||||
enable: false
|
||||
pubkeyv4: ""
|
||||
pubkeyv6: ""
|
||||
regurlv4: ""
|
||||
regurlv6: ""
|
||||
apiurl: ""
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
peers:
|
||||
- nodeid: 2
|
||||
pubkey: 'NuYJ/3Ght+C4HovFq5Te/BrIazo6zwDJ8Bdu4rQCz0o='
|
||||
endpoint: '127.0.0.1:3002'
|
||||
|
70
example_config/n2.yaml
Normal file
70
example_config/n2.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
interface:
|
||||
itype: 'stdio'
|
||||
ifaceid: 2
|
||||
name: 'netcat2'
|
||||
macaddr: 'BB:AA:CC:DD:EE:02'
|
||||
mtu: 1500
|
||||
recvaddr: '127.0.0.1:4002'
|
||||
sendaddr: '127.0.0.1:5002'
|
||||
humanfriendly: true
|
||||
nodeid: 2
|
||||
nodename: 'Node2'
|
||||
privkey: '4Pb81ZCfhNjIT/fobxsUo4ZZ3fls/g9Py/u6/jpa1Vc='
|
||||
listenport: 3002
|
||||
loglevel:
|
||||
loglevel: "error"
|
||||
logtransit: true
|
||||
supernode:
|
||||
enable: false
|
||||
pubkeyv4: ''
|
||||
pubkeyv6: ''
|
||||
regurlv4: ''
|
||||
regurlv6: ''
|
||||
apiurl: ''
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
peers:
|
||||
- nodeid: 1
|
||||
pubkey: '51/RzDlzd0vuFUbNMvFeVA/5ZgtUQKb+6HD+C5Ea2jA='
|
||||
endpoint: '127.0.0.1:3001'
|
||||
- nodeid: 3
|
||||
pubkey: '9HsPa7QAgBjvSyW1EBuqGCyZtWdAZHkSIlGraTd4+1E='
|
||||
endpoint: '127.0.0.1:3003'
|
||||
- nodeid: 4
|
||||
pubkey: 'QHX2qo9+qn6hPxQ4/E5J7k07HZaBsD9rRxm90+YqTSA='
|
||||
endpoint: '127.0.0.1:3004'
|
70
example_config/n3.yaml
Normal file
70
example_config/n3.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
interface:
|
||||
itype: 'stdio'
|
||||
ifaceid: 3
|
||||
name: 'netcat3'
|
||||
macaddr: 'BB:AA:CC:DD:EE:03'
|
||||
mtu: 1500
|
||||
recvaddr: '127.0.0.1:4003'
|
||||
sendaddr: '127.0.0.1:5003'
|
||||
humanfriendly: true
|
||||
nodeid: 3
|
||||
nodename: 'Node3'
|
||||
privkey: '8InEcDezmnCyiLA7HC6/qFMKELb4XHdLd3jIu4Jk7lU='
|
||||
listenport: 3003
|
||||
loglevel:
|
||||
loglevel: "error"
|
||||
logtransit: true
|
||||
supernode:
|
||||
enable: false
|
||||
pubkeyv4: ''
|
||||
pubkeyv6: ''
|
||||
regurlv4: ''
|
||||
regurlv6: ''
|
||||
apiurl: ''
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
peers:
|
||||
- nodeid: 2
|
||||
pubkey: 'NuYJ/3Ght+C4HovFq5Te/BrIazo6zwDJ8Bdu4rQCz0o='
|
||||
endpoint: '127.0.0.1:3002'
|
||||
- nodeid: 4
|
||||
pubkey: 'QHX2qo9+qn6hPxQ4/E5J7k07HZaBsD9rRxm90+YqTSA='
|
||||
endpoint: '127.0.0.1:3004'
|
||||
- nodeid: 5
|
||||
pubkey: 'q91lHawt/0XcfONJ/gHvGirQlVztTxS0Br3zOpuh60o='
|
||||
endpoint: '127.0.0.1:3005'
|
70
example_config/n4.yaml
Normal file
70
example_config/n4.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
interface:
|
||||
itype: 'stdio'
|
||||
ifaceid: 4
|
||||
name: 'netcat4'
|
||||
macaddr: 'BB:AA:CC:DD:EE:04'
|
||||
mtu: 1500
|
||||
recvaddr: '127.0.0.1:4004'
|
||||
sendaddr: '127.0.0.1:5004'
|
||||
humanfriendly: true
|
||||
nodeid: 4
|
||||
nodename: 'Node4'
|
||||
privkey: 'qPPlRulMI8NFq+Mp5+dq8j486RdRXCATkmFGlNXawXI='
|
||||
listenport: 3004
|
||||
loglevel:
|
||||
loglevel: "error"
|
||||
logtransit: true
|
||||
supernode:
|
||||
enable: false
|
||||
pubkeyv4: ''
|
||||
pubkeyv6: ''
|
||||
regurlv4: ''
|
||||
regurlv6: ''
|
||||
apiurl: ''
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
peers:
|
||||
- nodeid: 2
|
||||
pubkey: 'NuYJ/3Ght+C4HovFq5Te/BrIazo6zwDJ8Bdu4rQCz0o='
|
||||
endpoint: '127.0.0.1:3002'
|
||||
- nodeid: 3
|
||||
pubkey: '9HsPa7QAgBjvSyW1EBuqGCyZtWdAZHkSIlGraTd4+1E='
|
||||
endpoint: '127.0.0.1:3003'
|
||||
- nodeid: 6
|
||||
pubkey: 'XwQfrzumgOXkfgkm3n/QR/RdqBGkclGTmtLBgmoboBM='
|
||||
endpoint: '127.0.0.1:3006'
|
64
example_config/n5.yaml
Normal file
64
example_config/n5.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
interface:
|
||||
itype: 'stdio'
|
||||
ifaceid: 5
|
||||
name: 'netcat5'
|
||||
macaddr: 'BB:AA:CC:DD:EE:05'
|
||||
mtu: 1500
|
||||
recvaddr: '127.0.0.1:4005'
|
||||
sendaddr: '127.0.0.1:5005'
|
||||
humanfriendly: true
|
||||
nodeid: 5
|
||||
nodename: 'Node5'
|
||||
privkey: 'IMW0j2o4cxBqXDPX2sqX8KkXbAHkrLGjklnrM4zh/3s='
|
||||
listenport: 3005
|
||||
loglevel:
|
||||
loglevel: "error"
|
||||
logtransit: true
|
||||
supernode:
|
||||
enable: false
|
||||
pubkeyv4: ''
|
||||
pubkeyv6: ''
|
||||
regurlv4: ''
|
||||
regurlv6: ''
|
||||
apiurl: ''
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
peers:
|
||||
- nodeid: 3
|
||||
pubkey: '9HsPa7QAgBjvSyW1EBuqGCyZtWdAZHkSIlGraTd4+1E='
|
||||
endpoint: '127.0.0.1:3003'
|
64
example_config/n6.yaml
Normal file
64
example_config/n6.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
interface:
|
||||
itype: 'stdio'
|
||||
ifaceid: 6
|
||||
name: 'netcat6'
|
||||
macaddr: 'BB:AA:CC:DD:EE:06'
|
||||
mtu: 1500
|
||||
recvaddr: '127.0.0.1:4006'
|
||||
sendaddr: '127.0.0.1:5006'
|
||||
humanfriendly: true
|
||||
nodeid: 6
|
||||
nodename: 'Node6'
|
||||
privkey: 'yFCnbYnsOZoq10+ErLdMwWWBh5PVOUv7G4A5T2AyiUc='
|
||||
listenport: 3006
|
||||
loglevel:
|
||||
loglevel: "error"
|
||||
logtransit: true
|
||||
supernode:
|
||||
enable: false
|
||||
pubkeyv4: ''
|
||||
pubkeyv6: ''
|
||||
regurlv4: ''
|
||||
regurlv6: ''
|
||||
apiurl: ''
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
peers:
|
||||
- nodeid: 4
|
||||
pubkey: 'QHX2qo9+qn6hPxQ4/E5J7k07HZaBsD9rRxm90+YqTSA='
|
||||
endpoint: '127.0.0.1:3004'
|
4
go.mod
4
go.mod
@ -3,7 +3,7 @@ module github.com/KusakabeSi/EtherGuardVPN
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
22
go.sum
22
go.sum
@ -1,22 +0,0 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169 h1:fpeMGRM6A+XFcw4RPCO8s8hH7ppgrGR22pSIjwM7YUI=
|
||||
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0=
|
||||
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210402192133-700132347e07 h1:4k6HsQjxj6hVMsI2Vf0yKlzt5lXxZsMW1q0zaq2k8zY=
|
||||
golang.org/x/sys v0.0.0-20210402192133-700132347e07/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
@ -28,6 +28,10 @@ const (
|
||||
// flag in wireguard-android.
|
||||
var socketDirectory = "/var/run/wireguard"
|
||||
|
||||
func SetsocketDirectory(path string) {
|
||||
socketDirectory = path
|
||||
}
|
||||
|
||||
func sockPath(iface string) string {
|
||||
return fmt.Sprintf("%s/%s.sock", socketDirectory, iface)
|
||||
}
|
||||
|
266
main.go
266
main.go
@ -8,17 +8,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/device"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ipc"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tun"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -27,243 +25,61 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
ENV_WG_TUN_FD = "WG_TUN_FD"
|
||||
ENV_WG_UAPI_FD = "WG_UAPI_FD"
|
||||
ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND"
|
||||
ENV_WP_UAPI_FD = "WP_UAPI_FD"
|
||||
ENV_WP_UAPI_DIR = "WP_UAPI_DIR"
|
||||
)
|
||||
|
||||
func printUsage() {
|
||||
fmt.Printf("Usage: %s [-f/--foreground] INTERFACE-NAME\n", os.Args[0])
|
||||
fmt.Printf("Usage: %s -s/c CONFIG-PATH\n", os.Args[0])
|
||||
}
|
||||
|
||||
func warning() {
|
||||
switch runtime.GOOS {
|
||||
case "linux", "freebsd", "openbsd":
|
||||
if os.Getenv(ENV_WG_PROCESS_FOREGROUND) == "1" {
|
||||
return
|
||||
}
|
||||
default:
|
||||
func readYaml(filePath string, out interface{}) (err error) {
|
||||
yamlFile, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = yaml.Unmarshal(yamlFile, out)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "┌──────────────────────────────────────────────────────┐")
|
||||
fmt.Fprintln(os.Stderr, "│ │")
|
||||
fmt.Fprintln(os.Stderr, "│ Running wireguard-go is not required because this │")
|
||||
fmt.Fprintln(os.Stderr, "│ kernel has first class support for WireGuard. For │")
|
||||
fmt.Fprintln(os.Stderr, "│ information on installing the kernel module, │")
|
||||
fmt.Fprintln(os.Stderr, "│ please visit: │")
|
||||
fmt.Fprintln(os.Stderr, "│ https://www.wireguard.com/install/ │")
|
||||
fmt.Fprintln(os.Stderr, "│ │")
|
||||
fmt.Fprintln(os.Stderr, "└──────────────────────────────────────────────────────┘")
|
||||
var (
|
||||
config = flag.String("config", "", "Config path for the interface.")
|
||||
mode = flag.String("mode", "edge", "Running mode. [super|edge]")
|
||||
version = flag.Bool("version", false, "Show version")
|
||||
help = flag.Bool("help", false, "Show this help")
|
||||
nouapi = flag.Bool("no-uapi", false, "Do not use UAPI")
|
||||
)
|
||||
|
||||
type LoggerInfo struct {
|
||||
LogLevel string
|
||||
LogTransit bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) == 2 && os.Args[1] == "--version" {
|
||||
flag.Parse()
|
||||
if *version == true {
|
||||
fmt.Printf("wireguard-go v%s\n\nUserspace WireGuard daemon for %s-%s.\nInformation available at https://www.wireguard.com.\nCopyright (C) Jason A. Donenfeld <Jason@zx2c4.com>.\n", Version, runtime.GOOS, runtime.GOARCH)
|
||||
return
|
||||
}
|
||||
|
||||
warning()
|
||||
|
||||
var foreground bool
|
||||
var interfaceName string
|
||||
if len(os.Args) < 2 || len(os.Args) > 3 {
|
||||
printUsage()
|
||||
if *help == true {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
switch os.Args[1] {
|
||||
|
||||
case "-f", "--foreground":
|
||||
foreground = true
|
||||
if len(os.Args) != 3 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
interfaceName = os.Args[2]
|
||||
uapiDir := os.Getenv(ENV_WP_UAPI_DIR)
|
||||
if uapiDir != "" {
|
||||
ipc.SetsocketDirectory(uapiDir)
|
||||
}
|
||||
|
||||
switch *mode {
|
||||
case "edge":
|
||||
Edge(*config, !*nouapi)
|
||||
case "super":
|
||||
Super(*config, !*nouapi)
|
||||
case "path":
|
||||
path.Solve()
|
||||
default:
|
||||
foreground = false
|
||||
if len(os.Args) != 2 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
interfaceName = os.Args[1]
|
||||
flag.Usage()
|
||||
}
|
||||
|
||||
if !foreground {
|
||||
foreground = os.Getenv(ENV_WG_PROCESS_FOREGROUND) == "1"
|
||||
}
|
||||
|
||||
// get log level (default: info)
|
||||
|
||||
logLevel := func() int {
|
||||
switch os.Getenv("LOG_LEVEL") {
|
||||
case "verbose", "debug":
|
||||
return device.LogLevelVerbose
|
||||
case "error":
|
||||
return device.LogLevelError
|
||||
case "silent":
|
||||
return device.LogLevelSilent
|
||||
}
|
||||
return device.LogLevelError
|
||||
}()
|
||||
|
||||
// open TUN device (or use supplied fd)
|
||||
|
||||
tun, err := func() (tun.Device, error) {
|
||||
tunFdStr := os.Getenv(ENV_WG_TUN_FD)
|
||||
if tunFdStr == "" {
|
||||
return tun.CreateTUN(interfaceName, device.DefaultMTU)
|
||||
}
|
||||
|
||||
// construct tun device from supplied fd
|
||||
|
||||
fd, err := strconv.ParseUint(tunFdStr, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = syscall.SetNonblock(int(fd), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file := os.NewFile(uintptr(fd), "")
|
||||
return tun.CreateTUNFromFile(file, device.DefaultMTU)
|
||||
}()
|
||||
|
||||
if err == nil {
|
||||
realInterfaceName, err2 := tun.Name()
|
||||
if err2 == nil {
|
||||
interfaceName = realInterfaceName
|
||||
}
|
||||
}
|
||||
|
||||
logger := device.NewLogger(
|
||||
logLevel,
|
||||
fmt.Sprintf("(%s) ", interfaceName),
|
||||
)
|
||||
|
||||
logger.Verbosef("Starting wireguard-go version %s", Version)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to create TUN device: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
// open UAPI file (or use supplied fd)
|
||||
|
||||
fileUAPI, err := func() (*os.File, error) {
|
||||
uapiFdStr := os.Getenv(ENV_WG_UAPI_FD)
|
||||
if uapiFdStr == "" {
|
||||
return ipc.UAPIOpen(interfaceName)
|
||||
}
|
||||
|
||||
// use supplied fd
|
||||
|
||||
fd, err := strconv.ParseUint(uapiFdStr, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return os.NewFile(uintptr(fd), ""), nil
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("UAPI listen error: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
return
|
||||
}
|
||||
// daemonize the process
|
||||
|
||||
if !foreground {
|
||||
env := os.Environ()
|
||||
env = append(env, fmt.Sprintf("%s=3", ENV_WG_TUN_FD))
|
||||
env = append(env, fmt.Sprintf("%s=4", ENV_WG_UAPI_FD))
|
||||
env = append(env, fmt.Sprintf("%s=1", ENV_WG_PROCESS_FOREGROUND))
|
||||
files := [3]*os.File{}
|
||||
if os.Getenv("LOG_LEVEL") != "" && logLevel != device.LogLevelSilent {
|
||||
files[0], _ = os.Open(os.DevNull)
|
||||
files[1] = os.Stdout
|
||||
files[2] = os.Stderr
|
||||
} else {
|
||||
files[0], _ = os.Open(os.DevNull)
|
||||
files[1], _ = os.Open(os.DevNull)
|
||||
files[2], _ = os.Open(os.DevNull)
|
||||
}
|
||||
attr := &os.ProcAttr{
|
||||
Files: []*os.File{
|
||||
files[0], // stdin
|
||||
files[1], // stdout
|
||||
files[2], // stderr
|
||||
tun.File(),
|
||||
fileUAPI,
|
||||
},
|
||||
Dir: ".",
|
||||
Env: env,
|
||||
}
|
||||
|
||||
path, err := os.Executable()
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to determine executable: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
process, err := os.StartProcess(
|
||||
path,
|
||||
os.Args,
|
||||
attr,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to daemonize: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
process.Release()
|
||||
return
|
||||
}
|
||||
|
||||
device := device.NewDevice(tun, conn.NewDefaultBind(), logger)
|
||||
|
||||
logger.Verbosef("Device started")
|
||||
|
||||
errs := make(chan error)
|
||||
term := make(chan os.Signal, 1)
|
||||
|
||||
uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to listen on uapi socket: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := uapi.Accept()
|
||||
if err != nil {
|
||||
errs <- err
|
||||
return
|
||||
}
|
||||
go device.IpcHandle(conn)
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Verbosef("UAPI listener started")
|
||||
|
||||
// wait for program to terminate
|
||||
|
||||
signal.Notify(term, syscall.SIGTERM)
|
||||
signal.Notify(term, os.Interrupt)
|
||||
|
||||
select {
|
||||
case <-term:
|
||||
case <-errs:
|
||||
case <-device.Wait():
|
||||
}
|
||||
|
||||
// clean up
|
||||
|
||||
uapi.Close()
|
||||
device.Close()
|
||||
|
||||
logger.Verbosef("Shutting down")
|
||||
return
|
||||
}
|
||||
|
229
main_edge.go
Normal file
229
main_edge.go
Normal file
@ -0,0 +1,229 @@
|
||||
// +build !windows
|
||||
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/device"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ipc"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type edgeConfig struct {
|
||||
Interface InterfaceConf
|
||||
NodeID path.Vertex
|
||||
NodeName string
|
||||
PrivKey string
|
||||
ListenPort int
|
||||
LogLevel LoggerInfo
|
||||
SuperNode SuperInfo
|
||||
NextHopTable path.NextHopTable
|
||||
Peers []PeerInfo
|
||||
}
|
||||
|
||||
type InterfaceConf struct {
|
||||
Itype string
|
||||
IfaceID int
|
||||
Name string
|
||||
MacAddr string
|
||||
MTU int
|
||||
RecvAddr string
|
||||
SendAddr string
|
||||
HumanFriendly bool
|
||||
}
|
||||
|
||||
type SuperInfo struct {
|
||||
Enable bool
|
||||
PubKeyV4 string
|
||||
PubKeyV6 string
|
||||
RegURLV4 string
|
||||
RegURLV6 string
|
||||
APIUrl string
|
||||
}
|
||||
|
||||
type PeerInfo struct {
|
||||
NodeID path.Vertex
|
||||
PubKey string
|
||||
EndPoint string
|
||||
}
|
||||
|
||||
func printExampleConf() {
|
||||
var config edgeConfig
|
||||
config.Peers = make([]PeerInfo, 3)
|
||||
var g path.IG
|
||||
g.Init(4)
|
||||
g.Edge(1, 2, 0.5)
|
||||
g.Edge(2, 1, 0.5)
|
||||
g.Edge(2, 3, 0.5)
|
||||
g.Edge(3, 2, 0.5)
|
||||
g.Edge(2, 4, 0.5)
|
||||
g.Edge(4, 2, 0.5)
|
||||
g.Edge(3, 4, 0.5)
|
||||
g.Edge(4, 3, 0.5)
|
||||
g.Edge(5, 3, 0.5)
|
||||
g.Edge(3, 5, 0.5)
|
||||
g.Edge(6, 4, 0.5)
|
||||
g.Edge(4, 6, 0.5)
|
||||
_, next := path.FloydWarshall(g)
|
||||
config.NextHopTable = next
|
||||
test, _ := yaml.Marshal(config)
|
||||
fmt.Print(string(test))
|
||||
return
|
||||
}
|
||||
|
||||
func Edge(configPath string, useUAPI bool) (err error) {
|
||||
|
||||
var config edgeConfig
|
||||
//printExampleConf()
|
||||
//return
|
||||
|
||||
err = readYaml(configPath, &config)
|
||||
if err != nil {
|
||||
fmt.Printf("Error read config: %s :", configPath)
|
||||
fmt.Print(err)
|
||||
return err
|
||||
}
|
||||
|
||||
interfaceName := config.NodeName
|
||||
|
||||
var logLevel int
|
||||
switch config.LogLevel.LogLevel {
|
||||
case "verbose", "debug":
|
||||
logLevel = device.LogLevelVerbose
|
||||
case "error":
|
||||
logLevel = device.LogLevelError
|
||||
case "silent":
|
||||
logLevel = device.LogLevelSilent
|
||||
}
|
||||
|
||||
logger := device.NewLogger(
|
||||
logLevel,
|
||||
fmt.Sprintf("(%s) ", interfaceName),
|
||||
)
|
||||
|
||||
logger.Verbosef("Starting wireguard-go version %s", Version)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("UAPI listen error: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
return
|
||||
}
|
||||
|
||||
var thetap tap.Device
|
||||
// open TUN device (or use supplied fd)
|
||||
switch config.Interface.Itype {
|
||||
case "dummy":
|
||||
thetap, err = tap.CreateDummyTAP()
|
||||
case "stdio":
|
||||
thetap, err = tap.CreateStdIOTAP(config.Interface.Name, config.Interface.HumanFriendly)
|
||||
case "udpsock":
|
||||
{
|
||||
lis, _ := net.ResolveUDPAddr("udp", config.Interface.RecvAddr)
|
||||
sen, _ := net.ResolveUDPAddr("udp", config.Interface.SendAddr)
|
||||
thetap, err = tap.CreateUDPSockTAP(config.Interface.Name, lis, sen, config.Interface.HumanFriendly)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to create TUN device: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Config
|
||||
the_device := device.NewDevice(thetap, config.NodeID, conn.NewDefaultBind(), logger)
|
||||
the_device.LogTransit = config.LogLevel.LogTransit
|
||||
the_device.NhTable = config.NextHopTable
|
||||
defer the_device.Close()
|
||||
var sk [32]byte
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(config.PrivKey)
|
||||
copy(sk[:], sk_slice)
|
||||
the_device.SetPrivateKey(sk)
|
||||
the_device.IpcSet("fwmark=0\n")
|
||||
the_device.IpcSet("listen_port=" + strconv.Itoa(config.ListenPort) + "\n")
|
||||
the_device.IpcSet("replace_peers=true\n")
|
||||
for _, peerconf := range config.Peers {
|
||||
sk_slice, _ = base64.StdEncoding.DecodeString(peerconf.PubKey)
|
||||
copy(sk[:], sk_slice)
|
||||
the_device.NewPeer(sk, peerconf.NodeID)
|
||||
if peerconf.EndPoint != "" {
|
||||
peer := the_device.LookupPeer(sk)
|
||||
endpoint, err := the_device.Bind().ParseEndpoint(peerconf.EndPoint)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err)
|
||||
return err
|
||||
}
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Verbosef("Device started")
|
||||
|
||||
errs := make(chan error)
|
||||
term := make(chan os.Signal, 1)
|
||||
|
||||
if useUAPI {
|
||||
|
||||
fileUAPI, err := func() (*os.File, error) {
|
||||
uapiFdStr := os.Getenv(ENV_WP_UAPI_FD)
|
||||
if uapiFdStr == "" {
|
||||
return ipc.UAPIOpen(interfaceName)
|
||||
}
|
||||
|
||||
// use supplied fd
|
||||
|
||||
fd, err := strconv.ParseUint(uapiFdStr, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.NewFile(uintptr(fd), ""), nil
|
||||
}()
|
||||
uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to listen on uapi socket: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := uapi.Accept()
|
||||
if err != nil {
|
||||
errs <- err
|
||||
return
|
||||
}
|
||||
go the_device.IpcHandle(conn)
|
||||
}
|
||||
}()
|
||||
defer uapi.Close()
|
||||
logger.Verbosef("UAPI listener started")
|
||||
}
|
||||
|
||||
// wait for program to terminate
|
||||
|
||||
signal.Notify(term, syscall.SIGTERM)
|
||||
signal.Notify(term, os.Interrupt)
|
||||
|
||||
select {
|
||||
case <-term:
|
||||
case <-errs:
|
||||
case <-the_device.Wait():
|
||||
}
|
||||
|
||||
logger.Verbosef("Shutting down")
|
||||
return
|
||||
}
|
12
main_super.go
Normal file
12
main_super.go
Normal file
@ -0,0 +1,12 @@
|
||||
// +build !windows
|
||||
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
func Super(configPath string, useUAPI bool) {
|
||||
|
||||
}
|
67
path/header.go
Normal file
67
path/header.go
Normal file
@ -0,0 +1,67 @@
|
||||
package path
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const EgHeaderLen = 10
|
||||
|
||||
type EgHeader struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
type Usage uint8
|
||||
|
||||
const (
|
||||
NornalPacket Usage = iota
|
||||
PingSingleWay
|
||||
PingDualWay
|
||||
)
|
||||
|
||||
func NewEgHeader(pac []byte) (e EgHeader, err error) {
|
||||
if len(pac) != EgHeaderLen {
|
||||
err = errors.New("Invalid packet size")
|
||||
return
|
||||
}
|
||||
e.buf = pac
|
||||
return
|
||||
}
|
||||
|
||||
func (e EgHeader) GetDst() Vertex {
|
||||
return Vertex(binary.BigEndian.Uint32(e.buf[0:4]))
|
||||
}
|
||||
func (e EgHeader) SetDst(node_ID Vertex) {
|
||||
binary.BigEndian.PutUint32(e.buf[0:4], uint32(node_ID))
|
||||
}
|
||||
|
||||
func (e EgHeader) GetSrc() Vertex {
|
||||
return Vertex(binary.BigEndian.Uint32(e.buf[4:8]))
|
||||
}
|
||||
func (e EgHeader) SetSrc(node_ID Vertex) {
|
||||
binary.BigEndian.PutUint32(e.buf[4:8], uint32(node_ID))
|
||||
}
|
||||
|
||||
func (e EgHeader) GetTTL() uint8 {
|
||||
return e.buf[8]
|
||||
}
|
||||
func (e EgHeader) SetTTL(ttl uint8) {
|
||||
|
||||
e.buf[8] = ttl
|
||||
}
|
||||
|
||||
func (e EgHeader) GetUsage() uint8 {
|
||||
return e.buf[9]
|
||||
}
|
||||
func (e EgHeader) SetUsage(usage uint8) {
|
||||
e.buf[9] = usage
|
||||
}
|
||||
|
||||
/*
|
||||
func (e EgHeader) GetPacketLength() uint16 {
|
||||
return binary.BigEndian.Uint16(e.buf[10:12])
|
||||
}
|
||||
func (e EgHeader) SetPacketLength(length uint16) {
|
||||
binary.BigEndian.PutUint16(e.buf[10:12], length)
|
||||
}
|
||||
*/
|
172
path/path.go
Normal file
172
path/path.go
Normal file
@ -0,0 +1,172 @@
|
||||
package path
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
timeout = time.Second * 3
|
||||
)
|
||||
|
||||
// A Graph is the interface implemented by graphs that
|
||||
// this algorithm can run on.
|
||||
type Graph interface {
|
||||
Vertices() map[Vertex]bool
|
||||
Neighbors(v Vertex) []Vertex
|
||||
Weight(u, v Vertex) float64
|
||||
}
|
||||
|
||||
// Nonnegative integer ID of vertex
|
||||
type Vertex uint32
|
||||
|
||||
const Infinity = 99999
|
||||
|
||||
var Boardcast = Vertex(math.MaxUint32)
|
||||
|
||||
type Latency struct {
|
||||
ping float64
|
||||
time time.Time
|
||||
}
|
||||
|
||||
type DistTable map[Vertex]map[Vertex]float64
|
||||
type NextHopTable map[Vertex]map[Vertex]*Vertex
|
||||
|
||||
type Fullroute struct {
|
||||
Dist DistTable `json:"total distance"`
|
||||
Next NextHopTable `json:"next hop"`
|
||||
}
|
||||
|
||||
// IG is a graph of integers that satisfies the Graph interface.
|
||||
type IG struct {
|
||||
Vert map[Vertex]bool
|
||||
Edges map[Vertex]map[Vertex]Latency
|
||||
}
|
||||
|
||||
func (g *IG) Init(num_node int) error {
|
||||
g.Vert = make(map[Vertex]bool, num_node)
|
||||
g.Edges = make(map[Vertex]map[Vertex]Latency, num_node)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *IG) Edge(u, v Vertex, w float64) {
|
||||
g.Vert[u] = true
|
||||
g.Vert[v] = true
|
||||
if _, ok := g.Edges[u]; !ok {
|
||||
g.Edges[u] = make(map[Vertex]Latency)
|
||||
}
|
||||
g.Edges[u][v] = Latency{
|
||||
ping: w,
|
||||
time: time.Now(),
|
||||
}
|
||||
}
|
||||
func (g IG) Vertices() map[Vertex]bool { return g.Vert }
|
||||
func (g IG) Neighbors(v Vertex) (vs []Vertex) {
|
||||
for k := range g.Edges[v] {
|
||||
vs = append(vs, k)
|
||||
}
|
||||
return vs
|
||||
}
|
||||
func (g IG) Weight(u, v Vertex) float64 {
|
||||
if time.Now().Sub(g.Edges[u][v].time) < timeout {
|
||||
return g.Edges[u][v].ping
|
||||
}
|
||||
return Infinity
|
||||
}
|
||||
|
||||
func FloydWarshall(g Graph) (dist DistTable, next NextHopTable) {
|
||||
vert := g.Vertices()
|
||||
dist = make(DistTable)
|
||||
next = make(NextHopTable)
|
||||
for u, _ := range vert {
|
||||
dist[u] = make(map[Vertex]float64)
|
||||
next[u] = make(map[Vertex]*Vertex)
|
||||
for v, _ := range vert {
|
||||
dist[u][v] = Infinity
|
||||
}
|
||||
dist[u][u] = 0
|
||||
for _, v := range g.Neighbors(u) {
|
||||
w := g.Weight(u, v)
|
||||
if w < Infinity {
|
||||
v := v
|
||||
dist[u][v] = w
|
||||
next[u][v] = &v
|
||||
}
|
||||
}
|
||||
}
|
||||
for k, _ := range vert {
|
||||
for i, _ := range vert {
|
||||
for j, _ := range vert {
|
||||
if dist[i][k] < Infinity && dist[k][j] < Infinity {
|
||||
if dist[i][j] > dist[i][k]+dist[k][j] {
|
||||
dist[i][j] = dist[i][k] + dist[k][j]
|
||||
next[i][j] = next[i][k]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dist, next
|
||||
}
|
||||
|
||||
func Path(u, v Vertex, next NextHopTable) (path []Vertex) {
|
||||
if next[u][v] == nil {
|
||||
return []Vertex{}
|
||||
}
|
||||
path = []Vertex{u}
|
||||
for u != v {
|
||||
u = *next[u][v]
|
||||
path = append(path, u)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func GetBoardcastList(id Vertex, nh NextHopTable) (tosend map[Vertex]bool) {
|
||||
tosend = make(map[Vertex]bool)
|
||||
for _, element := range nh[id] {
|
||||
tosend[*element] = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetBoardcastThroughList(id Vertex, src Vertex, nh NextHopTable) (tosend map[Vertex]bool) {
|
||||
tosend = make(map[Vertex]bool)
|
||||
for check_id, _ := range GetBoardcastList(id, nh) {
|
||||
for _, path_node := range Path(src, check_id, nh) {
|
||||
if path_node == id {
|
||||
tosend[check_id] = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Solve() {
|
||||
var g IG
|
||||
g.Init(4)
|
||||
g.Edge(1, 2, 0.5)
|
||||
g.Edge(2, 1, 0.5)
|
||||
g.Edge(2, 3, 2)
|
||||
g.Edge(3, 2, 2)
|
||||
g.Edge(2, 4, 0.7)
|
||||
g.Edge(4, 2, 2)
|
||||
dist, next := FloydWarshall(g)
|
||||
fmt.Println("pair\tdist\tpath")
|
||||
for u, m := range dist {
|
||||
for v, d := range m {
|
||||
if u != v {
|
||||
fmt.Printf("%d -> %d\t%3f\t%s\n", u, v, d, fmt.Sprint(Path(u, v, next)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Print("Finish")
|
||||
rr, _ := yaml.Marshal(Fullroute{
|
||||
Dist: dist,
|
||||
Next: next,
|
||||
})
|
||||
fmt.Print(string(rr))
|
||||
}
|
190
server.go
Normal file
190
server.go
Normal file
@ -0,0 +1,190 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
ConnV4 net.Addr
|
||||
ConnV6 net.Addr
|
||||
InterV4 []net.Addr
|
||||
InterV6 []net.Addr
|
||||
notify4 string
|
||||
notify6 string
|
||||
}
|
||||
|
||||
type action struct {
|
||||
Action string `json:"a"`
|
||||
Node_ID int `json:"id"`
|
||||
Name string `json:"n"`
|
||||
}
|
||||
|
||||
type serverConf struct {
|
||||
UDP_port int `json:"port"`
|
||||
CONN_url string `json:"url"`
|
||||
USE_Oneway bool `json:"use_oneway"`
|
||||
}
|
||||
|
||||
type pathLentancy struct {
|
||||
NodeID_S int `json:"src"`
|
||||
NodeID_E int `json:"dst"`
|
||||
Latency float64 `json:"ping"`
|
||||
Is_Oneway bool `json:"oneway"`
|
||||
}
|
||||
|
||||
var (
|
||||
clients = []client{}
|
||||
graph = path.IG{}
|
||||
node_num = 10
|
||||
udp_port = 9595
|
||||
http_port = 9595
|
||||
)
|
||||
|
||||
func (c *client) hasV4() bool {
|
||||
return c.ConnV4.String() == ""
|
||||
}
|
||||
func (c *client) hasV6() bool {
|
||||
return c.ConnV6.String() == ""
|
||||
}
|
||||
func (c *client) online() bool {
|
||||
return c.hasV4() || c.hasV6()
|
||||
}
|
||||
|
||||
func serv(conn net.Conn, version int) {
|
||||
buffer := make([]byte, 1024)
|
||||
|
||||
_, err := conn.Read(buffer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
incoming := string(buffer)
|
||||
fmt.Println("[INCOMING]", conn.RemoteAddr(), incoming)
|
||||
theaction := action{}
|
||||
err = json.Unmarshal(buffer, &theaction)
|
||||
if err != nil {
|
||||
fmt.Println("[Error]", err)
|
||||
return
|
||||
}
|
||||
|
||||
if theaction.Action != "register" {
|
||||
fmt.Println("[Error]", "Unknow action", theaction.Action)
|
||||
return
|
||||
}
|
||||
if version == 4 {
|
||||
clients[theaction.Node_ID].ConnV4 = conn.RemoteAddr()
|
||||
} else if version == 6 {
|
||||
clients[theaction.Node_ID].ConnV6 = conn.RemoteAddr()
|
||||
}
|
||||
conn.Write([]byte("OK"))
|
||||
err = conn.Close()
|
||||
if err != nil {
|
||||
fmt.Println("[Error]", err)
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func accept(listener net.Listener, version int) {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
serv(conn, version)
|
||||
}
|
||||
}
|
||||
|
||||
// Server --
|
||||
func RegisterServer() {
|
||||
/*
|
||||
graph.Init(node_num)
|
||||
clients = make([]client, node_num)
|
||||
|
||||
addr4 := &net.UDPAddr{
|
||||
IP: net.IPv4zero,
|
||||
Port: udp_port,
|
||||
}
|
||||
addr6 := &net.UDPAddr{
|
||||
IP: net.IPv6zero,
|
||||
Port: udp_port,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Connect to a DTLS server
|
||||
listener4, err4 := dtls.Listen("udp4", addr4)
|
||||
if err4 != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer listener4.Close()
|
||||
listener6, err6 := dtls.Listen("udp6", addr6)
|
||||
if err6 != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer listener6.Close()
|
||||
if err4 != nil && err6 != nil {
|
||||
fmt.Println("udp4 and udp6 both failed!")
|
||||
return
|
||||
}
|
||||
go accept(listener4, 4)
|
||||
go accept(listener6, 6)*/
|
||||
}
|
||||
|
||||
func get_config(w http.ResponseWriter, r *http.Request) {
|
||||
rr, _ := json.Marshal(serverConf{
|
||||
UDP_port: udp_port,
|
||||
CONN_url: "https://example.com",
|
||||
})
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(rr)
|
||||
}
|
||||
|
||||
func get_neighbor(w http.ResponseWriter, r *http.Request) {
|
||||
rr, _ := json.Marshal(clients)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(rr)
|
||||
}
|
||||
|
||||
func get_route(w http.ResponseWriter, r *http.Request) {
|
||||
dist, next := path.FloydWarshall(graph)
|
||||
rr, _ := json.Marshal(path.Fullroute{
|
||||
Dist: dist,
|
||||
Next: next,
|
||||
})
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(rr)
|
||||
}
|
||||
|
||||
func post_latency(w http.ResponseWriter, r *http.Request) {
|
||||
body := make([]byte, r.ContentLength)
|
||||
info := pathLentancy{}
|
||||
err := json.Unmarshal(body, &info)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(fmt.Sprint(err)))
|
||||
return
|
||||
}
|
||||
if info.Is_Oneway {
|
||||
graph.Edge(path.Vertex(info.NodeID_S), path.Vertex(info.NodeID_E), info.Latency)
|
||||
} else {
|
||||
graph.Edge(path.Vertex(info.NodeID_S), path.Vertex(info.NodeID_E), info.Latency/2)
|
||||
graph.Edge(path.Vertex(info.NodeID_E), path.Vertex(info.NodeID_S), info.Latency/2)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
}
|
||||
|
||||
func HttpServer() {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/neighbor/", get_neighbor)
|
||||
mux.HandleFunc("/api/route/", get_route)
|
||||
mux.HandleFunc("/api/latency/", post_latency)
|
||||
go http.ListenAndServe(":"+strconv.Itoa(http_port), mux)
|
||||
}
|
50
tap/tap.go
Normal file
50
tap/tap.go
Normal file
@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Event int
|
||||
type MacAddress [6]uint8
|
||||
|
||||
func GetDstMacAddr(packet []byte) (dstMacAddr MacAddress) {
|
||||
copy(dstMacAddr[:], packet[0:6])
|
||||
return
|
||||
}
|
||||
|
||||
func GetSrcMacAddr(packet []byte) (srcMacAddr MacAddress) {
|
||||
copy(srcMacAddr[:], packet[6:12])
|
||||
return
|
||||
}
|
||||
|
||||
func IsBoardCast(mac_in MacAddress) bool {
|
||||
if bytes.Equal(mac_in[:], []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) {
|
||||
return true
|
||||
} else if bytes.Equal(mac_in[0:2], []byte{0x33, 0x33}) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
EventUp = 1 << iota
|
||||
EventDown
|
||||
EventMTUUpdate
|
||||
)
|
||||
|
||||
type Device interface {
|
||||
File() *os.File // returns the file descriptor of the device
|
||||
Read([]byte, int) (int, error) // read a packet from the device (without any additional headers)
|
||||
Write([]byte, int) (int, error) // writes a packet to the device (without any additional headers)
|
||||
Flush() error // flush all previous writes to the device
|
||||
MTU() (int, error) // returns the MTU of the device
|
||||
Name() (string, error) // fetches and returns the current name
|
||||
Events() chan Event // returns a constant channel of events related to the device
|
||||
Close() error // stops the device and closes the event channel
|
||||
}
|
53
tap/tap_dummy.go
Normal file
53
tap/tap_dummy.go
Normal file
@ -0,0 +1,53 @@
|
||||
package tap
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type DummyTap struct {
|
||||
stopRead chan struct{}
|
||||
events chan Event
|
||||
}
|
||||
|
||||
// New creates and returns a new TUN interface for the application.
|
||||
func CreateDummyTAP() (tapdev Device, err error) {
|
||||
// Setup TUN Config
|
||||
tapdev = &DummyTap{
|
||||
stopRead: make(chan struct{}, 1<<5),
|
||||
events: make(chan Event, 1<<5),
|
||||
}
|
||||
tapdev.Events() <- EventUp
|
||||
return
|
||||
}
|
||||
|
||||
// SetMTU sets the Maximum Tansmission Unit Size for a
|
||||
// Packet on the interface.
|
||||
|
||||
func (tap *DummyTap) File() *os.File {
|
||||
var tapFile *os.File
|
||||
return tapFile
|
||||
} // returns the file descriptor of the device
|
||||
func (tap *DummyTap) Read([]byte, int) (int, error) {
|
||||
_ = <-tap.stopRead
|
||||
return 0, nil
|
||||
} // read a packet from the device (without any additional headers)
|
||||
func (tap *DummyTap) Write(packet []byte, size int) (int, error) {
|
||||
return size, nil
|
||||
} // writes a packet to the device (without any additional headers)
|
||||
func (tap *DummyTap) Flush() error {
|
||||
return nil
|
||||
} // flush all previous writes to the device
|
||||
func (tap *DummyTap) MTU() (int, error) {
|
||||
return 1500, nil
|
||||
} // returns the MTU of the device
|
||||
func (tap *DummyTap) Name() (string, error) {
|
||||
return "DummyDevice", nil
|
||||
} // fetches and returns the current name
|
||||
func (tap *DummyTap) Events() chan Event {
|
||||
return tap.events
|
||||
} // returns a constant channel of events related to the device
|
||||
func (tap *DummyTap) Close() error {
|
||||
tap.events <- EventDown
|
||||
close(tap.events)
|
||||
return nil
|
||||
} // stops the device and closes the event channel
|
97
tap/tap_stdio.go
Normal file
97
tap/tap_stdio.go
Normal file
@ -0,0 +1,97 @@
|
||||
package tap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type StdIOTap struct {
|
||||
name string
|
||||
mtu int
|
||||
HumanFriendly bool
|
||||
events chan Event
|
||||
}
|
||||
|
||||
func Charform2mac(b byte) MacAddress {
|
||||
if b == 'b' {
|
||||
return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||
}
|
||||
return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, b - 48}
|
||||
}
|
||||
func Mac2charForm(m []byte) byte {
|
||||
var M MacAddress
|
||||
copy(M[:], m)
|
||||
if IsBoardCast(M) {
|
||||
return 'b'
|
||||
}
|
||||
return m[5] + 48
|
||||
}
|
||||
|
||||
// New creates and returns a new TUN interface for the application.
|
||||
func CreateStdIOTAP(interfaceName string, HumanFriendly bool) (tapdev Device, err error) {
|
||||
// Setup TUN Config
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
tapdev = &StdIOTap{
|
||||
name: interfaceName,
|
||||
mtu: 1500,
|
||||
HumanFriendly: HumanFriendly,
|
||||
events: make(chan Event, 1<<5),
|
||||
}
|
||||
tapdev.Events() <- EventUp
|
||||
return
|
||||
}
|
||||
|
||||
// SetMTU sets the Maximum Tansmission Unit Size for a
|
||||
// Packet on the interface.
|
||||
|
||||
func (tap *StdIOTap) File() *os.File {
|
||||
var tapFile *os.File
|
||||
return tapFile
|
||||
} // returns the file descriptor of the device
|
||||
func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) {
|
||||
if tap.HumanFriendly {
|
||||
size, err := os.Stdin.Read(buf[offset+10:])
|
||||
packet := buf[offset:]
|
||||
src := Charform2mac(packet[11])
|
||||
dst := Charform2mac(packet[10])
|
||||
copy(packet[0:6], dst[:])
|
||||
copy(packet[6:12], src[:])
|
||||
return size - 2 + 12, err
|
||||
} else {
|
||||
size, err := os.Stdin.Read(buf[offset:])
|
||||
return size, err
|
||||
}
|
||||
} // read a packet from the device (without any additional headers)
|
||||
func (tap *StdIOTap) Write(buf []byte, offset int) (size int, err error) {
|
||||
packet := buf[offset:]
|
||||
if tap.HumanFriendly {
|
||||
src := Mac2charForm(packet[6:12])
|
||||
dst := Mac2charForm(packet[0:6])
|
||||
packet[10] = dst
|
||||
packet[11] = src
|
||||
packet = packet[10:]
|
||||
}
|
||||
size, err = os.Stdout.Write(packet)
|
||||
return
|
||||
} // writes a packet to the device (without any additional headers)
|
||||
func (tap *StdIOTap) Flush() error {
|
||||
return nil
|
||||
} // flush all previous writes to the device
|
||||
func (tap *StdIOTap) MTU() (int, error) {
|
||||
return tap.mtu, nil
|
||||
} // returns the MTU of the device
|
||||
func (tap *StdIOTap) Name() (string, error) {
|
||||
return tap.name, nil
|
||||
} // fetches and returns the current name
|
||||
func (tap *StdIOTap) Events() chan Event {
|
||||
return tap.events
|
||||
} // returns a constant channel of events related to the device
|
||||
func (tap *StdIOTap) Close() error {
|
||||
tap.events <- EventDown
|
||||
os.Stdin.Close()
|
||||
close(tap.events)
|
||||
return nil
|
||||
} // stops the device and closes the event channel
|
91
tap/tap_udpsock.go
Normal file
91
tap/tap_udpsock.go
Normal file
@ -0,0 +1,91 @@
|
||||
package tap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
type UdpSockTap struct {
|
||||
name string
|
||||
mtu int
|
||||
recv *net.UDPConn
|
||||
send *net.UDPAddr
|
||||
HumanFriendly bool
|
||||
events chan Event
|
||||
}
|
||||
|
||||
// New creates and returns a new TUN interface for the application.
|
||||
func CreateUDPSockTAP(interfaceName string, listenAddr *net.UDPAddr, sendAddr *net.UDPAddr, HumanFriendly bool) (tapdev Device, err error) {
|
||||
// Setup TUN Config
|
||||
|
||||
listener, err := net.ListenUDP("udp", listenAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
tapdev = &UdpSockTap{
|
||||
name: interfaceName,
|
||||
mtu: 1500,
|
||||
recv: listener,
|
||||
send: sendAddr,
|
||||
HumanFriendly: HumanFriendly,
|
||||
events: make(chan Event, 1<<5),
|
||||
}
|
||||
tapdev.Events() <- EventUp
|
||||
return
|
||||
}
|
||||
|
||||
// SetMTU sets the Maximum Tansmission Unit Size for a
|
||||
// Packet on the interface.
|
||||
|
||||
|
||||
func (tap *UdpSockTap) File() *os.File {
|
||||
var tapFile *os.File
|
||||
return tapFile
|
||||
} // returns the file descriptor of the device
|
||||
func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) {
|
||||
if tap.HumanFriendly {
|
||||
size, _, err := tap.recv.ReadFromUDP(buf[offset+10:])
|
||||
packet := buf[offset:]
|
||||
src := Charform2mac(packet[11])
|
||||
dst := Charform2mac(packet[10])
|
||||
copy(packet[0:6], dst[:])
|
||||
copy(packet[6:12], src[:])
|
||||
return size - 2 + 12, err
|
||||
} else {
|
||||
size, _, err := tap.recv.ReadFromUDP(buf[offset:])
|
||||
return size, err
|
||||
}
|
||||
|
||||
} // read a packet from the device (without any additional headers)
|
||||
func (tap *UdpSockTap) Write(buf []byte, offset int) (size int, err error) {
|
||||
packet := buf[offset:]
|
||||
if tap.HumanFriendly {
|
||||
src := Mac2charForm(packet[6:12])
|
||||
dst := Mac2charForm(packet[0:6])
|
||||
packet[10] = dst
|
||||
packet[11] = src
|
||||
size, err = tap.recv.WriteToUDP(packet[10:], tap.send)
|
||||
return
|
||||
}
|
||||
size, err = tap.recv.WriteToUDP(packet, tap.send)
|
||||
return
|
||||
} // writes a packet to the device (without any additional headers)
|
||||
func (tap *UdpSockTap) Flush() error {
|
||||
return nil
|
||||
} // flush all previous writes to the device
|
||||
func (tap *UdpSockTap) MTU() (int, error) {
|
||||
return tap.mtu, nil
|
||||
} // returns the MTU of the device
|
||||
func (tap *UdpSockTap) Name() (string, error) {
|
||||
return tap.name, nil
|
||||
} // fetches and returns the current name
|
||||
func (tap *UdpSockTap) Events() chan Event {
|
||||
return tap.events
|
||||
} // returns a constant channel of events related to the device
|
||||
func (tap *UdpSockTap) Close() error {
|
||||
tap.events <- EventDown
|
||||
tap.recv.Close()
|
||||
close(tap.events)
|
||||
return nil
|
||||
} // stops the device and closes the event channel
|
Loading…
Reference in New Issue
Block a user