LinuxTap, not test yet

This commit is contained in:
KusakabeSi 2021-08-24 08:43:55 +00:00
parent 26ba4dbe94
commit d717d35f64
32 changed files with 988 additions and 208 deletions

3
.vscode/launch.json vendored
View File

@ -10,7 +10,8 @@
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${workspaceFolder}", "program": "${workspaceFolder}",
"args":["-config","example_config/p2p_mode/n1.yaml","-mode","edge"/*,"-example"*/], "env": {"CGO_CFLAGS":"-I/usr/include/memif"},
"args":["-config","example_config/static_mode/n1.yaml","-mode","edge"/*,"-example"*/],
} }
] ]
} }

View File

@ -5,15 +5,16 @@ import (
) )
type EdgeConfig struct { type EdgeConfig struct {
Interface InterfaceConf Interface InterfaceConf
NodeID Vertex NodeID Vertex
NodeName string NodeName string
PrivKey string PrivKey string
ListenPort int ListenPort int
LogLevel LoggerInfo LogLevel LoggerInfo
DynamicRoute DynamicRouteInfo DynamicRoute DynamicRouteInfo
NextHopTable NextHopTable NextHopTable NextHopTable
Peers []PeerInfo ResetConnInterval float64
Peers []PeerInfo
} }
type SuperConfig struct { type SuperConfig struct {
@ -28,15 +29,15 @@ type SuperConfig struct {
} }
type InterfaceConf struct { type InterfaceConf struct {
Itype string Itype string
Name string Name string
VPPIfaceID uint32 VPPIfaceID uint32
VPPBridgeID uint32 VPPBridgeID uint32
MacAddr string MacAddrPrefix string
MTU int MTU int
RecvAddr string RecvAddr string
SendAddr string SendAddr string
DevFriendly bool L2HeaderMode string
} }
type PeerInfo struct { type PeerInfo struct {

View File

@ -7,6 +7,7 @@ package device
import ( import (
"encoding/base64" "encoding/base64"
"errors"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -69,9 +70,12 @@ type Device struct {
Peer_state [32]byte Peer_state [32]byte
} }
event_tryendpoint chan struct{} event_tryendpoint chan struct{}
ResetConnInterval float64
EdgeConfigPath string EdgeConfigPath string
EdgeConfig *config.EdgeConfig EdgeConfig *config.EdgeConfig
SuperConfigPath string
SuperConfig *config.SuperConfig
Event_server_register chan path.RegisterMsg Event_server_register chan path.RegisterMsg
Event_server_pong chan path.PongMsg Event_server_pong chan path.PongMsg
@ -304,7 +308,7 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
return nil return nil
} }
func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, theconfigpath string, econfig *config.EdgeConfig, sconfig *config.SuperConfig, superevents *path.SUPER_Events) *Device { func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, configpath string, econfig *config.EdgeConfig, sconfig *config.SuperConfig, superevents *path.SUPER_Events) *Device {
device := new(Device) device := new(Device)
device.state.state = uint32(deviceStateDown) device.state.state = uint32(deviceStateDown)
device.closed = make(chan struct{}) device.closed = make(chan struct{})
@ -333,9 +337,11 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L
device.Event_server_NhTable_changed = superevents.Event_server_NhTable_changed device.Event_server_NhTable_changed = superevents.Event_server_NhTable_changed
device.LogTransit = sconfig.LogLevel.LogTransit device.LogTransit = sconfig.LogLevel.LogTransit
device.LogControl = sconfig.LogLevel.LogControl device.LogControl = sconfig.LogLevel.LogControl
device.SuperConfig = sconfig
device.SuperConfigPath = configpath
go device.RoutineRecalculateNhTable() go device.RoutineRecalculateNhTable()
} else { } else {
device.EdgeConfigPath = theconfigpath device.EdgeConfigPath = configpath
device.EdgeConfig = econfig device.EdgeConfig = econfig
device.DRoute = econfig.DynamicRoute device.DRoute = econfig.DynamicRoute
device.DupData = *fixed_time_cache.NewCache(path.S2TD(econfig.DynamicRoute.DupCheckTimeout), false, path.S2TD(60)) device.DupData = *fixed_time_cache.NewCache(path.S2TD(econfig.DynamicRoute.DupCheckTimeout), false, path.S2TD(60))
@ -343,11 +349,13 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L
device.Event_save_config = make(chan struct{}, 1<<5) device.Event_save_config = make(chan struct{}, 1<<5)
device.LogTransit = econfig.LogLevel.LogTransit device.LogTransit = econfig.LogLevel.LogTransit
device.LogControl = econfig.LogLevel.LogControl device.LogControl = econfig.LogLevel.LogControl
device.ResetConnInterval = device.EdgeConfig.ResetConnInterval
go device.RoutineSetEndpoint() go device.RoutineSetEndpoint()
go device.RoutineRegister() go device.RoutineRegister()
go device.RoutineSendPing() go device.RoutineSendPing()
go device.RoutineRecalculateNhTable() go device.RoutineRecalculateNhTable()
go device.RoutineSpreadAllMyNeighbor() go device.RoutineSpreadAllMyNeighbor()
go device.RoutineResetConn()
} }
// create queues // create queues
@ -374,6 +382,29 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L
return device return device
} }
func (device *Device) LookupPeerIDAtConfig(pk NoisePublicKey) (ID config.Vertex, err error) {
var peerlist []config.PeerInfo
if device.IsSuperNode {
if device.SuperConfig == nil {
return 0, errors.New("Superconfig is nil")
}
peerlist = device.SuperConfig.Peers
} else {
if device.EdgeConfig == nil {
return 0, errors.New("EdgeConfig is nil")
}
peerlist = device.EdgeConfig.Peers
}
pkstr := PubKey2Str(pk)
for _, peerinfo := range peerlist {
if peerinfo.PubKey == pkstr {
return peerinfo.NodeID, nil
}
}
return 0, errors.New("Peer not found in the config file.")
}
func (device *Device) LookupPeer(pk NoisePublicKey) *Peer { func (device *Device) LookupPeer(pk NoisePublicKey) *Peer {
device.peers.RLock() device.peers.RLock()
defer device.peers.RUnlock() defer device.peers.RUnlock()

View File

@ -36,6 +36,8 @@ type Peer struct {
ID config.Vertex ID config.Vertex
AskedForNeighbor bool AskedForNeighbor bool
StaticConn bool //if true, this peer will not write to config file when roaming, and the endpoint will be reset periodically
ConnURL string
// These fields are accessed with atomic operations, which must be // These fields are accessed with atomic operations, which must be
// 64-bit aligned even on 32-bit platforms. Go guarantees that an // 64-bit aligned even on 32-bit platforms. Go guarantees that an
@ -330,15 +332,16 @@ func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) {
if device.IsSuperNode { //Can't in super mode if device.IsSuperNode { //Can't in super mode
return return
} }
if peer.StaticConn == true { //static conn do not write new endpoint to config
return
}
if !device.DRoute.P2P.UseP2P { //Must in p2p mode if !device.DRoute.P2P.UseP2P { //Must in p2p mode
return return
} }
if peer.endpoint != nil && peer.endpoint.DstIP().Equal(endpoint.DstIP()) { //endpoint changed if peer.endpoint != nil && peer.endpoint.DstIP().Equal(endpoint.DstIP()) { //endpoint changed
return return
} }
if peer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).After(time.Now()) { //Peer alives
return
}
url := endpoint.DstToString() url := endpoint.DstToString()
foundInFile := false foundInFile := false
pubkeystr := PubKey2Str(peer.handshake.remoteStatic) pubkeystr := PubKey2Str(peer.handshake.remoteStatic)

View File

@ -548,7 +548,7 @@ func (peer *Peer) RoutineSequentialReceiver() {
goto skip goto skip
} }
src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:]) src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:])
if !tap.IsBoardCast(src_macaddr) { if !tap.IsNotUnicast(src_macaddr) {
device.l2fib.Store(src_macaddr, src_nodeID) // Write to l2fib table device.l2fib.Store(src_macaddr, src_nodeID) // Write to l2fib table
} }
_, err = device.tap.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent+path.EgHeaderLen) _, err = device.tap.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent+path.EgHeaderLen)

View File

