Detect network changes, initial code. Actions to be developed. #2

This commit is contained in:
Kleissner
2021-03-02 00:28:03 +01:00
parent c34adc472c
commit 213c724016
7 changed files with 134 additions and 3 deletions

View File

@@ -152,6 +152,9 @@ func bootstrap() {
func autoMulticastBroadcast() {
sendMulticastBroadcast := func() {
networksMutex.RLock()
defer networksMutex.RUnlock()
for _, network := range networks6 {
if err := network.MulticastIPv6Send(); err != nil {
log.Printf("bootstrap error multicast from network address '%s': %v", network.address.IP.String(), err.Error())

View File

@@ -70,6 +70,11 @@ func (peer *PeerInfo) cmdResponse(msg *packet2) {
// cmdPing handles an incoming ping message
func (peer *PeerInfo) cmdPing(msg *packet2) {
if peer == nil {
// Unexpected incoming ping, reply with announce message
// TODO
return
}
peer.send(&PacketRaw{Command: CommandPong})
//fmt.Printf("Incoming ping from %s on %s\n", msg.connection.Address.String(), msg.connection.Address.String())
}

View File

@@ -241,6 +241,9 @@ func sendAllNetworks(receiverPublicKey *btcec.PublicKey, packet *PacketRaw, remo
successCount := 0
networksMutex.RLock()
defer networksMutex.RUnlock()
if IsIPv6(remote.IP.To16()) {
for _, network := range networks6 {
// Do not mix link-local unicast targets with non link-local networks (only when iface is known, i.e. not catch all local)

View File

@@ -7,8 +7,11 @@ Author: Peter Kleissner
package core
import (
"fmt"
"log"
"net"
"strings"
"time"
)
// FindInterfaceByIP finds an interface based on the IP. The IP must be available at the interface.
@@ -87,3 +90,111 @@ func IsNetworkErrorFatal(err error) bool {
return false
}
// changeMonitorFrequency is the frequency in seconds to check for a network change
const changeMonitorFrequency = 10
// networkChangeMonitor() monitors for network changes to act accordingly
func networkChangeMonitor() {
// If manual IPs are entered, no need for monitoring for any network changes.
if len(config.Listen) > 0 {
return
}
for {
time.Sleep(time.Second * changeMonitorFrequency)
interfaceList, err := net.Interfaces()
if err != nil {
log.Printf("networkChangeMonitor enumerating network adapters failed: %s\n", err.Error())
continue
}
ifacesNew := make(map[string][]net.Addr)
for _, iface := range interfaceList {
addressesNew, err := iface.Addrs()
if err != nil {
log.Printf("initNetwork error enumerating IPs for network adapter '%s': %s\n", iface.Name, err.Error())
continue
}
ifacesNew[iface.Name] = addressesNew
// was the interface added?
addressesExist, ok := ifacesExist[iface.Name]
if !ok {
networkChangeInterfaceNew(iface, addressesNew)
} else {
// new IPs added for this interface?
for _, addr := range addressesNew {
exists := false
for _, exist := range addressesExist {
if exist.String() == addr.String() {
exists = true
break
}
}
if !exists {
networkChangeIPNew(iface, addr)
}
}
// were IPs removed from this interface
for _, exist := range addressesExist {
removed := true
for _, addr := range addressesNew {
if exist.String() == addr.String() {
removed = false
break
}
}
if removed {
networkChangeIPRemove(iface, exist)
}
}
}
}
// was an existing interface removed?
for ifaceExist, addressesExist := range ifacesExist {
if _, ok := ifacesNew[ifaceExist]; !ok {
networkChangeInterfaceRemove(ifaceExist, addressesExist)
}
}
ifacesExist = ifacesNew
}
}
// networkChangeInterfaceNew is called when a new interface is detected
func networkChangeInterfaceNew(iface net.Interface, addresses []net.Addr) {
fmt.Printf("Interface new: %s\n", iface.Name)
for _, addr := range addresses {
fmt.Printf(" IP: %s\n", addr.String())
}
}
// networkChangeInterfaceRemove is called when an existing interface is removed
func networkChangeInterfaceRemove(iface string, addresses []net.Addr) {
//networksMutex.RLock()
//defer networksMutex.RUnlock()
fmt.Printf("Interface removed: %s\n", iface)
for _, addr := range addresses {
fmt.Printf(" IP: %s\n", addr.String())
}
}
// networkChangeIPNew is called when an existing interface lists a new IP
func networkChangeIPNew(iface net.Interface, address net.Addr) {
fmt.Printf("IP new on iface: %s address %s\n", iface.Name, address.String())
}
// networkChangeIPRemove is called when an existing interface removes an IP
func networkChangeIPRemove(iface net.Interface, address net.Addr) {
fmt.Printf("IP removed on iface: %s address %s\n", iface.Name, address.String())
}

View File

@@ -31,14 +31,16 @@ type networkWire struct {
}
var (
rawPacketsIncoming chan networkWire // channel for processing incoming decoded packets by workers
ipsListen map[string]struct{} // list of IPs currently listening on
rawPacketsIncoming chan networkWire // channel for processing incoming decoded packets by workers
ipsListen map[string]struct{} // list of IPs currently listening on
ifacesExist map[string][]net.Addr // list of currently known interfaces with list of IP addresses
)
// initNetwork sets up the network configuration and starts listening.
func initNetwork() {
rawPacketsIncoming = make(chan networkWire, 1000) // buffer up to 1000 UDP packets before they get buffered by the OS network stack and eventually dropped
ipsListen = make(map[string]struct{})
ifacesExist = make(map[string][]net.Addr)
rand.Seed(time.Now().UnixNano()) // we are not using "crypto/rand" for speed tradeoff
if config.ListenWorkers == 0 {
@@ -96,6 +98,8 @@ func initNetwork() {
continue
}
ifacesExist[iface.Name] = addresses
for _, address := range addresses {
net1 := address.(*net.IPNet)

View File

@@ -10,6 +10,7 @@ import (
"errors"
"log"
"net"
"sync"
"sync/atomic"
"time"
)
@@ -30,6 +31,9 @@ type Network struct {
// networks is a list of all connected networks
var networks4, networks6 []*Network
// single mutex for both network lists. Higher granularity currently not needed.
var networksMutex sync.RWMutex
// Default ports to use. This may be randomized in the future to prevent fingerprinting (and subsequent blocking) by corporate and ISP firewalls.
const defaultPort = 'p' // 112
@@ -115,7 +119,7 @@ func packetWorker(packets <-chan networkWire) {
for packet := range packets {
decoded, senderPublicKey, err := PacketDecrypt(packet.raw, packet.receiverPublicKey)
if err != nil {
log.Printf("packetWorker Error decrypting packet from '%s': %s\n", packet.sender.String(), err.Error())
//log.Printf("packetWorker Error decrypting packet from '%s': %s\n", packet.sender.String(), err.Error())
continue
}

View File

@@ -20,4 +20,5 @@ func Connect() {
go bootstrap()
go autoMulticastBroadcast()
go autoPingAll()
go networkChangeMonitor()
}