mirror of
https://github.com/safing/portmaster
synced 2025-09-01 01:59:11 +00:00
100 lines
2.4 KiB
Go
100 lines
2.4 KiB
Go
package netenv
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/sha1" //nolint:gosec // not used for security
|
|
"io"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/safing/portbase/log"
|
|
"github.com/safing/portbase/utils"
|
|
)
|
|
|
|
var (
|
|
networkChangeCheckTrigger = make(chan struct{}, 1)
|
|
networkChangedFlagController = utils.NewFlagController()
|
|
)
|
|
|
|
func GetNetworkChangedFlag() *utils.Flag {
|
|
return networkChangedFlagController.NewFlag()
|
|
}
|
|
|
|
func notifyOfNetworkChange() {
|
|
networkChangedFlagController.NotifyAndReset()
|
|
module.TriggerEvent(NetworkChangedEvent, nil)
|
|
}
|
|
|
|
func triggerNetworkChangeCheck() {
|
|
select {
|
|
case networkChangeCheckTrigger <- struct{}{}:
|
|
default:
|
|
}
|
|
}
|
|
|
|
func monitorNetworkChanges(ctx context.Context) error {
|
|
var lastNetworkChecksum []byte
|
|
|
|
serviceLoop:
|
|
for {
|
|
trigger := false
|
|
|
|
timeout := time.Minute
|
|
if GetOnlineStatus() != StatusOnline {
|
|
timeout = time.Second
|
|
}
|
|
// wait for trigger
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
case <-networkChangeCheckTrigger:
|
|
// don't fall through because the online change check
|
|
// triggers the networkChangeCheck this way. If we would set
|
|
// trigger == true we would trigger the online check again
|
|
// resulting in a loop of pointless checks.
|
|
case <-time.After(timeout):
|
|
trigger = true
|
|
}
|
|
|
|
// check network for changes
|
|
// create hashsum of current network config
|
|
hasher := sha1.New() //nolint:gosec // not used for security
|
|
interfaces, err := net.Interfaces()
|
|
if err != nil {
|
|
log.Warningf("environment: failed to get interfaces: %s", err)
|
|
continue
|
|
}
|
|
for _, iface := range interfaces {
|
|
_, _ = io.WriteString(hasher, iface.Name)
|
|
// log.Tracef("adding: %s", iface.Name)
|
|
_, _ = io.WriteString(hasher, iface.Flags.String())
|
|
// log.Tracef("adding: %s", iface.Flags.String())
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
log.Warningf("environment: failed to get addrs from interface %s: %s", iface.Name, err)
|
|
continue
|
|
}
|
|
for _, addr := range addrs {
|
|
_, _ = io.WriteString(hasher, addr.String())
|
|
// log.Tracef("adding: %s", addr.String())
|
|
}
|
|
}
|
|
newChecksum := hasher.Sum(nil)
|
|
|
|
// compare checksum with last
|
|
if !bytes.Equal(lastNetworkChecksum, newChecksum) {
|
|
if len(lastNetworkChecksum) == 0 {
|
|
lastNetworkChecksum = newChecksum
|
|
continue serviceLoop
|
|
}
|
|
lastNetworkChecksum = newChecksum
|
|
|
|
if trigger {
|
|
triggerOnlineStatusInvestigation()
|
|
}
|
|
notifyOfNetworkChange()
|
|
}
|
|
|
|
}
|
|
}
|