@ -142,7 +142,7 @@ func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []b
} }
case path.BoardcastPeer: case path.BoardcastPeer:
if content, err := path.ParseBoardcastPeerMsg(body); err == nil { if content, err := path.ParseBoardcastPeerMsg(body); err == nil {
return device.process_BoardcastPeerMsg(content) return device.process_BoardcastPeerMsg(peer, content)
} }
default: default:
err = errors.New("Not a valid msg_type") err = errors.New("Not a valid msg_type")
@ -245,7 +245,6 @@ func (device *Device) process_pong(peer *Peer, content path.PongMsg) error {
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
copy(buf[path.EgHeaderLen:], body) copy(buf[path.EgHeaderLen:], body)
device.SendPacket(peer, buf, MessageTransportOffsetContent) device.SendPacket(peer, buf, MessageTransportOffsetContent)
peer.AskedForNeighbor = true
} }
} }
return nil return nil
@ -434,12 +433,35 @@ func (device *Device) RoutineSpreadAllMyNeighbor() {
} }
for { for {
device.process_RequestPeerMsg(path.QueryPeerMsg{ device.process_RequestPeerMsg(path.QueryPeerMsg{
Request_ID: 0, Request_ID: uint32(path.Boardcast),
}) })
time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval)) time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval))
} }
} }
func (device *Device) RoutineResetConn() {
if device.ResetConnInterval <= 0.01 {
return
}
for {
for _, peer := range device.peers.keyMap {
if peer.StaticConn {
continue
}
if peer.ConnURL == "" {
continue
}
endpoint, err := device.Bind().ParseEndpoint(peer.ConnURL)
if err != nil {
device.log.Errorf("Failed to bind "+peer.ConnURL, err)
continue
}
peer.SetEndpointFromPacket(endpoint)
}
time.Sleep(time.Duration(device.ResetConnInterval))
}
}
func (device *Device) GeneratePingPacket(src_nodeID config.Vertex) ([]byte, error) { func (device *Device) GeneratePingPacket(src_nodeID config.Vertex) ([]byte, error) {
body, err := path.GetByte(&path.PingMsg{ body, err := path.GetByte(&path.PingMsg{
Src_nodeID: src_nodeID, Src_nodeID: src_nodeID,
@ -531,9 +553,12 @@ func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error {
return nil return nil
} }
func (device *Device) process_BoardcastPeerMsg(content path.BoardcastPeerMsg) error { func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.BoardcastPeerMsg) error {
if device.DRoute.P2P.UseP2P { if device.DRoute.P2P.UseP2P {
var sk NoisePublicKey var sk NoisePublicKey
if content.Request_ID == uint32(device.ID) {
peer.AskedForNeighbor = true
}
if bytes.Equal(content.PubKey[:], device.staticIdentity.publicKey[:]) { if bytes.Equal(content.PubKey[:], device.staticIdentity.publicKey[:]) {
return nil return nil
} }

View File

@ -250,7 +250,7 @@ func (device *Device) RoutineReadFromTUN() {
dst_nodeID := EgBody.GetDst() dst_nodeID := EgBody.GetDst()
dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:]) dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:])
// lookup peer // lookup peer
if tap.IsBoardCast(dstMacAddr) { if tap.IsNotUnicast(dstMacAddr) {
dst_nodeID = path.Boardcast dst_nodeID = path.Boardcast
} else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed } else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed
dst_nodeID = path.Boardcast dst_nodeID = path.Boardcast

View File

@ -10,7 +10,6 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"hash/crc32"
"io" "io"
"net" "net"
"strconv" "strconv"
@ -19,7 +18,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config"
"github.com/KusakabeSi/EtherGuardVPN/ipc" "github.com/KusakabeSi/EtherGuardVPN/ipc"
) )
@ -268,8 +266,6 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error
if err != nil { if err != nil {
return ipcErrorf(ipc.IpcErrorInvalid, "failed to get peer by public key: %w", err) 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. // Ignore peer with the same public key as this device.
device.staticIdentity.RLock() device.staticIdentity.RLock()
@ -284,7 +280,11 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error
peer.created = peer.Peer == nil peer.created = peer.Peer == nil
if peer.created { if peer.created {
peer.Peer, err = device.NewPeer(publicKey, config.Vertex(h.Sum32())) id, err := device.LookupPeerIDAtConfig(publicKey)
if err != nil {
return errors.New("Create new peer by UAPI is not implemented")
}
peer.Peer, err = device.NewPeer(publicKey, id)
if err != nil { if err != nil {
return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err) return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err)
} }

View File

@ -1,18 +1,19 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 1
name: tap1 name: tap1
macaddr: AA:BB:CC:DD:EE:01 vppifaceid: 1
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4001 recvaddr: 127.0.0.1:4001
sendaddr: 127.0.0.1:5001 sendaddr: 127.0.0.1:5001
devfriendly: true l2headermode: kbdbg
nodeid: 1 nodeid: 1
nodename: Node01 nodename: Node01
privkey: aABzjKhWdkFfQ29ZuijtMp1h1TNJe66SDCwvfmvQznw= privkey: aABzjKhWdkFfQ29ZuijtMp1h1TNJe66SDCwvfmvQznw=
listenport: 3001 listenport: 3001
loglevel: loglevel:
loglevel: normal` loglevel: normal
logtransit: true logtransit: true
logcontrol: true logcontrol: true
dynamicroute: dynamicroute:
@ -23,9 +24,9 @@ dynamicroute:
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 2 - nodeid: 2
pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 2
name: tap2 name: tap2
macaddr: AA:BB:CC:DD:EE:02 vppifaceid: 2
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4002 recvaddr: 127.0.0.1:4002
sendaddr: 127.0.0.1:5002 sendaddr: 127.0.0.1:5002
devfriendly: true l2headermode: kbdbg
nodeid: 2 nodeid: 2
nodename: Node02 nodename: Node02
privkey: UNZMzPX5fG/8yGC8edVj/ksF9N6ARRqdq7fqE/PD7ls= privkey: UNZMzPX5fG/8yGC8edVj/ksF9N6ARRqdq7fqE/PD7ls=
@ -23,9 +24,9 @@ dynamicroute:
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 1 - nodeid: 1
pubkey: CooSkIP7/wiC7Rh83UYnB2yPkJijkNFmhtorHtyYlzY= pubkey: CooSkIP7/wiC7Rh83UYnB2yPkJijkNFmhtorHtyYlzY=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 3
name: tap3 name: tap3
macaddr: AA:BB:CC:DD:EE:03 vppifaceid: 3
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4003 recvaddr: 127.0.0.1:4003
sendaddr: 127.0.0.1:5003 sendaddr: 127.0.0.1:5003
devfriendly: true l2headermode: kbdbg
nodeid: 3 nodeid: 3
nodename: Node03 nodename: Node03
privkey: gJy35nbsd8FuuxyWHjsefN+U+oM7RkuIB1EanNLSVHg= privkey: gJy35nbsd8FuuxyWHjsefN+U+oM7RkuIB1EanNLSVHg=
@ -23,9 +24,9 @@ dynamicroute:
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 2 - nodeid: 2
pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 4
name: tap4 name: tap4
macaddr: AA:BB:CC:DD:EE:04 vppifaceid: 4
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4004 recvaddr: 127.0.0.1:4004
sendaddr: 127.0.0.1:5004 sendaddr: 127.0.0.1:5004
devfriendly: true l2headermode: kbdbg
nodeid: 4 nodeid: 4
nodename: Node04 nodename: Node04
privkey: wAdLgCk0SHiO11/aUf9944focD1BUCH5b6Pe+cRHHXQ= privkey: wAdLgCk0SHiO11/aUf9944focD1BUCH5b6Pe+cRHHXQ=
@ -23,9 +24,9 @@ dynamicroute:
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 2 - nodeid: 2
pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 5
name: tap5 name: tap5
macaddr: AA:BB:CC:DD:EE:05 vppifaceid: 5
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4005 recvaddr: 127.0.0.1:4005
sendaddr: 127.0.0.1:5005 sendaddr: 127.0.0.1:5005
devfriendly: true l2headermode: kbdbg
nodeid: 5 nodeid: 5
nodename: Node05 nodename: Node05
privkey: gLmzeCbmN/hjiE+ehNXL9IxuG9hhWIYv2s16/DOW6FE= privkey: gLmzeCbmN/hjiE+ehNXL9IxuG9hhWIYv2s16/DOW6FE=
@ -23,9 +24,9 @@ dynamicroute:
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 3 - nodeid: 3
pubkey: 0meQ0pQCAkLZdpfyMqggpnk0k3UKG2M8jfIMlQjTRWs= pubkey: 0meQ0pQCAkLZdpfyMqggpnk0k3UKG2M8jfIMlQjTRWs=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 6
name: tap6 name: tap6
macaddr: AA:BB:CC:DD:EE:03 vppifaceid: 6
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4006 recvaddr: 127.0.0.1:4006
sendaddr: 127.0.0.1:5006 sendaddr: 127.0.0.1:5006
devfriendly: true l2headermode: kbdbg
nodeid: 6 nodeid: 6
nodename: Node06 nodename: Node06
privkey: IIX5F6oWZUS2dlhxWFJ7TxdJtDCr5jzeuhxUB6YM7Us= privkey: IIX5F6oWZUS2dlhxWFJ7TxdJtDCr5jzeuhxUB6YM7Us=
@ -23,9 +24,9 @@ dynamicroute:
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 4 - nodeid: 4
pubkey: 2EfY85KF1S+3dZ3A55eZcyi0QU+sOzOyuADtJs2U2Ww= pubkey: 2EfY85KF1S+3dZ3A55eZcyi0QU+sOzOyuADtJs2U2Ww=

View File

@ -1,31 +1,32 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 1
name: tap1 name: tap1
macaddr: AA:BB:CC:DD:EE:01 vppifaceid: 1
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4001 recvaddr: 127.0.0.1:4001
sendaddr: 127.0.0.1:5001 sendaddr: 127.0.0.1:5001
devfriendly: true l2headermode: kbdbg
nodeid: 1 nodeid: 1
nodename: Node01 nodename: Node01
privkey: aABzjKhWdkFfQ29ZuijtMp1h1TNJe66SDCwvfmvQznw= privkey: aABzjKhWdkFfQ29ZuijtMp1h1TNJe66SDCwvfmvQznw=
listenport: 3001 listenport: 3001
loglevel: loglevel:
loglevel: normal` loglevel: normal
logtransit: true logtransit: true
logcontrol: true logcontrol: true
dynamicroute: dynamicroute:
sendpinginterval: 20 sendpinginterval: 20
dupchecktimeout: 40 dupchecktimeout: 40
conntimeout: 30 conntimeout: 30
savenewpeers: true savenewpeers: false
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 2 - nodeid: 2
pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 2
name: tap2 name: tap2
macaddr: AA:BB:CC:DD:EE:02 vppifaceid: 2
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4002 recvaddr: 127.0.0.1:4002
sendaddr: 127.0.0.1:5002 sendaddr: 127.0.0.1:5002
devfriendly: true l2headermode: kbdbg
nodeid: 2 nodeid: 2
nodename: Node02 nodename: Node02
privkey: UNZMzPX5fG/8yGC8edVj/ksF9N6ARRqdq7fqE/PD7ls= privkey: UNZMzPX5fG/8yGC8edVj/ksF9N6ARRqdq7fqE/PD7ls=
@ -19,13 +20,13 @@ dynamicroute:
sendpinginterval: 20 sendpinginterval: 20
dupchecktimeout: 40 dupchecktimeout: 40
conntimeout: 30 conntimeout: 30
savenewpeers: true savenewpeers: false
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 1 - nodeid: 1
pubkey: CooSkIP7/wiC7Rh83UYnB2yPkJijkNFmhtorHtyYlzY= pubkey: CooSkIP7/wiC7Rh83UYnB2yPkJijkNFmhtorHtyYlzY=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 3
name: tap3 name: tap3
macaddr: AA:BB:CC:DD:EE:03 vppifaceid: 3
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4003 recvaddr: 127.0.0.1:4003
sendaddr: 127.0.0.1:5003 sendaddr: 127.0.0.1:5003
devfriendly: true l2headermode: kbdbg
nodeid: 3 nodeid: 3
nodename: Node03 nodename: Node03
privkey: gJy35nbsd8FuuxyWHjsefN+U+oM7RkuIB1EanNLSVHg= privkey: gJy35nbsd8FuuxyWHjsefN+U+oM7RkuIB1EanNLSVHg=
@ -19,13 +20,13 @@ dynamicroute:
sendpinginterval: 20 sendpinginterval: 20
dupchecktimeout: 40 dupchecktimeout: 40
conntimeout: 30 conntimeout: 30
savenewpeers: true savenewpeers: false
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 2 - nodeid: 2
pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 4
name: tap4 name: tap4
macaddr: AA:BB:CC:DD:EE:04 vppifaceid: 4
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4004 recvaddr: 127.0.0.1:4004
sendaddr: 127.0.0.1:5004 sendaddr: 127.0.0.1:5004
devfriendly: true l2headermode: kbdbg
nodeid: 4 nodeid: 4
nodename: Node04 nodename: Node04
privkey: wAdLgCk0SHiO11/aUf9944focD1BUCH5b6Pe+cRHHXQ= privkey: wAdLgCk0SHiO11/aUf9944focD1BUCH5b6Pe+cRHHXQ=
@ -19,13 +20,13 @@ dynamicroute:
sendpinginterval: 20 sendpinginterval: 20
dupchecktimeout: 40 dupchecktimeout: 40
conntimeout: 30 conntimeout: 30
savenewpeers: true savenewpeers: false
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 2 - nodeid: 2
pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 5
name: tap5 name: tap5
macaddr: AA:BB:CC:DD:EE:05 vppifaceid: 5
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4005 recvaddr: 127.0.0.1:4005
sendaddr: 127.0.0.1:5005 sendaddr: 127.0.0.1:5005
devfriendly: true l2headermode: kbdbg
nodeid: 5 nodeid: 5
nodename: Node05 nodename: Node05
privkey: gLmzeCbmN/hjiE+ehNXL9IxuG9hhWIYv2s16/DOW6FE= privkey: gLmzeCbmN/hjiE+ehNXL9IxuG9hhWIYv2s16/DOW6FE=
@ -19,13 +20,13 @@ dynamicroute:
sendpinginterval: 20 sendpinginterval: 20
dupchecktimeout: 40 dupchecktimeout: 40
conntimeout: 30 conntimeout: 30
savenewpeers: true savenewpeers: false
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 3 - nodeid: 3
pubkey: 0meQ0pQCAkLZdpfyMqggpnk0k3UKG2M8jfIMlQjTRWs= pubkey: 0meQ0pQCAkLZdpfyMqggpnk0k3UKG2M8jfIMlQjTRWs=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 6
name: tap6 name: tap6
macaddr: AA:BB:CC:DD:EE:03 vppifaceid: 6
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4006 recvaddr: 127.0.0.1:4006
sendaddr: 127.0.0.1:5006 sendaddr: 127.0.0.1:5006
devfriendly: true l2headermode: kbdbg
nodeid: 6 nodeid: 6
nodename: Node06 nodename: Node06
privkey: IIX5F6oWZUS2dlhxWFJ7TxdJtDCr5jzeuhxUB6YM7Us= privkey: IIX5F6oWZUS2dlhxWFJ7TxdJtDCr5jzeuhxUB6YM7Us=
@ -19,13 +20,13 @@ dynamicroute:
sendpinginterval: 20 sendpinginterval: 20
dupchecktimeout: 40 dupchecktimeout: 40
conntimeout: 30 conntimeout: 30
savenewpeers: true savenewpeers: false
supernode: supernode:
usesupernode: false usesupernode: false
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:3000' connurlv6: '[::1]:3000'
pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
p2p: p2p:
@ -93,6 +94,7 @@ nexthoptable:
3: 4 3: 4
4: 4 4: 4
5: 4 5: 4
resetconninterval: 86400
peers: peers:
- nodeid: 4 - nodeid: 4
pubkey: 2EfY85KF1S+3dZ3A55eZcyi0QU+sOzOyuADtJs2U2Ww= pubkey: 2EfY85KF1S+3dZ3A55eZcyi0QU+sOzOyuADtJs2U2Ww=

View File

@ -1,12 +1,13 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 1
name: tap1 name: tap1
macaddr: AA:BB:CC:DD:EE:FF vppifaceid: 1
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4001 recvaddr: 127.0.0.1:4001
sendaddr: 127.0.0.1:5001 sendaddr: 127.0.0.1:5001
devfriendly: true l2headermode: kbdbg
nodeid: 1 nodeid: 1
nodename: Node01 nodename: Node01
privkey: 6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M= privkey: 6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=
@ -24,7 +25,7 @@ dynamicroute:
usesupernode: true usesupernode: true
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:2999' connurlv6: '[::1]:3000'
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
@ -57,4 +58,5 @@ dynamicroute:
- time.euro.apple.com - time.euro.apple.com
- time.windows.com - time.windows.com
nexthoptable: {} nexthoptable: {}
resetconninterval: 86400
peers: [] peers: []

View File

@ -1,14 +1,15 @@
interface: interface:
itype: stdio itype: stdio
ifaceid: 2
name: tap2 name: tap2
macaddr: AA:BB:CC:DD:EE:FF vppifaceid: 2
vppbridgeid: 0
macaddrprefix: AA:BB:CC:DD:EE
mtu: 1400 mtu: 1400
recvaddr: 127.0.0.1:4002 recvaddr: 127.0.0.1:4002
sendaddr: 127.0.0.1:5002 sendaddr: 127.0.0.1:5002
devfriendly: true l2headermode: kbdbg
nodeid: 2 nodeid: 1
nodename: Node02 nodename: Node01
privkey: OH8BsVUU2Rqzeu9B2J5GPG8PUmxWfX8uVvNFZKhVF3o= privkey: OH8BsVUU2Rqzeu9B2J5GPG8PUmxWfX8uVvNFZKhVF3o=
listenport: 3002 listenport: 3002
loglevel: loglevel:
@ -24,7 +25,7 @@ dynamicroute:
usesupernode: true usesupernode: true
connurlv4: 127.0.0.1:3000 connurlv4: 127.0.0.1:3000
pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
connurlv6: '[::1]:2999' connurlv6: '[::1]:3000'
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 40 supernodeinfotimeout: 40
@ -57,4 +58,5 @@ dynamicroute:
- time.euro.apple.com - time.euro.apple.com
- time.windows.com - time.windows.com
nexthoptable: {} nexthoptable: {}
resetconninterval: 86400
peers: [] peers: []

View File

@ -2,14 +2,14 @@ nodename: NodeSuper
privkeyv4: mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk= privkeyv4: mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=
privkeyv6: +EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I= privkeyv6: +EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=
listenport: 3000 listenport: 3000
repushconfiginterval: 10
loglevel: loglevel:
loglevel: normal loglevel: normal
logtransit: true logtransit: true
logcontrol: true logcontrol: true
repushconfiginterval: 30
graphrecalculatesetting: graphrecalculatesetting:
jittertolerance: 20 jittertolerance: 5
jittertolerancemultiplier: 1.1 jittertolerancemultiplier: 1.01
nodereporttimeout: 40 nodereporttimeout: 40
recalculatecooldown: 5 recalculatecooldown: 5
peers: peers:

15
main.go
View File

@ -25,8 +25,8 @@ const (
) )
const ( const (
ENV_WP_UAPI_FD = "WP_UAPI_FD" ENV_EG_UAPI_FD = "EG_UAPI_FD"
ENV_WP_UAPI_DIR = "WP_UAPI_DIR" ENV_EG_UAPI_DIR = "EG_UAPI_DIR"
) )
func printUsage() { func printUsage() {
@ -62,20 +62,25 @@ func main() {
return return
} }
uapiDir := os.Getenv(ENV_WP_UAPI_DIR) uapiDir := os.Getenv(ENV_EG_UAPI_DIR)
if uapiDir != "" { if uapiDir != "" {
ipc.SetsocketDirectory(uapiDir) ipc.SetsocketDirectory(uapiDir)
} }
var err error
switch *mode { switch *mode {
case "edge": case "edge":
Edge(*tconfig, !*nouapi, *printExample) err = Edge(*tconfig, !*nouapi, *printExample)
case "super": case "super":
Super(*tconfig, !*nouapi, *printExample) err = Super(*tconfig, !*nouapi, *printExample)
case "path": case "path":
path.Solve() path.Solve()
default: default:
flag.Usage() flag.Usage()
} }
if err != nil {
fmt.Fprintf(os.Stderr, "Error :%v\n", err)
os.Exit(1)
}
return return
} }

View File

@ -29,13 +29,13 @@ func printExampleEdgeConf() {
tconfig := config.EdgeConfig{ tconfig := config.EdgeConfig{
Interface: config.InterfaceConf{ Interface: config.InterfaceConf{
Itype: "stdio", Itype: "stdio",
VPPIfaceID: 5, VPPIfaceID: 5,
Name: "tap1", Name: "tap1",
MacAddr: "AA:BB:CC:DD:EE:FF", MacAddrPrefix: "AA:BB:CC:DD:EE:FF",
MTU: 1400, MTU: 1400,
RecvAddr: "127.0.0.1:4001", RecvAddr: "127.0.0.1:4001",
SendAddr: "127.0.0.1:5001", SendAddr: "127.0.0.1:5001",
DevFriendly: true, L2HeaderMode: "nochg",
}, },
NodeID: 1, NodeID: 1,
NodeName: "Node01", NodeName: "Node01",
@ -44,6 +44,7 @@ func printExampleEdgeConf() {
LogLevel: config.LoggerInfo{ LogLevel: config.LoggerInfo{
LogLevel: "normal", LogLevel: "normal",
LogTransit: true, LogTransit: true,
LogControl: true,
}, },
DynamicRoute: config.DynamicRouteInfo{ DynamicRoute: config.DynamicRouteInfo{
SendPingInterval: 20, SendPingInterval: 20,
@ -53,9 +54,9 @@ func printExampleEdgeConf() {
SuperNode: config.SuperInfo{ SuperNode: config.SuperInfo{
UseSuperNode: true, UseSuperNode: true,
ConnURLV4: "127.0.0.1:3000", ConnURLV4: "127.0.0.1:3000",
PubKeyV4: "j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y=", PubKeyV4: "LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=",
ConnURLV6: "[::1]:3000", ConnURLV6: "[::1]:3000",
PubKeyV6: "cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw=", PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=",
APIUrl: "http://127.0.0.1:3000/api", APIUrl: "http://127.0.0.1:3000/api",
SuperNodeInfoTimeout: 40, SuperNodeInfoTimeout: 40,
}, },
@ -90,7 +91,8 @@ func printExampleEdgeConf() {
"time.windows.com"}, "time.windows.com"},
}, },
}, },
NextHopTable: config.NextHopTable{}, NextHopTable: config.NextHopTable{},
ResetConnInterval: 86400,
Peers: []config.PeerInfo{ Peers: []config.PeerInfo{
{ {
NodeID: 2, NodeID: 2,
@ -165,13 +167,17 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
case "dummy": case "dummy":
thetap, err = tap.CreateDummyTAP() thetap, err = tap.CreateDummyTAP()
case "stdio": case "stdio":
thetap, err = tap.CreateStdIOTAP(tconfig.Interface.Name, tconfig.Interface.DevFriendly) tconfig.Interface.VPPIfaceID = uint32(tconfig.NodeID)
thetap, err = tap.CreateStdIOTAP(tconfig.Interface)
case "udpsock": case "udpsock":
{ tconfig.Interface.VPPIfaceID = uint32(tconfig.NodeID)
lis, _ := net.ResolveUDPAddr("udp", tconfig.Interface.RecvAddr) lis, _ := net.ResolveUDPAddr("udp", tconfig.Interface.RecvAddr)
sen, _ := net.ResolveUDPAddr("udp", tconfig.Interface.SendAddr) sen, _ := net.ResolveUDPAddr("udp", tconfig.Interface.SendAddr)
thetap, err = tap.CreateUDPSockTAP(tconfig.Interface.Name, lis, sen, tconfig.Interface.DevFriendly) thetap, err = tap.CreateUDPSockTAP(tconfig.Interface, lis, sen)
} case "vpp":
thetap, err = tap.CreateVppTAP(tconfig.Interface, tconfig.LogLevel.LogLevel)
default:
return errors.New("Unknow interface type:" + tconfig.Interface.Itype)
} }
if err != nil { if err != nil {
logger.Errorf("Failed to create TAP device: %v", err) logger.Errorf("Failed to create TAP device: %v", err)
@ -206,6 +212,8 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err) logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err)
return err return err
} }
peer.StaticConn = peerconf.Static
peer.ConnURL = peerconf.EndPoint
peer.SetEndpointFromPacket(endpoint) peer.SetEndpointFromPacket(endpoint)
} }
} }
@ -222,6 +230,8 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
if err != nil { if err != nil {
return err return err
} }
peer.StaticConn = false
peer.ConnURL = tconfig.DynamicRoute.SuperNode.ConnURLV4
peer.SetEndpointFromPacket(endpoint) peer.SetEndpointFromPacket(endpoint)
} }
if tconfig.DynamicRoute.SuperNode.ConnURLV6 != "" { if tconfig.DynamicRoute.SuperNode.ConnURLV6 != "" {
@ -235,6 +245,8 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
if err != nil { if err != nil {
return err return err
} }
peer.StaticConn = false
peer.ConnURL = tconfig.DynamicRoute.SuperNode.ConnURLV6
peer.SetEndpointFromPacket(endpoint) peer.SetEndpointFromPacket(endpoint)
} }
} }

