2017-12-29 04:16:20 +00:00
|
|
|
package yggdrasil
|
|
|
|
|
|
|
|
// These are functions that should not exist
|
|
|
|
// They are (or were) used during development, to work around missing features
|
|
|
|
// They're also used to configure things from the outside
|
|
|
|
// It would be better to define and export a few config functions elsewhere
|
|
|
|
// Or define some remote API and call it to send/request configuration info
|
|
|
|
|
|
|
|
import _ "golang.org/x/net/ipv6" // TODO put this somewhere better
|
|
|
|
|
2018-04-26 14:23:21 +00:00
|
|
|
import "golang.org/x/net/proxy"
|
|
|
|
|
2017-12-29 04:16:20 +00:00
|
|
|
import "fmt"
|
|
|
|
import "net"
|
2018-04-26 14:23:21 +00:00
|
|
|
import "net/url"
|
2017-12-29 04:16:20 +00:00
|
|
|
import "log"
|
2018-04-26 14:23:21 +00:00
|
|
|
import "strings"
|
2018-01-09 08:08:54 +00:00
|
|
|
import "regexp"
|
2017-12-29 04:16:20 +00:00
|
|
|
|
|
|
|
// Core
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getSigPub() sigPubKey {
|
2018-01-04 22:37:51 +00:00
|
|
|
return (sigPubKey)(c.sigPub)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getBoxPub() boxPubKey {
|
2018-01-04 22:37:51 +00:00
|
|
|
return (boxPubKey)(c.boxPub)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-04 22:37:51 +00:00
|
|
|
func (c *Core) DEBUG_getSend() chan<- []byte {
|
|
|
|
return c.tun.send
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-04 22:37:51 +00:00
|
|
|
func (c *Core) DEBUG_getRecv() <-chan []byte {
|
|
|
|
return c.tun.recv
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Peer
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getPeers() *peers {
|
2018-01-04 22:37:51 +00:00
|
|
|
return &c.peers
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *peers) DEBUG_newPeer(box boxPubKey,
|
2018-01-04 22:37:51 +00:00
|
|
|
sig sigPubKey) *peer {
|
|
|
|
//in <-chan []byte,
|
|
|
|
//out chan<- []byte) *peer {
|
|
|
|
return ps.newPeer(&box, &sig) //, in, out)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (ps *peers) DEBUG_startPeers() {
|
|
|
|
ps.mutex.RLock()
|
|
|
|
defer ps.mutex.RUnlock()
|
|
|
|
for _, p := range ps.ports {
|
|
|
|
if p == nil { continue }
|
|
|
|
go p.MainLoop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
func (ps *peers) DEBUG_hasPeer(key sigPubKey) bool {
|
2018-01-04 22:37:51 +00:00
|
|
|
ports := ps.ports.Load().(map[switchPort]*peer)
|
|
|
|
for _, p := range ports {
|
|
|
|
if p == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if p.sig == key {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *peers) DEBUG_getPorts() map[switchPort]*peer {
|
2018-01-04 22:37:51 +00:00
|
|
|
ports := ps.ports.Load().(map[switchPort]*peer)
|
|
|
|
newPeers := make(map[switchPort]*peer)
|
|
|
|
for port, p := range ports {
|
|
|
|
newPeers[port] = p
|
|
|
|
}
|
|
|
|
return newPeers
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *peer) DEBUG_getSigKey() sigPubKey {
|
2018-01-04 22:37:51 +00:00
|
|
|
return p.sig
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *peer) DEEBUG_getPort() switchPort {
|
2018-01-04 22:37:51 +00:00
|
|
|
return p.port
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Router
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getSwitchTable() *switchTable {
|
2018-01-04 22:37:51 +00:00
|
|
|
return &c.switchTable
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getLocator() switchLocator {
|
2018-01-04 22:37:51 +00:00
|
|
|
return c.switchTable.getLocator()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *switchLocator) DEBUG_getCoords() []byte {
|
2018-01-04 22:37:51 +00:00
|
|
|
return l.getCoords()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_switchLookup(dest []byte, ttl uint64) (switchPort, uint64) {
|
2018-01-04 22:37:51 +00:00
|
|
|
return c.switchTable.lookup(dest, ttl)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (t *switchTable) DEBUG_isDirty() bool {
|
|
|
|
//data := t.data.Load().(*tabledata)
|
|
|
|
t.mutex.RLock()
|
|
|
|
defer t.mutex.RUnlock()
|
|
|
|
data := t.data
|
|
|
|
return data.dirty
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
func (t *switchTable) DEBUG_dumpTable() {
|
2018-01-04 22:37:51 +00:00
|
|
|
//data := t.data.Load().(*tabledata)
|
|
|
|
t.mutex.RLock()
|
|
|
|
defer t.mutex.RUnlock()
|
|
|
|
data := t.data
|
|
|
|
for _, peer := range data.peers {
|
|
|
|
//fmt.Println("DUMPTABLE:", t.treeID, peer.treeID, peer.port,
|
|
|
|
// peer.locator.Root, peer.coords,
|
|
|
|
// peer.reverse.Root, peer.reverse.Coords, peer.forward)
|
|
|
|
fmt.Println("DUMPTABLE:", t.key, peer.key, peer.locator.coords, peer.port /*, peer.forward*/)
|
|
|
|
}
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *switchTable) DEBUG_getReversePort(port switchPort) switchPort {
|
2018-01-04 22:37:51 +00:00
|
|
|
// Returns Port(0) if it cannot get the reverse peer for any reason
|
|
|
|
//data := t.data.Load().(*tabledata)
|
|
|
|
t.mutex.RLock()
|
|
|
|
defer t.mutex.RUnlock()
|
|
|
|
data := t.data
|
|
|
|
if port >= switchPort(len(data.peers)) {
|
|
|
|
return switchPort(0)
|
|
|
|
}
|
|
|
|
pinfo := data.peers[port]
|
|
|
|
if len(pinfo.locator.coords) < 1 {
|
|
|
|
return switchPort(0)
|
|
|
|
}
|
|
|
|
return pinfo.locator.coords[len(pinfo.locator.coords)-1]
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Wire
|
|
|
|
|
|
|
|
func DEBUG_wire_encode_coords(coords []byte) []byte {
|
2018-01-04 22:37:51 +00:00
|
|
|
return wire_encode_coords(coords)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// DHT, via core
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getDHTSize() int {
|
2018-01-04 22:37:51 +00:00
|
|
|
total := 0
|
|
|
|
for bidx := 0; bidx < c.dht.nBuckets(); bidx++ {
|
|
|
|
b := c.dht.getBucket(bidx)
|
2018-03-10 19:58:48 +00:00
|
|
|
total += len(b.peers)
|
|
|
|
total += len(b.other)
|
2018-01-04 22:37:51 +00:00
|
|
|
}
|
|
|
|
return total
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-03-03 12:30:54 +00:00
|
|
|
// TUN defaults
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_GetTUNDefaultIfName() string {
|
|
|
|
return getDefaults().defaultIfName
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_GetTUNDefaultIfMTU() int {
|
|
|
|
return getDefaults().defaultIfMTU
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_GetTUNDefaultIfTAPMode() bool {
|
|
|
|
return getDefaults().defaultIfTAPMode
|
|
|
|
}
|
|
|
|
|
2017-12-29 04:16:20 +00:00
|
|
|
// udpInterface
|
|
|
|
// FIXME udpInterface isn't exported
|
|
|
|
// So debug functions need to work differently...
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c *Core) DEBUG_setupLoopbackUDPInterface() {
|
|
|
|
iface := udpInterface{}
|
|
|
|
iface.init(c, "[::1]:0")
|
|
|
|
c.ifaces = append(c.ifaces[:0], &iface)
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c *Core) DEBUG_getLoopbackAddr() net.Addr {
|
|
|
|
iface := c.ifaces[0]
|
|
|
|
return iface.sock.LocalAddr()
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c *Core) DEBUG_addLoopbackPeer(addr *net.UDPAddr,
|
|
|
|
in (chan<- []byte),
|
|
|
|
out (<-chan []byte)) {
|
|
|
|
iface := c.ifaces[0]
|
|
|
|
iface.addPeer(addr, in, out)
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c *Core) DEBUG_startLoopbackUDPInterface() {
|
|
|
|
iface := c.ifaces[0]
|
|
|
|
go iface.reader()
|
|
|
|
for addr, chs := range iface.peers {
|
|
|
|
udpAddr, err := net.ResolveUDPAddr("udp6", addr)
|
|
|
|
if err != nil { panic(err) }
|
|
|
|
go iface.writer(udpAddr, chs.out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getAddr() *address {
|
2018-01-04 22:37:51 +00:00
|
|
|
return address_addrForNodeID(&c.dht.nodeID)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-02-11 21:45:44 +00:00
|
|
|
func (c *Core) DEBUG_startTun(ifname string, iftapmode bool) {
|
|
|
|
c.DEBUG_startTunWithMTU(ifname, iftapmode, 1280)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-02-11 21:45:44 +00:00
|
|
|
func (c *Core) DEBUG_startTunWithMTU(ifname string, iftapmode bool, mtu int) {
|
2018-01-04 22:37:51 +00:00
|
|
|
addr := c.DEBUG_getAddr()
|
|
|
|
straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix))
|
2018-02-15 22:29:13 +00:00
|
|
|
if ifname != "none" {
|
|
|
|
err := c.tun.setup(ifname, iftapmode, straddr, mtu)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-03-03 19:56:26 +00:00
|
|
|
go func() { panic(c.tun.read()) }()
|
2018-01-04 22:37:51 +00:00
|
|
|
}
|
2018-03-03 19:56:26 +00:00
|
|
|
go func() { panic(c.tun.write()) }()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_stopTun() {
|
2018-01-04 22:37:51 +00:00
|
|
|
c.tun.close()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_newBoxKeys() (*boxPubKey, *boxPrivKey) {
|
2018-01-04 22:37:51 +00:00
|
|
|
return newBoxKeys()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_newSigKeys() (*sigPubKey, *sigPrivKey) {
|
2018-01-04 22:37:51 +00:00
|
|
|
return newSigKeys()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getNodeID(pub *boxPubKey) *NodeID {
|
2018-01-04 22:37:51 +00:00
|
|
|
return getNodeID(pub)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getTreeID(pub *sigPubKey) *TreeID {
|
2018-01-04 22:37:51 +00:00
|
|
|
return getTreeID(pub)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_addrForNodeID(nodeID *NodeID) string {
|
2018-01-04 22:37:51 +00:00
|
|
|
return net.IP(address_addrForNodeID(nodeID)[:]).String()
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_init(bpub []byte,
|
2018-01-04 22:37:51 +00:00
|
|
|
bpriv []byte,
|
|
|
|
spub []byte,
|
|
|
|
spriv []byte) {
|
|
|
|
var boxPub boxPubKey
|
|
|
|
var boxPriv boxPrivKey
|
|
|
|
var sigPub sigPubKey
|
|
|
|
var sigPriv sigPrivKey
|
|
|
|
copy(boxPub[:], bpub)
|
|
|
|
copy(boxPriv[:], bpriv)
|
|
|
|
copy(sigPub[:], spub)
|
|
|
|
copy(sigPriv[:], spriv)
|
|
|
|
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_setupAndStartGlobalUDPInterface(addrport string) {
|
2018-01-04 22:37:51 +00:00
|
|
|
iface := udpInterface{}
|
|
|
|
iface.init(c, addrport)
|
|
|
|
c.udp = &iface
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-25 00:45:29 +00:00
|
|
|
func (c *Core) DEBUG_getGlobalUDPAddr() *net.UDPAddr {
|
|
|
|
return c.udp.sock.LocalAddr().(*net.UDPAddr)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-03 00:45:09 +00:00
|
|
|
func (c *Core) DEBUG_maybeSendUDPKeys(saddr string) {
|
2018-01-13 13:26:26 +00:00
|
|
|
udpAddr, err := net.ResolveUDPAddr("udp", saddr)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
var addr connAddr
|
|
|
|
addr.fromUDPAddr(udpAddr)
|
2018-01-04 22:37:51 +00:00
|
|
|
c.udp.mutex.RLock()
|
2018-01-13 13:26:26 +00:00
|
|
|
_, isIn := c.udp.conns[addr]
|
2018-01-04 22:37:51 +00:00
|
|
|
c.udp.mutex.RUnlock()
|
|
|
|
if !isIn {
|
|
|
|
c.udp.sendKeys(addr)
|
|
|
|
}
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-04-26 14:23:21 +00:00
|
|
|
func (c *Core) DEBUG_addPeer(addr string) {
|
|
|
|
u, err := url.Parse(addr)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if len(u.Opaque) == 0 {
|
|
|
|
switch strings.ToLower(u.Scheme) {
|
|
|
|
case "tcp":
|
|
|
|
c.DEBUG_addTCPConn(u.Host)
|
|
|
|
case "udp":
|
|
|
|
c.DEBUG_maybeSendUDPKeys(u.Host)
|
|
|
|
case "socks":
|
|
|
|
c.DEBUG_addSOCKSConn(u.Host, u.Path[1:])
|
|
|
|
default:
|
|
|
|
panic("invalid peer: " + addr)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// no url scheme provided
|
|
|
|
addr = strings.ToLower(addr)
|
|
|
|
if strings.HasPrefix(addr, "udp:") {
|
|
|
|
c.DEBUG_maybeSendUDPKeys(addr[4:])
|
|
|
|
} else {
|
|
|
|
if strings.HasPrefix(addr, "tcp:") {
|
|
|
|
addr = addr[4:]
|
|
|
|
}
|
|
|
|
c.DEBUG_addTCPConn(addr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) {
|
|
|
|
go func() {
|
|
|
|
dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct)
|
|
|
|
if err == nil {
|
|
|
|
conn, err := dialer.Dial("tcp", peeraddr)
|
|
|
|
if err == nil {
|
|
|
|
c.tcp.callWithConn(&wrappedConn{
|
|
|
|
c: conn,
|
|
|
|
raddr: &wrappedAddr{
|
|
|
|
network: "tcp",
|
|
|
|
addr: peeraddr,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2017-12-29 04:16:20 +00:00
|
|
|
//*
|
|
|
|
func (c *Core) DEBUG_setupAndStartGlobalTCPInterface(addrport string) {
|
2018-01-04 22:37:51 +00:00
|
|
|
iface := tcpInterface{}
|
|
|
|
iface.init(c, addrport)
|
|
|
|
c.tcp = &iface
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getGlobalTCPAddr() *net.TCPAddr {
|
2018-01-04 22:37:51 +00:00
|
|
|
return c.tcp.serv.Addr().(*net.TCPAddr)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_addTCPConn(saddr string) {
|
2018-01-04 22:37:51 +00:00
|
|
|
c.tcp.call(saddr)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
2018-01-04 22:37:51 +00:00
|
|
|
|
2017-12-29 04:16:20 +00:00
|
|
|
//*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c *Core) DEBUG_startSelfPeer() {
|
|
|
|
c.Peers.mutex.RLock()
|
|
|
|
defer c.Peers.mutex.RUnlock()
|
|
|
|
p := c.Peers.ports[0]
|
|
|
|
go p.MainLoop()
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c *Core) DEBUG_setupAndStartGlobalKCPInterface(addrport string) {
|
|
|
|
iface := kcpInterface{}
|
|
|
|
iface.init(c, addrport)
|
|
|
|
c.kcp = &iface
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_getGlobalKCPAddr() net.Addr {
|
|
|
|
return c.kcp.serv.Addr()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) DEBUG_addKCPConn(saddr string) {
|
|
|
|
c.kcp.call(saddr)
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-01-21 00:17:15 +00:00
|
|
|
func (c *Core) DEBUG_setupAndStartAdminInterface(addrport string) {
|
|
|
|
a := admin{}
|
|
|
|
a.init(c, addrport)
|
|
|
|
c.admin = a
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2017-12-29 04:16:20 +00:00
|
|
|
func (c *Core) DEBUG_setLogger(log *log.Logger) {
|
2018-01-04 22:37:51 +00:00
|
|
|
c.log = log
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-09 08:08:54 +00:00
|
|
|
func (c *Core) DEBUG_setIfceExpr(expr *regexp.Regexp) {
|
|
|
|
c.ifceExpr = expr
|
|
|
|
}
|
|
|
|
|
2017-12-29 04:16:20 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
func DEBUG_simLinkPeers(p, q *peer) {
|
2018-01-04 22:37:51 +00:00
|
|
|
// Sets q.out() to point to p and starts p.linkLoop()
|
|
|
|
plinkIn := make(chan []byte, 1)
|
|
|
|
qlinkIn := make(chan []byte, 1)
|
|
|
|
p.out = func(bs []byte) {
|
|
|
|
go q.handlePacket(bs, qlinkIn)
|
|
|
|
}
|
|
|
|
q.out = func(bs []byte) {
|
|
|
|
go p.handlePacket(bs, plinkIn)
|
|
|
|
}
|
|
|
|
go p.linkLoop(plinkIn)
|
|
|
|
go q.linkLoop(qlinkIn)
|
2017-12-29 04:16:20 +00:00
|
|
|
}
|
2018-02-17 23:10:08 +00:00
|
|
|
|
|
|
|
func (c *Core) DEBUG_simFixMTU() {
|
|
|
|
c.tun.mtu = 65535
|
|
|
|
}
|