View File

@ -34,13 +34,15 @@ import (
func printExampleSuperConf() { func printExampleSuperConf() {
sconfig := config.SuperConfig{ sconfig := config.SuperConfig{
NodeName: "NodeSuper", NodeName: "NodeSuper",
PrivKeyV4: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=", PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=",
PrivKeyV6: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=", PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=",
ListenPort: 3000, ListenPort: 3000,
LogLevel: config.LoggerInfo{ LogLevel: config.LoggerInfo{
LogLevel: "normal", LogLevel: "normal",
LogTransit: true, LogTransit: true,
LogControl: true,
}, },
RePushConfigInterval: 30,
Peers: []config.PeerInfo{ Peers: []config.PeerInfo{
{ {
NodeID: 2, NodeID: 2,
@ -50,8 +52,8 @@ func printExampleSuperConf() {
}, },
}, },
GraphRecalculateSetting: config.GraphRecalculateSetting{ GraphRecalculateSetting: config.GraphRecalculateSetting{
JitterTolerance: 20, JitterTolerance: 5,
JitterToleranceMultiplier: 1.1, JitterToleranceMultiplier: 1.01,
NodeReportTimeout: 40, NodeReportTimeout: 40,
RecalculateCoolDown: 5, RecalculateCoolDown: 5,
}, },
@ -70,8 +72,7 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
var sconfig config.SuperConfig var sconfig config.SuperConfig
err = readYaml(configPath, &sconfig) err = readYaml(configPath, &sconfig)
if err != nil { if err != nil {
fmt.Printf("Error read config: %s :", configPath) fmt.Printf("Error read config: %v\n", configPath)
fmt.Print(err)
return err return err
} }
interfaceName := sconfig.NodeName interfaceName := sconfig.NodeName
@ -107,21 +108,29 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
thetap, _ := tap.CreateDummyTAP() thetap, _ := tap.CreateDummyTAP()
http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting) http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting)
http_device4 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(true, false), logger4, http_graph, true, "", nil, &sconfig, &super_chains) http_device4 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(true, false), logger4, http_graph, true, configPath, nil, &sconfig, &super_chains)
http_device6 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(false, true), logger6, http_graph, true, "", nil, &sconfig, &super_chains) http_device6 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(false, true), logger6, http_graph, true, configPath, nil, &sconfig, &super_chains)
defer http_device4.Close() defer http_device4.Close()
defer http_device6.Close() defer http_device6.Close()
var sk [32]byte var sk [32]byte
sk_slice, _ := base64.StdEncoding.DecodeString(sconfig.PrivKeyV4) sk_slice, err := base64.StdEncoding.DecodeString(sconfig.PrivKeyV4)
if err != nil {
fmt.Printf("Can't decode base64:%v\n", sconfig.PrivKeyV4)
return err
}
copy(sk[:], sk_slice) copy(sk[:], sk_slice)
http_device4.SetPrivateKey(sk) http_device4.SetPrivateKey(sk)
sk_slice, _ = base64.StdEncoding.DecodeString(sconfig.PrivKeyV6) sk_slice, err = base64.StdEncoding.DecodeString(sconfig.PrivKeyV6)
if err != nil {
fmt.Printf("Can't decode base64:%v\n", sconfig.PrivKeyV6)
return err
}
copy(sk[:], sk_slice) copy(sk[:], sk_slice)
http_device6.SetPrivateKey(sk) http_device6.SetPrivateKey(sk)
http_device4.IpcSet("fwmark=0\n") http_device4.IpcSet("fwmark=0\n")
http_device6.IpcSet("fwmark=0\n") http_device6.IpcSet("fwmark=0\n")
http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort-1) + "\n") http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
http_device4.IpcSet("replace_peers=true\n") http_device4.IpcSet("replace_peers=true\n")
http_device6.IpcSet("replace_peers=true\n") http_device6.IpcSet("replace_peers=true\n")
@ -143,8 +152,20 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
PSKey: peerconf.PSKey, PSKey: peerconf.PSKey,
Connurl: make(map[string]bool), Connurl: make(map[string]bool),
} }
peer4, _ := http_device4.NewPeer(pk, peerconf.NodeID) peer4, err := http_device4.NewPeer(pk, peerconf.NodeID)
peer6, _ := http_device6.NewPeer(pk, peerconf.NodeID) if err != nil {
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
return err
}
peer4.StaticConn = true
peer4.ConnURL = peerconf.EndPoint
peer6, err := http_device6.NewPeer(pk, peerconf.NodeID)
if err != nil {
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
return err
}
peer6.StaticConn = true
peer6.ConnURL = peerconf.EndPoint
if peerconf.PSKey != "" { if peerconf.PSKey != "" {
var psk device.NoisePresharedKey var psk device.NoisePresharedKey
psk_slice, err := base64.StdEncoding.DecodeString(peerconf.PSKey) psk_slice, err := base64.StdEncoding.DecodeString(peerconf.PSKey)
@ -306,7 +327,7 @@ func PushUpdate() {
func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) { func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) {
fileUAPI, err := func() (*os.File, error) { fileUAPI, err := func() (*os.File, error) {
uapiFdStr := os.Getenv(ENV_WP_UAPI_FD) uapiFdStr := os.Getenv(ENV_EG_UAPI_FD)
if uapiFdStr == "" { if uapiFdStr == "" {
return ipc.UAPIOpen(interfaceName) return ipc.UAPIOpen(interfaceName)
} }
@ -317,10 +338,14 @@ func startUAPI(interfaceName string, logger *device.Logger, the_device *device.D
} }
return os.NewFile(uintptr(fd), ""), nil return os.NewFile(uintptr(fd), ""), nil
}() }()
if err != nil {
fmt.Printf("Error create UAPI socket \n")
return nil, err
}
uapi, err := ipc.UAPIListen(interfaceName, fileUAPI) uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
if err != nil { if err != nil {
logger.Errorf("Failed to listen on uapi socket: %v", err) logger.Errorf("Failed to listen on uapi socket: %v", err)
os.Exit(ExitSetupFailed) return nil, err
} }
go func() { go func() {

View File

@ -79,22 +79,29 @@ func NewGraph(num_node int, IsSuperMode bool, theconfig config.GraphRecalculateS
return &g return &g
} }
func (g *IG) GetWeightType(x float64) float64 { func (g *IG) GetWeightType(x float64) (y float64) {
x = math.Abs(x) x = math.Abs(x)
y := x y = x
if g.JitterTolerance > 1 && g.JitterToleranceMultiplier > 0.001 { if g.JitterTolerance > 0.001 && g.JitterToleranceMultiplier > 1 {
r := g.JitterTolerance t := g.JitterTolerance
m := g.JitterToleranceMultiplier r := g.JitterToleranceMultiplier
y = math.Pow(math.Ceil(math.Pow(x/m, 1/r)), r) * m y = math.Pow(math.Ceil(math.Pow(x/t, 1/r)), r) * t
} }
return y return y
} }
func (g *IG) ShouldUpdate(u config.Vertex, v config.Vertex, newval float64) bool { func (g *IG) ShouldUpdate(u config.Vertex, v config.Vertex, newval float64) bool {
oldval := g.Weight(u, v) * 1000 oldval := math.Abs(g.Weight(u, v) * 1000)
newval *= 1000 newval = math.Abs(newval * 1000)
if g.IsSuperMode { if g.IsSuperMode {
return (oldval-newval)*(oldval*g.JitterToleranceMultiplier) >= g.JitterTolerance if g.JitterTolerance > 0.001 && g.JitterToleranceMultiplier >= 1 {
diff := math.Abs(newval - oldval)
x := math.Max(oldval, newval)
t := g.JitterTolerance
r := g.JitterToleranceMultiplier
return diff > t+x*(r-1) // https://www.desmos.com/calculator/raoti16r5n
}
return oldval == newval
} else { } else {
return g.GetWeightType(oldval) == g.GetWeightType(newval) return g.GetWeightType(oldval) == g.GetWeightType(newval)
} }

View File

@ -6,7 +6,10 @@
package tap package tap
import ( import (
"bytes" "encoding/binary"
"errors"
"strconv"
"strings"
) )
type Event int type Event int
@ -22,13 +25,44 @@ func GetSrcMacAddr(packet []byte) (srcMacAddr MacAddress) {
return return
} }
func IsBoardCast(mac_in MacAddress) bool { func GetMacAddr(prefix string, uid uint32) (mac MacAddress, err error) {
if bytes.Equal(mac_in[:], []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) { macprefix, _, err := prefixStr2prefix(prefix)
return true if err != nil {
} else if bytes.Equal(mac_in[0:2], []byte{0x33, 0x33}) { return
return true
} }
return false idbuf := make([]byte, 4)
binary.BigEndian.PutUint32(idbuf, uid)
copy(mac[2:], idbuf)
copy(mac[:], macprefix)
if IsNotUnicast(mac) {
err = errors.New("ERROR: MAC address can only set to unicast address")
return
}
return
}
func prefixStr2prefix(prefix string) ([]uint8, uint32, error) {
hexStrs := strings.Split(strings.ToLower(prefix), ":")
retprefix := make([]uint8, len(hexStrs))
maxID := uint32(1)<<((6-len(hexStrs))*8) - 1
if len(hexStrs) < 2 || len(hexStrs) > 6 {
return []uint8{}, 0, errors.New("Macaddr prefix length must between 2 and 6, " + prefix + " is " + strconv.Itoa(len(hexStrs)))
}
for index, hexstr := range hexStrs {
value, err := strconv.ParseInt(hexstr, 16, 16)
if err != nil {
return []uint8{}, 0, err
}
retprefix[index] = uint8(value)
}
return retprefix, maxID, nil
}
func IsNotUnicast(mac_in MacAddress) bool {
if mac_in[0]&1 == 0 { // Is unicast
return false
}
return true
} }
const ( const (

529
tap/tap_linux.go Normal file
View File

@ -0,0 +1,529 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
*/
package tap
/* Implementation of the TUN device interface for linux
*/
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"os"
"sync"
"syscall"
"time"
"unsafe"
"golang.org/x/sys/unix"
"github.com/KusakabeSi/EtherGuardVPN/config"
"github.com/KusakabeSi/EtherGuardVPN/rwcancel"
)
const (
cloneDevicePath = "/dev/net/tun"
ifReqSize = unix.IFNAMSIZ + 64
)
type NativeTap struct {
tapFile *os.File
index int32 // if index
errors chan error // async error handling
events chan Event // device related events
nopi bool // the device was passed IFF_NO_PI
netlinkSock int
netlinkCancel *rwcancel.RWCancel
hackListenerClosed sync.Mutex
statusListenersShutdown chan struct{}
closeOnce sync.Once
nameOnce sync.Once // guards calling initNameCache, which sets following fields
nameCache string // name of interface
nameErr error
}
func (tap *NativeTap) File() *os.File {
return tap.tapFile
}
func (tap *NativeTap) routineHackListener() {
defer tap.hackListenerClosed.Unlock()
/* This is needed for the detection to work across network namespaces
* If you are reading this and know a better method, please get in touch.
*/
last := 0
const (
up = 1
down = 2
)
for {
sysconn, err := tap.tapFile.SyscallConn()
if err != nil {
return
}
err2 := sysconn.Control(func(fd uintptr) {
_, err = unix.Write(int(fd), nil)
})
if err2 != nil {
return
}
switch err {
case unix.EINVAL:
if last != up {
// If the tunnel is up, it reports that write() is
// allowed but we provided invalid data.
tap.events <- EventUp
last = up
}
case unix.EIO:
if last != down {
// If the tunnel is down, it reports that no I/O
// is possible, without checking our provided data.
tap.events <- EventDown
last = down
}
default:
return
}
select {
case <-time.After(time.Second):
// nothing
case <-tap.statusListenersShutdown:
return
}
}
}
func createNetlinkSocket() (int, error) {
sock, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, unix.NETLINK_ROUTE)
if err != nil {
return -1, err
}
saddr := &unix.SockaddrNetlink{
Family: unix.AF_NETLINK,
Groups: unix.RTMGRP_LINK | unix.RTMGRP_IPV4_IFADDR | unix.RTMGRP_IPV6_IFADDR,
}
err = unix.Bind(sock, saddr)
if err != nil {
return -1, err
}
return sock, nil
}
func (tap *NativeTap) routineNetlinkListener() {
defer func() {
unix.Close(tap.netlinkSock)
tap.hackListenerClosed.Lock()
close(tap.events)
tap.netlinkCancel.Close()
}()
for msg := make([]byte, 1<<16); ; {
var err error
var msgn int
for {
msgn, _, _, _, err = unix.Recvmsg(tap.netlinkSock, msg[:], nil, 0)
if err == nil || !rwcancel.RetryAfterError(err) {
break
}
if !tap.netlinkCancel.ReadyRead() {
tap.errors <- fmt.Errorf("netlink socket closed: %w", err)
return
}
}
if err != nil {
tap.errors <- fmt.Errorf("failed to receive netlink message: %w", err)
return
}
select {
case <-tap.statusListenersShutdown:
return
default:
}
wasEverUp := false
for remain := msg[:msgn]; len(remain) >= unix.SizeofNlMsghdr; {
hdr := *(*unix.NlMsghdr)(unsafe.Pointer(&remain[0]))
if int(hdr.Len) > len(remain) {
break
}
switch hdr.Type {
case unix.NLMSG_DONE:
remain = []byte{}
case unix.RTM_NEWLINK:
info := *(*unix.IfInfomsg)(unsafe.Pointer(&remain[unix.SizeofNlMsghdr]))
remain = remain[hdr.Len:]
if info.Index != tap.index {
// not our interface
continue
}
if info.Flags&unix.IFF_RUNNING != 0 {
tap.events <- EventUp
wasEverUp = true
}
if info.Flags&unix.IFF_RUNNING == 0 {
// Don't emit EventDown before we've ever emitted EventUp.
// This avoids a startup race with HackListener, which
// might detect Up before we have finished reporting Down.
if wasEverUp {
tap.events <- EventDown
}
}
tap.events <- EventMTUUpdate
default:
remain = remain[hdr.Len:]
}
}
}
}
func (tap *NativeTap) setMacAddr(mac MacAddress) (err error) {
fd, err := unix.Socket(
unix.AF_INET,
unix.SOCK_DGRAM,
0,
)
if err != nil {
return err
}
defer unix.Close(fd)
var ifr [ifReqSize]byte
name, err := tap.Name()
if err != nil {
return err
}
/*
ifreq = struct.pack('16sH6B8x', self.name, AF_UNIX, *macbytes)
fcntl.ioctl(sockfd, SIOCSIFHWADDR, ifreq)
*/
copy(ifr[:16], name)
binary.BigEndian.PutUint16(ifr[16:18], unix.AF_UNIX)
copy(ifr[18:24], mac[:])
copy(ifr[24:32], make([]byte, 8))
_, _, err = unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.SIOCSIFHWADDR),
uintptr(unsafe.Pointer(&ifr[0])),
)
return
}
func getIFIndex(name string) (int32, error) {
fd, err := unix.Socket(
unix.AF_INET,
unix.SOCK_DGRAM,
0,
)
if err != nil {
return 0, err
}
defer unix.Close(fd)
var ifr [ifReqSize]byte
copy(ifr[:], name)
_, _, errno := unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.SIOCGIFINDEX),
uintptr(unsafe.Pointer(&ifr[0])),
)
if errno != 0 {
return 0, errno
}
return *(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])), nil
}
func (tap *NativeTap) setMTU(n int) error {
name, err := tap.Name()
if err != nil {
return err
}
// open datagram socket
fd, err := unix.Socket(
unix.AF_INET,
unix.SOCK_DGRAM,
0,
)
if err != nil {
return err
}
defer unix.Close(fd)
// do ioctl call
var ifr [ifReqSize]byte
copy(ifr[:], name)
*(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n)
_, _, errno := unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.SIOCSIFMTU),
uintptr(unsafe.Pointer(&ifr[0])),
)
if errno != 0 {
return fmt.Errorf("failed to set MTU of TUN device: %w", errno)
}
return nil
}
func (tap *NativeTap) MTU() (int, error) {
name, err := tap.Name()
if err != nil {
return 0, err
}
// open datagram socket
fd, err := unix.Socket(
unix.AF_INET,
unix.SOCK_DGRAM,
0,
)
if err != nil {
return 0, err
}
defer unix.Close(fd)
// do ioctl call
var ifr [ifReqSize]byte
copy(ifr[:], name)
_, _, errno := unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.SIOCGIFMTU),
uintptr(unsafe.Pointer(&ifr[0])),
)
if errno != 0 {
return 0, fmt.Errorf("failed to get MTU of TUN device: %w", errno)
}
return int(*(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ]))), nil
}
func (tap *NativeTap) Name() (string, error) {
tap.nameOnce.Do(tap.initNameCache)
return tap.nameCache, tap.nameErr
}
func (tap *NativeTap) initNameCache() {
tap.nameCache, tap.nameErr = tap.nameSlow()
}
func (tap *NativeTap) nameSlow() (string, error) {
sysconn, err := tap.tapFile.SyscallConn()
if err != nil {
return "", err
}
var ifr [ifReqSize]byte
var errno syscall.Errno
err = sysconn.Control(func(fd uintptr) {
_, _, errno = unix.Syscall(
unix.SYS_IOCTL,
fd,
uintptr(unix.TUNGETIFF),
uintptr(unsafe.Pointer(&ifr[0])),
)
})
if err != nil {
return "", fmt.Errorf("failed to get name of TUN device: %w", err)
}
if errno != 0 {
return "", fmt.Errorf("failed to get name of TUN device: %w", errno)
}
name := ifr[:]
if i := bytes.IndexByte(name, 0); i != -1 {
name = name[:i]
}
return string(name), nil
}
func (tap *NativeTap) Write(buf []byte, offset int) (int, error) {
buf = buf[offset:]
n, err := tap.tapFile.Write(buf)
if errors.Is(err, syscall.EBADFD) {
err = os.ErrClosed
}
return n, err
}
func (tap *NativeTap) Flush() error {
// TODO: can flushing be implemented by buffering and using sendmmsg?
return nil
}
func (tap *NativeTap) Read(buf []byte, offset int) (n int, err error) {
select {
case err = <-tap.errors:
default:
n, err = tap.tapFile.Read(buf[offset:])
if errors.Is(err, syscall.EBADFD) {
err = os.ErrClosed
}
}
return
}
func (tap *NativeTap) Events() chan Event {
return tap.events
}
func (tap *NativeTap) Close() error {
var err1, err2 error
tap.closeOnce.Do(func() {
if tap.statusListenersShutdown != nil {
close(tap.statusListenersShutdown)
if tap.netlinkCancel != nil {
err1 = tap.netlinkCancel.Cancel()
}
} else if tap.events != nil {
close(tap.events)
}
err2 = tap.tapFile.Close()
})
if err1 != nil {
return err1
}
return err2
}
func CreateTAP(iconfig config.InterfaceConf) (Device, error) {
nfd, err := unix.Open(cloneDevicePath, os.O_RDWR, 0)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("CreateTAP(%q) failed; %s does not exist", iconfig.Name, cloneDevicePath)
}
return nil, err
}
var ifr [ifReqSize]byte
var flags uint16 = unix.IFF_TAP | unix.IFF_NO_PI // (disabled for TUN status hack)
if err != nil {
fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
return nil, err
}
nameBytes := []byte(iconfig.Name)
if len(nameBytes) >= unix.IFNAMSIZ {
return nil, fmt.Errorf("interface name too long: %w", unix.ENAMETOOLONG)
}
copy(ifr[:], nameBytes)
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
_, _, errno := unix.Syscall(
unix.SYS_IOCTL,
uintptr(nfd),
uintptr(unix.TUNSETIFF),
uintptr(unsafe.Pointer(&ifr[0])),
)
if errno != 0 {
return nil, errno
}
err = unix.SetNonblock(nfd, true)
// Note that the above -- open,ioctl,nonblock -- must happen prior to handing it to netpoll as below this line.
fd := os.NewFile(uintptr(nfd), cloneDevicePath)
if err != nil {
return nil, err
}
return CreateTAPFromFile(fd, iconfig)
}
func CreateTAPFromFile(file *os.File, iconfig config.InterfaceConf) (Device, error) {
tap := &NativeTap{
tapFile: file,
events: make(chan Event, 5),
errors: make(chan error, 5),
statusListenersShutdown: make(chan struct{}),
nopi: false,
}
name, err := tap.Name()
if err != nil {
return nil, err
}
// start event listener
tap.index, err = getIFIndex(name)
if err != nil {
return nil, err
}
tap.netlinkSock, err = createNetlinkSocket()
if err != nil {
return nil, err
}
tap.netlinkCancel, err = rwcancel.NewRWCancel(tap.netlinkSock)
if err != nil {
unix.Close(tap.netlinkSock)
return nil, err
}
tap.hackListenerClosed.Lock()
go tap.routineNetlinkListener()
go tap.routineHackListener() // cross namespace
err = tap.setMTU(iconfig.MTU)
if err != nil {
unix.Close(tap.netlinkSock)
return nil, err
}
IfMacAddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID)
if err != nil {
fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
return nil, err
}
err = tap.setMacAddr(IfMacAddr)
if err != nil {
unix.Close(tap.netlinkSock)
return nil, err
}
return tap, nil
}
func CreateUnmonitoredTUNFromFD(fd int) (Device, string, error) {
err := unix.SetNonblock(fd, true)
if err != nil {
return nil, "", err
}
file := os.NewFile(uintptr(fd), "/dev/tap")
tap := &NativeTap{
tapFile: file,
events: make(chan Event, 5),
errors: make(chan error, 5),
nopi: true,
}
name, err := tap.Name()
if err != nil {
return nil, "", err
}
return tap, name, nil
}

View File

@ -3,42 +3,71 @@ package tap
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/KusakabeSi/EtherGuardVPN/config"
) )
type L2MODE uint8
const (
NoChange L2MODE = iota
KeyboardDebug //Register to server
BoardcastAndNodeID
)
func GetL2Mode(mode string) L2MODE {
switch mode {
case "nochg":
return NoChange
case "kbdbg":
return KeyboardDebug
case "noL2":
return BoardcastAndNodeID
}
return NoChange
}
type StdIOTap struct { type StdIOTap struct {
name string name string
mtu int mtu int
HumanFriendly bool macaddr MacAddress
events chan Event L2mode L2MODE
events chan Event
} }
func Charform2mac(b byte) MacAddress { func Charform2mac(b byte) MacAddress {
if b == 'b' { if b == 'b' {
return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
} }
return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, b - 48} return MacAddress{0x00, 0x11, 0xff, 0xff, 0xff, b - 48}
} }
func Mac2charForm(m []byte) byte { func Mac2charForm(m []byte) byte {
var M MacAddress var M MacAddress
copy(M[:], m) copy(M[:], m)
if IsBoardCast(M) { if IsNotUnicast(M) {
return 'b' return 'b'
} }
return m[5] + 48 return m[5] + 48
} }
// New creates and returns a new TUN interface for the application. // New creates and returns a new TUN interface for the application.
func CreateStdIOTAP(interfaceName string, HumanFriendly bool) (tapdev Device, err error) { func CreateStdIOTAP(iconfig config.InterfaceConf) (tapdev Device, err error) {
// Setup TUN Config // Setup TUN Config
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
macaddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID)
if err != nil {
fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
return nil, err
}
tapdev = &StdIOTap{ tapdev = &StdIOTap{
name: interfaceName, name: iconfig.Name,
mtu: 1500, mtu: 1500,
HumanFriendly: HumanFriendly, macaddr: macaddr,
events: make(chan Event, 1<<5), L2mode: GetL2Mode(iconfig.L2HeaderMode),
events: make(chan Event, 1<<5),
} }
tapdev.Events() <- EventUp tapdev.Events() <- EventUp
return return
@ -48,7 +77,8 @@ func CreateStdIOTAP(interfaceName string, HumanFriendly bool) (tapdev Device, er
// Packet on the interface. // Packet on the interface.
func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) { func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) {
if tap.HumanFriendly { switch tap.L2mode {
case KeyboardDebug:
size, err := os.Stdin.Read(buf[offset+10:]) size, err := os.Stdin.Read(buf[offset+10:])
packet := buf[offset:] packet := buf[offset:]
src := Charform2mac(packet[11]) src := Charform2mac(packet[11])
@ -56,22 +86,36 @@ func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) {
copy(packet[0:6], dst[:]) copy(packet[0:6], dst[:])
copy(packet[6:12], src[:]) copy(packet[6:12], src[:])
return size - 2 + 12, err return size - 2 + 12, err
} else { case BoardcastAndNodeID:
size, err := os.Stdin.Read(buf[offset+12:])
packet := buf[offset:]
src := tap.macaddr
dst := Charform2mac('b')
copy(packet[0:6], dst[:])
copy(packet[6:12], src[:])
return size + 12, err
default:
size, err := os.Stdin.Read(buf[offset:]) size, err := os.Stdin.Read(buf[offset:])
return size, err return size, err
} }
} // read a packet from the device (without any additional headers) } // read a packet from the device (without any additional headers)
func (tap *StdIOTap) Write(buf []byte, offset int) (size int, err error) { func (tap *StdIOTap) Write(buf []byte, offset int) (size int, err error) {
packet := buf[offset:] packet := buf[offset:]
if tap.HumanFriendly { switch tap.L2mode {
case KeyboardDebug:
src := Mac2charForm(packet[6:12]) src := Mac2charForm(packet[6:12])
dst := Mac2charForm(packet[0:6]) dst := Mac2charForm(packet[0:6])
packet[10] = dst packet[10] = dst
packet[11] = src packet[11] = src
packet = packet[10:] size, err = os.Stdout.Write(packet[10:])
return
case BoardcastAndNodeID:
size, err = os.Stdout.Write(packet[12:])
return
default:
size, err = os.Stdout.Write(packet)
return
} }
size, err = os.Stdout.Write(packet)
return
} // writes a packet to the device (without any additional headers) } // writes a packet to the device (without any additional headers)
func (tap *StdIOTap) Flush() error { func (tap *StdIOTap) Flush() error {
return nil return nil

View File

@ -3,32 +3,41 @@ package tap
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/KusakabeSi/EtherGuardVPN/config"
) )
type UdpSockTap struct { type UdpSockTap struct {
name string name string
mtu int mtu int
recv *net.UDPConn recv *net.UDPConn
send *net.UDPAddr send *net.UDPAddr
HumanFriendly bool L2mode L2MODE
events chan Event macaddr MacAddress
events chan Event
} }
// New creates and returns a new TUN interface for the application. // 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) { func CreateUDPSockTAP(iconfig config.InterfaceConf, listenAddr *net.UDPAddr, sendAddr *net.UDPAddr) (tapdev Device, err error) {
// Setup TUN Config // Setup TUN Config
listener, err := net.ListenUDP("udp", listenAddr) listener, err := net.ListenUDP("udp", listenAddr)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
macaddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID)
if err != nil {
fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
return nil, err
}
tapdev = &UdpSockTap{ tapdev = &UdpSockTap{
name: interfaceName, name: iconfig.Name,
mtu: 1500, mtu: 1500,
recv: listener, recv: listener,
send: sendAddr, send: sendAddr,
HumanFriendly: HumanFriendly, macaddr: macaddr,
events: make(chan Event, 1<<5), L2mode: GetL2Mode(iconfig.L2HeaderMode),
events: make(chan Event, 1<<5),
} }
tapdev.Events() <- EventUp tapdev.Events() <- EventUp
return return
@ -38,15 +47,24 @@ func CreateUDPSockTAP(interfaceName string, listenAddr *net.UDPAddr, sendAddr *n
// Packet on the interface. // Packet on the interface.
func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) { func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) {
if tap.HumanFriendly { switch tap.L2mode {
case KeyboardDebug:
size, _, err := tap.recv.ReadFromUDP(buf[offset+10:]) size, _, err := tap.recv.ReadFromUDP(buf[offset+10:])
packet := buf[offset:] packet := buf[offset:]
src := Charform2mac(packet[11]) src := Charform2mac(packet[11])
dst := Charform2mac(packet[10]) dst := Charform2mac(packet[10])
copy(packet[0:6], dst[:]) copy(packet[0:6], dst[:])
copy(packet[6:12], src[:]) copy(packet[6:12], src[:])
return size - 2 + 12, err return size + 10, err
} else { case BoardcastAndNodeID:
size, _, err := tap.recv.ReadFromUDP(buf[offset+12:])
packet := buf[offset:]
src := tap.macaddr
dst := Charform2mac('b')
copy(packet[0:6], dst[:])
copy(packet[6:12], src[:])
return size + 12, err
default:
size, _, err := tap.recv.ReadFromUDP(buf[offset:]) size, _, err := tap.recv.ReadFromUDP(buf[offset:])
return size, err return size, err
} }
@ -54,16 +72,21 @@ func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) {
} // read a packet from the device (without any additional headers) } // read a packet from the device (without any additional headers)
func (tap *UdpSockTap) Write(buf []byte, offset int) (size int, err error) { func (tap *UdpSockTap) Write(buf []byte, offset int) (size int, err error) {
packet := buf[offset:] packet := buf[offset:]
if tap.HumanFriendly { switch tap.L2mode {
case KeyboardDebug:
src := Mac2charForm(packet[6:12]) src := Mac2charForm(packet[6:12])
dst := Mac2charForm(packet[0:6]) dst := Mac2charForm(packet[0:6])
packet[10] = dst packet[10] = dst
packet[11] = src packet[11] = src
size, err = tap.recv.WriteToUDP(packet[10:], tap.send) size, err = tap.recv.WriteToUDP(packet[10:], tap.send)
return return
case BoardcastAndNodeID:
size, err = tap.recv.WriteToUDP(packet[12:], tap.send)
return
default:
size, err = tap.recv.WriteToUDP(packet, tap.send)
return
} }
size, err = tap.recv.WriteToUDP(packet, tap.send)
return
} // writes a packet to the device (without any additional headers) } // writes a packet to the device (without any additional headers)
func (tap *UdpSockTap) Flush() error { func (tap *UdpSockTap) Flush() error {
return nil return nil

View File

@ -2,6 +2,7 @@ package tap
import ( import (
"context" "context"
"path"
"errors" "errors"
"fmt" "fmt"
@ -58,7 +59,7 @@ type VppTap struct {
} }
// New creates and returns a new TUN interface for the application. // New creates and returns a new TUN interface for the application.
func CreateVppTAP(interfaceName string, iconfig config.InterfaceConf, loglevel string) (tapdev Device, err error) { func CreateVppTAP(iconfig config.InterfaceConf, loglevel string) (tapdev Device, err error) {
// Setup TUN Config // Setup TUN Config
// Set logger // Set logger
log := logger.New() log := logger.New()
@ -75,10 +76,20 @@ func CreateVppTAP(interfaceName string, iconfig config.InterfaceConf, loglevel s
return logger.ErrorLevel return logger.ErrorLevel
}() }()
libmemif.SetLogger(log) libmemif.SetLogger(log)
if os.Getenv(ENV_VPP_MEMIF_SOCKET_DIR) != "" {
vppMemifSocketDir = os.Getenv(ENV_VPP_MEMIF_SOCKET_DIR)
}
if os.Getenv(ENV_VPP_SOCKET_PATH) != "" {
vppApiSocketPath = os.Getenv(ENV_VPP_SOCKET_PATH)
}
if err := os.MkdirAll(vppMemifSocketDir, 0755); err != nil {
log.Fatalln("ERROR: Failed to create VPP memif socket folder " + vppMemifSocketDir)
return nil, err
}
// connect to VPP // connect to VPP
conn, err := govpp.Connect(vppApiSocketPath) conn, err := govpp.Connect(vppApiSocketPath)
if err != nil { if err != nil {
log.Fatalln("ERROR: connecting to VPP failed:", err) log.Fatalln("ERROR: Connecting to VPP failed:", err)
return nil, err return nil, err
} }
defer conn.Disconnect() defer conn.Disconnect()
@ -105,18 +116,19 @@ func CreateVppTAP(interfaceName string, iconfig config.InterfaceConf, loglevel s
l2service := l2.NewServiceClient(conn) l2service := l2.NewServiceClient(conn)
interfacservice := interfaces.NewServiceClient(conn) interfacservice := interfaces.NewServiceClient(conn)
vppIfMacAddr, err := ethernet_types.ParseMacAddress(iconfig.MacAddr) IfMacAddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID)
if err != nil { if err != nil {
log.Fatalln("ERROR: Failed parse mac address:", iconfig.MacAddr) log.Fatalln("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
return nil, err return nil, err
} }
vppIfMacAddr := ethernet_types.MacAddress(IfMacAddr)
tap := &VppTap{ tap := &VppTap{
name: iconfig.Name, name: iconfig.Name,
mtu: iconfig.MTU, mtu: iconfig.MTU,
ifuid: iconfig.VPPIfaceID, ifuid: iconfig.VPPIfaceID,
SwIfIndex: 0, SwIfIndex: 0,
memifSockPath: vppMemifSocketDir + "/" + iconfig.Name, memifSockPath: path.Join(vppMemifSocketDir, iconfig.Name+".sock"),
secret: config.RandomStr(16, iconfig.Name), secret: config.RandomStr(16, iconfig.Name),
logger: log, logger: log,
errors: make(chan error, 1<<5), errors: make(chan error, 1<<5),