mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Clean up linter errors
This commit is contained in:
parent
35c7f4955b
commit
f75fc7d162
50 changed files with 402 additions and 334 deletions
|
@ -3,7 +3,6 @@ package firewall
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -21,26 +20,28 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
module *modules.Module
|
||||
|
||||
// localNet net.IPNet
|
||||
localhost net.IP
|
||||
dnsServer net.IPNet
|
||||
// localhost net.IP
|
||||
// dnsServer net.IPNet
|
||||
packetsAccepted *uint64
|
||||
packetsBlocked *uint64
|
||||
packetsDropped *uint64
|
||||
|
||||
localNet4 *net.IPNet
|
||||
// localNet4 *net.IPNet
|
||||
|
||||
localhost4 = net.IPv4(127, 0, 0, 1)
|
||||
localhost6 = net.IPv6loopback
|
||||
// localhost4 = net.IPv4(127, 0, 0, 1)
|
||||
// localhost6 = net.IPv6loopback
|
||||
|
||||
tunnelNet4 *net.IPNet
|
||||
tunnelNet6 *net.IPNet
|
||||
tunnelEntry4 = net.IPv4(127, 0, 0, 17)
|
||||
tunnelEntry6 = net.ParseIP("fd17::17")
|
||||
// tunnelNet4 *net.IPNet
|
||||
// tunnelNet6 *net.IPNet
|
||||
// tunnelEntry4 = net.IPv4(127, 0, 0, 17)
|
||||
// tunnelEntry6 = net.ParseIP("fd17::17")
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("firewall", prep, start, stop, "core", "network", "nameserver", "profile", "updates")
|
||||
module = modules.Register("firewall", prep, start, stop, "core", "network", "nameserver", "profile", "updates")
|
||||
}
|
||||
|
||||
func prep() (err error) {
|
||||
|
@ -55,21 +56,21 @@ func prep() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
_, localNet4, err = net.ParseCIDR("127.0.0.0/24")
|
||||
// Yes, this would normally be 127.0.0.0/8
|
||||
// TODO: figure out any side effects
|
||||
if err != nil {
|
||||
return fmt.Errorf("firewall: failed to parse cidr 127.0.0.0/24: %s", err)
|
||||
}
|
||||
// _, localNet4, err = net.ParseCIDR("127.0.0.0/24")
|
||||
// // Yes, this would normally be 127.0.0.0/8
|
||||
// // TODO: figure out any side effects
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("firewall: failed to parse cidr 127.0.0.0/24: %s", err)
|
||||
// }
|
||||
|
||||
_, tunnelNet4, err = net.ParseCIDR("127.17.0.0/16")
|
||||
if err != nil {
|
||||
return fmt.Errorf("firewall: failed to parse cidr 127.17.0.0/16: %s", err)
|
||||
}
|
||||
_, tunnelNet6, err = net.ParseCIDR("fd17::/64")
|
||||
if err != nil {
|
||||
return fmt.Errorf("firewall: failed to parse cidr fd17::/64: %s", err)
|
||||
}
|
||||
// _, tunnelNet4, err = net.ParseCIDR("127.17.0.0/16")
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("firewall: failed to parse cidr 127.17.0.0/16: %s", err)
|
||||
// }
|
||||
// _, tunnelNet6, err = net.ParseCIDR("fd17::/64")
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("firewall: failed to parse cidr fd17::/64: %s", err)
|
||||
// }
|
||||
|
||||
var pA uint64
|
||||
packetsAccepted = &pA
|
||||
|
@ -83,9 +84,21 @@ func prep() (err error) {
|
|||
|
||||
func start() error {
|
||||
startAPIAuth()
|
||||
go statLogger()
|
||||
go run()
|
||||
go portsInUseCleaner()
|
||||
|
||||
module.StartWorker("stat logger", func(ctx context.Context) error {
|
||||
statLogger()
|
||||
return nil
|
||||
})
|
||||
|
||||
module.StartWorker("packet handler", func(ctx context.Context) error {
|
||||
run()
|
||||
return nil
|
||||
})
|
||||
|
||||
module.StartWorker("ports state cleaner", func(ctx context.Context) error {
|
||||
portsInUseCleaner()
|
||||
return nil
|
||||
})
|
||||
|
||||
return interception.Start()
|
||||
}
|
||||
|
@ -106,7 +119,7 @@ func handlePacket(pkt packet.Packet) {
|
|||
// allow local dns
|
||||
if (pkt.Info().DstPort == 53 || pkt.Info().SrcPort == 53) && pkt.Info().Src.Equal(pkt.Info().Dst) {
|
||||
log.Debugf("accepting local dns: %s", pkt)
|
||||
pkt.PermanentAccept()
|
||||
_ = pkt.PermanentAccept()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -114,7 +127,7 @@ func handlePacket(pkt packet.Packet) {
|
|||
if apiPortSet {
|
||||
if (pkt.Info().DstPort == apiPort || pkt.Info().SrcPort == apiPort) && pkt.Info().Src.Equal(pkt.Info().Dst) {
|
||||
log.Debugf("accepting api connection: %s", pkt)
|
||||
pkt.PermanentAccept()
|
||||
_ = pkt.PermanentAccept()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -130,20 +143,20 @@ func handlePacket(pkt packet.Packet) {
|
|||
switch pkt.Info().Protocol {
|
||||
case packet.ICMP:
|
||||
log.Debugf("accepting ICMP: %s", pkt)
|
||||
pkt.PermanentAccept()
|
||||
_ = pkt.PermanentAccept()
|
||||
return
|
||||
case packet.ICMPv6:
|
||||
log.Debugf("accepting ICMPv6: %s", pkt)
|
||||
pkt.PermanentAccept()
|
||||
_ = pkt.PermanentAccept()
|
||||
return
|
||||
case packet.IGMP:
|
||||
log.Debugf("accepting IGMP: %s", pkt)
|
||||
pkt.PermanentAccept()
|
||||
_ = pkt.PermanentAccept()
|
||||
return
|
||||
case packet.UDP:
|
||||
if pkt.Info().DstPort == 67 || pkt.Info().DstPort == 68 {
|
||||
log.Debugf("accepting DHCP: %s", pkt)
|
||||
pkt.PermanentAccept()
|
||||
_ = pkt.PermanentAccept()
|
||||
return
|
||||
}
|
||||
// TODO: Howto handle NetBios?
|
||||
|
@ -310,39 +323,44 @@ func issueVerdict(pkt packet.Packet, link *network.Link, verdict network.Verdict
|
|||
verdict = link.Verdict
|
||||
}
|
||||
|
||||
var err error
|
||||
switch verdict {
|
||||
case network.VerdictAccept:
|
||||
atomic.AddUint64(packetsAccepted, 1)
|
||||
if link.VerdictPermanent {
|
||||
pkt.PermanentAccept()
|
||||
err = pkt.PermanentAccept()
|
||||
} else {
|
||||
pkt.Accept()
|
||||
err = pkt.Accept()
|
||||
}
|
||||
case network.VerdictBlock:
|
||||
atomic.AddUint64(packetsBlocked, 1)
|
||||
if link.VerdictPermanent {
|
||||
pkt.PermanentBlock()
|
||||
err = pkt.PermanentBlock()
|
||||
} else {
|
||||
pkt.Block()
|
||||
err = pkt.Block()
|
||||
}
|
||||
case network.VerdictDrop:
|
||||
atomic.AddUint64(packetsDropped, 1)
|
||||
if link.VerdictPermanent {
|
||||
pkt.PermanentDrop()
|
||||
err = pkt.PermanentDrop()
|
||||
} else {
|
||||
pkt.Drop()
|
||||
err = pkt.Drop()
|
||||
}
|
||||
case network.VerdictRerouteToNameserver:
|
||||
pkt.RerouteToNameserver()
|
||||
err = pkt.RerouteToNameserver()
|
||||
case network.VerdictRerouteToTunnel:
|
||||
pkt.RerouteToTunnel()
|
||||
err = pkt.RerouteToTunnel()
|
||||
default:
|
||||
atomic.AddUint64(packetsDropped, 1)
|
||||
pkt.Drop()
|
||||
err = pkt.Drop()
|
||||
}
|
||||
|
||||
link.Unlock()
|
||||
|
||||
if err != nil {
|
||||
log.Warningf("firewall: failed to apply verdict to pkt %s: %s", pkt, err)
|
||||
}
|
||||
|
||||
log.Tracer(pkt.Ctx()).Infof("firewall: %s %s", link.Verdict, link)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/safing/portmaster/network/packet"
|
||||
)
|
||||
|
||||
//nolint:golint,stylecheck // FIXME
|
||||
const (
|
||||
DO_NOTHING uint8 = iota
|
||||
BLOCK_PACKET
|
||||
|
@ -25,6 +26,7 @@ var (
|
|||
inspectorsLock sync.Mutex
|
||||
)
|
||||
|
||||
// RegisterInspector registers a traffic inspector.
|
||||
func RegisterInspector(name string, inspector inspectorFn, inspectVerdict network.Verdict) (index int) {
|
||||
inspectorsLock.Lock()
|
||||
defer inspectorsLock.Unlock()
|
||||
|
@ -35,13 +37,14 @@ func RegisterInspector(name string, inspector inspectorFn, inspectVerdict networ
|
|||
return
|
||||
}
|
||||
|
||||
// RunInspectors runs all the applicable inspectors on the given packet.
|
||||
func RunInspectors(pkt packet.Packet, link *network.Link) (network.Verdict, bool) {
|
||||
// inspectorsLock.Lock()
|
||||
// defer inspectorsLock.Unlock()
|
||||
|
||||
activeInspectors := link.GetActiveInspectors()
|
||||
if activeInspectors == nil {
|
||||
activeInspectors = make([]bool, len(inspectors), len(inspectors))
|
||||
activeInspectors = make([]bool, len(inspectors))
|
||||
link.SetActiveInspectors(activeInspectors)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
// Package nfqueue provides network interception capabilites on linux via iptables nfqueue.
|
||||
// Package nfqueue provides network interception capabilities on linux via iptables nfqueue.
|
||||
package nfqueue
|
||||
|
|
|
@ -27,6 +27,8 @@ func init() {
|
|||
queues = make(map[uint16]*NFQueue)
|
||||
}
|
||||
|
||||
// NFQueue holds a Linux NFQ Handle and associated information.
|
||||
//nolint:maligned // FIXME
|
||||
type NFQueue struct {
|
||||
DefaultVerdict uint32
|
||||
Timeout time.Duration
|
||||
|
@ -41,6 +43,7 @@ type NFQueue struct {
|
|||
Packets chan packet.Packet
|
||||
}
|
||||
|
||||
// NewNFQueue initializes a new netfilter queue.
|
||||
func NewNFQueue(qid uint16) (nfq *NFQueue, err error) {
|
||||
if os.Geteuid() != 0 {
|
||||
return nil, errors.New("must be root to intercept packets")
|
||||
|
@ -61,96 +64,98 @@ func NewNFQueue(qid uint16) (nfq *NFQueue, err error) {
|
|||
return nfq, nil
|
||||
}
|
||||
|
||||
func (this *NFQueue) init() error {
|
||||
func (nfq *NFQueue) init() error {
|
||||
var err error
|
||||
if this.h, err = C.nfq_open(); err != nil || this.h == nil {
|
||||
if nfq.h, err = C.nfq_open(); err != nil || nfq.h == nil {
|
||||
return fmt.Errorf("could not open nfqueue: %s", err)
|
||||
}
|
||||
|
||||
//if this.qh, err = C.nfq_create_queue(this.h, qid, C.get_cb(), unsafe.Pointer(nfq)); err != nil || this.qh == nil {
|
||||
//if nfq.qh, err = C.nfq_create_queue(nfq.h, qid, C.get_cb(), unsafe.Pointer(nfq)); err != nil || nfq.qh == nil {
|
||||
|
||||
this.Packets = make(chan packet.Packet, 1)
|
||||
nfq.Packets = make(chan packet.Packet, 1)
|
||||
|
||||
if C.nfq_unbind_pf(this.h, C.AF_INET) < 0 {
|
||||
this.Destroy()
|
||||
if C.nfq_unbind_pf(nfq.h, C.AF_INET) < 0 {
|
||||
nfq.Destroy()
|
||||
return errors.New("nfq_unbind_pf(AF_INET) failed, are you root?")
|
||||
}
|
||||
if C.nfq_unbind_pf(this.h, C.AF_INET6) < 0 {
|
||||
this.Destroy()
|
||||
if C.nfq_unbind_pf(nfq.h, C.AF_INET6) < 0 {
|
||||
nfq.Destroy()
|
||||
return errors.New("nfq_unbind_pf(AF_INET6) failed")
|
||||
}
|
||||
|
||||
if C.nfq_bind_pf(this.h, C.AF_INET) < 0 {
|
||||
this.Destroy()
|
||||
if C.nfq_bind_pf(nfq.h, C.AF_INET) < 0 {
|
||||
nfq.Destroy()
|
||||
return errors.New("nfq_bind_pf(AF_INET) failed")
|
||||
}
|
||||
if C.nfq_bind_pf(this.h, C.AF_INET6) < 0 {
|
||||
this.Destroy()
|
||||
if C.nfq_bind_pf(nfq.h, C.AF_INET6) < 0 {
|
||||
nfq.Destroy()
|
||||
return errors.New("nfq_bind_pf(AF_INET6) failed")
|
||||
}
|
||||
|
||||
if this.qh, err = C.create_queue(this.h, C.uint16_t(this.qid)); err != nil || this.qh == nil {
|
||||
C.nfq_close(this.h)
|
||||
if nfq.qh, err = C.create_queue(nfq.h, C.uint16_t(nfq.qid)); err != nil || nfq.qh == nil {
|
||||
C.nfq_close(nfq.h)
|
||||
return fmt.Errorf("could not create queue: %s", err)
|
||||
}
|
||||
|
||||
this.fd = int(C.nfq_fd(this.h))
|
||||
nfq.fd = int(C.nfq_fd(nfq.h))
|
||||
|
||||
if C.nfq_set_mode(this.qh, C.NFQNL_COPY_PACKET, 0xffff) < 0 {
|
||||
this.Destroy()
|
||||
if C.nfq_set_mode(nfq.qh, C.NFQNL_COPY_PACKET, 0xffff) < 0 {
|
||||
nfq.Destroy()
|
||||
return errors.New("nfq_set_mode(NFQNL_COPY_PACKET) failed")
|
||||
}
|
||||
if C.nfq_set_queue_maxlen(this.qh, 1024*8) < 0 {
|
||||
this.Destroy()
|
||||
if C.nfq_set_queue_maxlen(nfq.qh, 1024*8) < 0 {
|
||||
nfq.Destroy()
|
||||
return errors.New("nfq_set_queue_maxlen(1024 * 8) failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *NFQueue) Destroy() {
|
||||
this.lk.Lock()
|
||||
defer this.lk.Unlock()
|
||||
// Destroy closes all the nfqueues.
|
||||
func (nfq *NFQueue) Destroy() {
|
||||
nfq.lk.Lock()
|
||||
defer nfq.lk.Unlock()
|
||||
|
||||
if this.fd != 0 && this.Valid() {
|
||||
syscall.Close(this.fd)
|
||||
if nfq.fd != 0 && nfq.Valid() {
|
||||
syscall.Close(nfq.fd)
|
||||
}
|
||||
if this.qh != nil {
|
||||
C.nfq_destroy_queue(this.qh)
|
||||
this.qh = nil
|
||||
if nfq.qh != nil {
|
||||
C.nfq_destroy_queue(nfq.qh)
|
||||
nfq.qh = nil
|
||||
}
|
||||
if this.h != nil {
|
||||
C.nfq_close(this.h)
|
||||
this.h = nil
|
||||
if nfq.h != nil {
|
||||
C.nfq_close(nfq.h)
|
||||
nfq.h = nil
|
||||
}
|
||||
|
||||
// TODO: don't close, we're exiting anyway
|
||||
// if this.Packets != nil {
|
||||
// close(this.Packets)
|
||||
// if nfq.Packets != nil {
|
||||
// close(nfq.Packets)
|
||||
// }
|
||||
}
|
||||
|
||||
func (this *NFQueue) Valid() bool {
|
||||
return this.h != nil && this.qh != nil
|
||||
// Valid returns whether the NFQueue is still valid.
|
||||
func (nfq *NFQueue) Valid() bool {
|
||||
return nfq.h != nil && nfq.qh != nil
|
||||
}
|
||||
|
||||
//export go_nfq_callback
|
||||
func go_nfq_callback(id uint32, hwproto uint16, hook uint8, mark *uint32,
|
||||
version, protocol, tos, ttl uint8, saddr, daddr unsafe.Pointer,
|
||||
sport, dport, checksum uint16, payload_len uint32, payload, data unsafe.Pointer) (v uint32) {
|
||||
sport, dport, checksum uint16, payloadLen uint32, payload, data unsafe.Pointer) (v uint32) {
|
||||
|
||||
qidptr := (*uint16)(data)
|
||||
qid := uint16(*qidptr)
|
||||
qid := *qidptr
|
||||
|
||||
// nfq := (*NFQueue)(nfqptr)
|
||||
ipVersion := packet.IPVersion(version)
|
||||
ipsz := C.int(ipVersion.ByteSize())
|
||||
bs := C.GoBytes(payload, (C.int)(payload_len))
|
||||
bs := C.GoBytes(payload, (C.int)(payloadLen))
|
||||
|
||||
verdict := make(chan uint32, 1)
|
||||
pkt := Packet{
|
||||
QueueId: qid,
|
||||
Id: id,
|
||||
QueueID: qid,
|
||||
ID: id,
|
||||
HWProtocol: hwproto,
|
||||
Hook: hook,
|
||||
Mark: *mark,
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package nfqueue
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
)
|
||||
|
||||
// NFQ Errors
|
||||
var (
|
||||
ErrVerdictSentOrTimedOut error = fmt.Errorf("The verdict was already sent or timed out.")
|
||||
ErrVerdictSentOrTimedOut = errors.New("the verdict was already sent or timed out")
|
||||
)
|
||||
|
||||
// NFQ Packet Constants
|
||||
//nolint:golint,stylecheck // FIXME
|
||||
const (
|
||||
NFQ_DROP uint32 = 0 // discarded the packet
|
||||
NFQ_ACCEPT uint32 = 1 // the packet passes, continue iterations
|
||||
|
@ -19,11 +22,12 @@ const (
|
|||
NFQ_STOP uint32 = 5 // accept, but don't continue iterations
|
||||
)
|
||||
|
||||
// Packet represents a packet with a NFQ reference.
|
||||
type Packet struct {
|
||||
packet.Base
|
||||
|
||||
QueueId uint16
|
||||
Id uint32
|
||||
QueueID uint16
|
||||
ID uint32
|
||||
HWProtocol uint16
|
||||
Hook uint8
|
||||
Mark uint32
|
||||
|
@ -35,9 +39,10 @@ type Packet struct {
|
|||
|
||||
// func (pkt *Packet) String() string {
|
||||
// return fmt.Sprintf("<Packet QId: %d, Id: %d, Type: %s, Src: %s:%d, Dst: %s:%d, Mark: 0x%X, Checksum: 0x%X, TOS: 0x%X, TTL: %d>",
|
||||
// pkt.QueueId, pkt.Id, pkt.Protocol, pkt.Src, pkt.SrcPort, pkt.Dst, pkt.DstPort, pkt.Mark, pkt.Checksum, pkt.Tos, pkt.TTL)
|
||||
// pkt.QueueID, pkt.Id, pkt.Protocol, pkt.Src, pkt.SrcPort, pkt.Dst, pkt.DstPort, pkt.Mark, pkt.Checksum, pkt.Tos, pkt.TTL)
|
||||
// }
|
||||
|
||||
//nolint:unparam // FIXME
|
||||
func (pkt *Packet) setVerdict(v uint32) (err error) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
|
@ -68,41 +73,49 @@ func (pkt *Packet) setVerdict(v uint32) (err error) {
|
|||
// return pkt.setVerdict(NFQ_DROP)
|
||||
// }
|
||||
|
||||
// Accept implements the packet interface.
|
||||
func (pkt *Packet) Accept() error {
|
||||
pkt.Mark = 1700
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// Block implements the packet interface.
|
||||
func (pkt *Packet) Block() error {
|
||||
pkt.Mark = 1701
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// Drop implements the packet interface.
|
||||
func (pkt *Packet) Drop() error {
|
||||
pkt.Mark = 1702
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// PermanentAccept implements the packet interface.
|
||||
func (pkt *Packet) PermanentAccept() error {
|
||||
pkt.Mark = 1710
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// PermanentBlock implements the packet interface.
|
||||
func (pkt *Packet) PermanentBlock() error {
|
||||
pkt.Mark = 1711
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// PermanentDrop implements the packet interface.
|
||||
func (pkt *Packet) PermanentDrop() error {
|
||||
pkt.Mark = 1712
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// RerouteToNameserver implements the packet interface.
|
||||
func (pkt *Packet) RerouteToNameserver() error {
|
||||
pkt.Mark = 1799
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
}
|
||||
|
||||
// RerouteToTunnel implements the packet interface.
|
||||
func (pkt *Packet) RerouteToTunnel() error {
|
||||
pkt.Mark = 1717
|
||||
return pkt.setVerdict(NFQ_ACCEPT)
|
||||
|
|
|
@ -247,28 +247,28 @@ func StartNfqueueInterception() (err error) {
|
|||
|
||||
err = activateNfqueueFirewall()
|
||||
if err != nil {
|
||||
Stop()
|
||||
_ = Stop()
|
||||
return fmt.Errorf("could not initialize nfqueue: %s", err)
|
||||
}
|
||||
|
||||
out4Queue, err = nfqueue.NewNFQueue(17040)
|
||||
if err != nil {
|
||||
Stop()
|
||||
_ = Stop()
|
||||
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||
}
|
||||
in4Queue, err = nfqueue.NewNFQueue(17140)
|
||||
if err != nil {
|
||||
Stop()
|
||||
_ = Stop()
|
||||
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||
}
|
||||
out6Queue, err = nfqueue.NewNFQueue(17060)
|
||||
if err != nil {
|
||||
Stop()
|
||||
_ = Stop()
|
||||
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||
}
|
||||
in6Queue, err = nfqueue.NewNFQueue(17160)
|
||||
if err != nil {
|
||||
Stop()
|
||||
_ = Stop()
|
||||
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||
}
|
||||
|
||||
|
@ -321,12 +321,3 @@ func handleInterception() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stringInSlice(slice []string, value string) bool {
|
||||
for _, entry := range slice {
|
||||
if value == entry {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// +build windows
|
||||
|
||||
package windowskext
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// +build windows
|
||||
|
||||
package windowskext
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// +build windows
|
||||
|
||||
package windowskext
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const integerSize int = int(unsafe.Sizeof(0))
|
||||
|
||||
func isBigEndian() bool {
|
||||
var i int = 0x1
|
||||
bs := (*[integerSize]byte)(unsafe.Pointer(&i))
|
||||
if bs[0] == 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if isBigEndian() {
|
||||
fmt.Println("System is Big Endian (Network Byte Order): uint16 0x1234 is 0x1234 in memory")
|
||||
} else {
|
||||
fmt.Println("System is Little Endian (Host Byte Order): uint16 0x1234 is 0x3412 in memory")
|
||||
}
|
||||
}
|
|
@ -139,6 +139,7 @@ func DecideOnCommunicationAfterIntel(comm *network.Communication, fqdn string, r
|
|||
}
|
||||
|
||||
// FilterDNSResponse filters a dns response according to the application profile and settings.
|
||||
//nolint:gocognit // FIXME
|
||||
func FilterDNSResponse(comm *network.Communication, q *intel.Query, rrCache *intel.RRCache) *intel.RRCache {
|
||||
// do not modify own queries - this should not happen anyway
|
||||
if comm.Process().Pid == os.Getpid() {
|
||||
|
@ -497,7 +498,7 @@ func checkRelation(comm *network.Communication, fqdn string) (related bool) {
|
|||
|
||||
// TODO: add #AI
|
||||
|
||||
pathElements := strings.Split(comm.Process().Path, "/") // FIXME: path seperator
|
||||
pathElements := strings.Split(comm.Process().Path, "/") // FIXME: path separator
|
||||
// only look at the last two path segments
|
||||
if len(pathElements) > 2 {
|
||||
pathElements = pathElements[len(pathElements)-2:]
|
||||
|
@ -537,5 +538,5 @@ matchLoop:
|
|||
log.Infof("firewall: permitting communication %s, match to domain was found: %s is related to %s", comm, domainElement, processElement)
|
||||
comm.Accept(fmt.Sprintf("domain is related to process: %s is related to %s", domainElement, processElement))
|
||||
}
|
||||
return
|
||||
return related
|
||||
}
|
||||
|
|
|
@ -80,10 +80,10 @@ func cleanPortsInUse() {
|
|||
portsInUseLock.Lock()
|
||||
defer portsInUseLock.Unlock()
|
||||
|
||||
threshhold := time.Now().Add(-cleanTimeout)
|
||||
threshold := time.Now().Add(-cleanTimeout)
|
||||
|
||||
for port, status := range portsInUse {
|
||||
if status.lastSeen.Before(threshhold) {
|
||||
if status.lastSeen.Before(threshold) {
|
||||
delete(portsInUse, port)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package firewall
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -24,6 +25,11 @@ const (
|
|||
denyServingIP = "deny-serving-ip"
|
||||
)
|
||||
|
||||
var (
|
||||
mtSaveProfile = "save profile"
|
||||
)
|
||||
|
||||
//nolint:gocognit // FIXME
|
||||
func prompt(comm *network.Communication, link *network.Link, pkt packet.Packet, fqdn string) {
|
||||
nTTL := time.Duration(promptTimeout()) * time.Second
|
||||
|
||||
|
@ -66,11 +72,11 @@ func prompt(comm *network.Communication, link *network.Link, pkt packet.Packet,
|
|||
case comm.Direction: // incoming
|
||||
n.Message = fmt.Sprintf("Application %s wants to accept connections from %s (on %d/%d)", comm.Process(), pkt.Info().RemoteIP(), pkt.Info().Protocol, pkt.Info().LocalPort())
|
||||
n.AvailableActions = []*notifications.Action{
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: permitServingIP,
|
||||
Text: "Permit",
|
||||
},
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: denyServingIP,
|
||||
Text: "Deny",
|
||||
},
|
||||
|
@ -78,11 +84,11 @@ func prompt(comm *network.Communication, link *network.Link, pkt packet.Packet,
|
|||
case fqdn == "": // direct connection
|
||||
n.Message = fmt.Sprintf("Application %s wants to connect to %s (on %d/%d)", comm.Process(), pkt.Info().RemoteIP(), pkt.Info().Protocol, pkt.Info().RemotePort())
|
||||
n.AvailableActions = []*notifications.Action{
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: permitIP,
|
||||
Text: "Permit",
|
||||
},
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: denyIP,
|
||||
Text: "Deny",
|
||||
},
|
||||
|
@ -94,15 +100,15 @@ func prompt(comm *network.Communication, link *network.Link, pkt packet.Packet,
|
|||
n.Message = fmt.Sprintf("Application %s wants to connect to %s", comm.Process(), comm.Domain)
|
||||
}
|
||||
n.AvailableActions = []*notifications.Action{
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: permitDomainAll,
|
||||
Text: "Permit all",
|
||||
},
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: permitDomainDistinct,
|
||||
Text: "Permit",
|
||||
},
|
||||
¬ifications.Action{
|
||||
{
|
||||
ID: denyDomainDistinct,
|
||||
Text: "Deny",
|
||||
},
|
||||
|
@ -182,7 +188,9 @@ func prompt(comm *network.Communication, link *network.Link, pkt packet.Packet,
|
|||
}
|
||||
|
||||
// save!
|
||||
go userProfile.Save("")
|
||||
module.StartMicroTask(&mtSaveProfile, func(ctx context.Context) error {
|
||||
return userProfile.Save("")
|
||||
})
|
||||
|
||||
case <-n.Expired():
|
||||
if link != nil {
|
||||
|
|
|
@ -37,6 +37,7 @@ var (
|
|||
ErrNoCompliance = fmt.Errorf("%w: no compliant resolvers for this query", ErrBlocked)
|
||||
)
|
||||
|
||||
// Query describes a dns query.
|
||||
type Query struct {
|
||||
FQDN string
|
||||
QType dns.Type
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/safing/portmaster/network/environment"
|
||||
)
|
||||
|
||||
// DNS Resolver Attributes
|
||||
const (
|
||||
ServerTypeDNS = "dns"
|
||||
ServerTypeTCP = "tcp"
|
||||
|
@ -85,6 +86,7 @@ func (brc *BasicResolverConn) LastFail() time.Time {
|
|||
return brc.lastFail
|
||||
}
|
||||
|
||||
// Query executes the given query against the resolver.
|
||||
func (brc *BasicResolverConn) Query(ctx context.Context, q *Query) (*RRCache, error) {
|
||||
// convenience
|
||||
resolver := brc.resolver
|
||||
|
|
|
@ -25,7 +25,7 @@ var (
|
|||
mtDNSRequest = "dns request"
|
||||
|
||||
listenAddress = "0.0.0.0:53"
|
||||
IPv4Localhost = net.IPv4(127, 0, 0, 1)
|
||||
ipv4Localhost = net.IPv4(127, 0, 0, 1)
|
||||
localhostRRs []dns.RR
|
||||
)
|
||||
|
||||
|
@ -135,7 +135,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, query *dns.Msg) er
|
|||
log.Warningf("nameserver: could not get remote address of request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
return nil
|
||||
}
|
||||
if !remoteAddr.IP.Equal(IPv4Localhost) {
|
||||
if !remoteAddr.IP.Equal(ipv4Localhost) {
|
||||
// if request is not coming from 127.0.0.1, check if it's really local
|
||||
|
||||
localAddr, ok := w.RemoteAddr().(*net.UDPAddr)
|
||||
|
|
|
@ -22,7 +22,7 @@ var (
|
|||
mtDNSRequest = "dns request"
|
||||
|
||||
listenAddress = "127.0.0.1:53"
|
||||
IPv4Localhost = net.IPv4(127, 0, 0, 1)
|
||||
ipv4Localhost = net.IPv4(127, 0, 0, 1)
|
||||
localhostRRs []dns.RR
|
||||
)
|
||||
|
||||
|
@ -127,7 +127,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, query *dns.Msg) er
|
|||
log.Warningf("nameserver: could not get remote address of request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
return nil
|
||||
}
|
||||
if !remoteAddr.IP.Equal(IPv4Localhost) {
|
||||
if !remoteAddr.IP.Equal(ipv4Localhost) {
|
||||
// if request is not coming from 127.0.0.1, check if it's really local
|
||||
|
||||
localAddr, ok := w.RemoteAddr().(*net.UDPAddr)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
|
@ -11,7 +12,8 @@ var (
|
|||
cleanerTickDuration = 10 * time.Second
|
||||
deleteLinksAfterEndedThreshold = 5 * time.Minute
|
||||
deleteCommsWithoutLinksThreshhold = 3 * time.Minute
|
||||
lastEstablishedUpdateThreshold = 30 * time.Second
|
||||
|
||||
mtSaveLink = "save network link"
|
||||
)
|
||||
|
||||
func cleaner() {
|
||||
|
@ -68,12 +70,17 @@ func cleanLinks() (activeComms map[string]struct{}) {
|
|||
link.Ended = now
|
||||
link.Unlock()
|
||||
log.Tracef("network.clean: marked %s as ended", link.DatabaseKey())
|
||||
go link.save()
|
||||
// save
|
||||
linkToSave := link
|
||||
module.StartMicroTask(&mtSaveLink, func(ctx context.Context) error {
|
||||
linkToSave.saveAndLog()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
return activeComms
|
||||
}
|
||||
|
||||
func cleanComms(activeLinks map[string]struct{}) (activeComms map[string]struct{}) {
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
)
|
||||
|
||||
// Communication describes a logical connection between a process and a domain.
|
||||
//nolint:maligned // TODO: fix alignment
|
||||
type Communication struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
@ -288,7 +289,10 @@ func (comm *Communication) SaveIfNeeded() {
|
|||
comm.Unlock()
|
||||
|
||||
if save {
|
||||
comm.save()
|
||||
err := comm.save()
|
||||
if err != nil {
|
||||
log.Warningf("network: failed to save comm %s: %s", comm, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ type StorageInterface struct {
|
|||
func (s *StorageInterface) Get(key string) (record.Record, error) {
|
||||
|
||||
splitted := strings.Split(key, "/")
|
||||
switch splitted[0] {
|
||||
switch splitted[0] { //nolint:gocritic // TODO: implement full key space
|
||||
case "tree":
|
||||
switch len(splitted) {
|
||||
case 2:
|
||||
|
|
|
@ -15,12 +15,14 @@ var (
|
|||
module *modules.Module
|
||||
)
|
||||
|
||||
// InitSubModule initializes module specific things with the given module. Intended to be used as part of the "network" module.
|
||||
func InitSubModule(m *modules.Module) {
|
||||
module = m
|
||||
module.RegisterEvent(networkChangedEvent)
|
||||
module.RegisterEvent(onlineStatusChangedEvent)
|
||||
}
|
||||
|
||||
// StartSubModule starts module specific things with the given module. Intended to be used as part of the "network" module.
|
||||
func StartSubModule() error {
|
||||
if module == nil {
|
||||
return errors.New("not initialized")
|
||||
|
|
35
network/environment/main_test.go
Normal file
35
network/environment/main_test.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package environment
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/safing/portbase/modules"
|
||||
"github.com/safing/portmaster/core"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// setup
|
||||
tmpDir, err := core.InitForTesting()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// setup package
|
||||
netModule := modules.Register("network", nil, nil, nil, "core")
|
||||
InitSubModule(netModule)
|
||||
err = StartSubModule()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// run tests
|
||||
rv := m.Run()
|
||||
|
||||
// teardown
|
||||
core.StopTesting()
|
||||
_ = os.RemoveAll(tmpDir)
|
||||
|
||||
// exit with test run return value
|
||||
os.Exit(rv)
|
||||
}
|
|
@ -95,7 +95,7 @@ func (l *Location) EstimateNetworkProximity(to *Location) (proximity int) {
|
|||
}
|
||||
}
|
||||
|
||||
return //nolint:nakedreturn
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
// PrimitiveNetworkProximity calculates the numerical distance between two IP addresses. Returns a proximity value between 0 (far away) and 100 (nearby).
|
||||
|
|
|
@ -3,7 +3,6 @@ package geoip
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portbase/modules"
|
||||
)
|
||||
|
@ -22,22 +21,12 @@ func start() error {
|
|||
return fmt.Errorf("goeip: failed to load databases: %s", err)
|
||||
}
|
||||
|
||||
module.RegisterEventHook(
|
||||
return module.RegisterEventHook(
|
||||
"updates",
|
||||
"resource update",
|
||||
"upgrade databases",
|
||||
upgradeDatabases,
|
||||
)
|
||||
|
||||
// TODO: replace with update subscription
|
||||
module.NewTask("update databases", func(ctx context.Context, task *modules.Task) {
|
||||
|
||||
dbFileLock.Lock()
|
||||
defer dbFileLock.Unlock()
|
||||
|
||||
}).Repeat(10 * time.Minute).MaxDelay(1 * time.Hour)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func upgradeDatabases(_ context.Context, _ interface{}) error {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
@ -14,11 +15,8 @@ import (
|
|||
// FirewallHandler defines the function signature for a firewall handle function
|
||||
type FirewallHandler func(pkt packet.Packet, link *Link)
|
||||
|
||||
var (
|
||||
linkTimeout = 10 * time.Minute
|
||||
)
|
||||
|
||||
// Link describes a distinct physical connection (e.g. TCP connection) - like an instance - of a Connection.
|
||||
//nolint:maligned // TODO: fix alignment
|
||||
type Link struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
@ -75,7 +73,13 @@ func (link *Link) SetFirewallHandler(handler FirewallHandler) {
|
|||
if link.firewallHandler == nil {
|
||||
link.firewallHandler = handler
|
||||
link.pktQueue = make(chan packet.Packet, 1000)
|
||||
go link.packetHandler()
|
||||
|
||||
// start handling
|
||||
module.StartWorker("", func(ctx context.Context) error {
|
||||
link.packetHandler()
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
link.firewallHandler = handler
|
||||
|
@ -98,8 +102,13 @@ func (link *Link) HandlePacket(pkt packet.Packet) {
|
|||
link.pktQueue <- pkt
|
||||
return
|
||||
}
|
||||
|
||||
log.Warningf("network: link %s does not have a firewallHandler, dropping packet", link)
|
||||
pkt.Drop()
|
||||
|
||||
err := pkt.Drop()
|
||||
if err != nil {
|
||||
log.Warningf("network: failed to drop packet %s: %s", pkt, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Accept accepts the link and adds the given reason.
|
||||
|
@ -195,41 +204,48 @@ func (link *Link) ApplyVerdict(pkt packet.Packet) {
|
|||
link.Lock()
|
||||
defer link.Unlock()
|
||||
|
||||
var err error
|
||||
|
||||
if link.VerdictPermanent {
|
||||
switch link.Verdict {
|
||||
case VerdictAccept:
|
||||
pkt.PermanentAccept()
|
||||
err = pkt.PermanentAccept()
|
||||
case VerdictBlock:
|
||||
pkt.PermanentBlock()
|
||||
err = pkt.PermanentBlock()
|
||||
case VerdictDrop:
|
||||
pkt.PermanentDrop()
|
||||
err = pkt.PermanentDrop()
|
||||
case VerdictRerouteToNameserver:
|
||||
pkt.RerouteToNameserver()
|
||||
err = pkt.RerouteToNameserver()
|
||||
case VerdictRerouteToTunnel:
|
||||
pkt.RerouteToTunnel()
|
||||
err = pkt.RerouteToTunnel()
|
||||
default:
|
||||
pkt.Drop()
|
||||
err = pkt.Drop()
|
||||
}
|
||||
} else {
|
||||
switch link.Verdict {
|
||||
case VerdictAccept:
|
||||
pkt.Accept()
|
||||
err = pkt.Accept()
|
||||
case VerdictBlock:
|
||||
pkt.Block()
|
||||
err = pkt.Block()
|
||||
case VerdictDrop:
|
||||
pkt.Drop()
|
||||
err = pkt.Drop()
|
||||
case VerdictRerouteToNameserver:
|
||||
pkt.RerouteToNameserver()
|
||||
err = pkt.RerouteToNameserver()
|
||||
case VerdictRerouteToTunnel:
|
||||
pkt.RerouteToTunnel()
|
||||
err = pkt.RerouteToTunnel()
|
||||
default:
|
||||
pkt.Drop()
|
||||
err = pkt.Drop()
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Warningf("network: failed to apply link verdict to packet %s: %s", pkt, err)
|
||||
}
|
||||
}
|
||||
|
||||
// SaveWhenFinished marks the Link for saving after all current actions are finished.
|
||||
func (link *Link) SaveWhenFinished() {
|
||||
// FIXME: check if we should lock here
|
||||
link.saveWhenFinished = true
|
||||
}
|
||||
|
||||
|
@ -243,11 +259,19 @@ func (link *Link) SaveIfNeeded() {
|
|||
link.Unlock()
|
||||
|
||||
if save {
|
||||
link.save()
|
||||
link.saveAndLog()
|
||||
}
|
||||
}
|
||||
|
||||
// Save saves the link object in the storage and propagates the change.
|
||||
// saveAndLog saves the link object in the storage and propagates the change. It does not return an error, but logs it.
|
||||
func (link *Link) saveAndLog() {
|
||||
err := link.save()
|
||||
if err != nil {
|
||||
log.Warningf("network: failed to save link %s: %s", link, err)
|
||||
}
|
||||
}
|
||||
|
||||
// save saves the link object in the storage and propagates the change.
|
||||
func (link *Link) save() error {
|
||||
// update link
|
||||
link.Lock()
|
||||
|
|
|
@ -85,6 +85,7 @@ func initControlLogFile() *os.File {
|
|||
return initializeLogFile(logFilePath, "control/portmaster-control", info.Version())
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
func logControlError(cErr error) {
|
||||
// check if error present
|
||||
if cErr == nil {
|
||||
|
@ -110,6 +111,7 @@ func logControlError(cErr error) {
|
|||
errorFile.Close()
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // TODO
|
||||
func logControlStack() {
|
||||
// check logging dir
|
||||
logFileBasePath := filepath.Join(logsRoot.Path, "fstree", "control")
|
||||
|
@ -126,10 +128,11 @@ func logControlStack() {
|
|||
}
|
||||
|
||||
// write error and close
|
||||
pprof.Lookup("goroutine").WriteTo(errorFile, 1)
|
||||
_ = pprof.Lookup("goroutine").WriteTo(errorFile, 2)
|
||||
errorFile.Close()
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
func runAndLogControlError(wrappedFunc func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
err := wrappedFunc(cmd, args)
|
||||
|
|
|
@ -65,8 +65,8 @@ func init() {
|
|||
|
||||
rootCmd.PersistentFlags().StringVar(&dataDir, "data", "", "set data directory")
|
||||
rootCmd.PersistentFlags().StringVar(&databaseDir, "db", "", "alias to --data (deprecated)")
|
||||
rootCmd.MarkPersistentFlagDirname("data")
|
||||
rootCmd.MarkPersistentFlagDirname("db")
|
||||
_ = rootCmd.MarkPersistentFlagDirname("data")
|
||||
_ = rootCmd.MarkPersistentFlagDirname("db")
|
||||
rootCmd.Flags().BoolVar(&showFullVersion, "version", false, "print version")
|
||||
rootCmd.Flags().BoolVar(&showShortVersion, "ver", false, "print version number only")
|
||||
}
|
||||
|
@ -85,11 +85,10 @@ func main() {
|
|||
// }()
|
||||
|
||||
// catch interrupt for clean shutdown
|
||||
signalCh := make(chan os.Signal)
|
||||
signalCh := make(chan os.Signal, 2)
|
||||
signal.Notify(
|
||||
signalCh,
|
||||
os.Interrupt,
|
||||
os.Kill,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
|
|
11
pmctl/run.go
11
pmctl/run.go
|
@ -124,7 +124,13 @@ func run(cmd *cobra.Command, opts *Options) (err error) {
|
|||
if pid != 0 {
|
||||
return fmt.Errorf("another instance of Portmaster Core is already running: PID %d", pid)
|
||||
}
|
||||
defer deleteInstanceLock(opts.ShortIdentifier)
|
||||
defer func() {
|
||||
err := deleteInstanceLock(opts.ShortIdentifier)
|
||||
if err != nil {
|
||||
log.Printf("failed to delete instance lock: %s\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// notify service after some time
|
||||
|
@ -192,6 +198,7 @@ func run(cmd *cobra.Command, opts *Options) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// nolint:gocyclo,gocognit // TODO: simplify
|
||||
func execute(opts *Options, args []string) (cont bool, err error) {
|
||||
file, err := registry.GetFile(platform(opts.Identifier))
|
||||
if err != nil {
|
||||
|
@ -236,7 +243,7 @@ func execute(opts *Options, args []string) (cont bool, err error) {
|
|||
}
|
||||
|
||||
// create command
|
||||
exc := exec.Command(file.Path(), args...)
|
||||
exc := exec.Command(file.Path(), args...) //nolint:gosec // everything is okay
|
||||
|
||||
if !runningInConsole && opts.AllowHidingWindow {
|
||||
// Windows only:
|
||||
|
|
|
@ -8,8 +8,9 @@ var (
|
|||
startupComplete = make(chan struct{}) // signal that the start procedure completed (is never closed, just signaled once)
|
||||
shuttingDown = make(chan struct{}) // signal that we are shutting down (will be closed, may not be closed directly, use initiateShutdown)
|
||||
shutdownInitiated = false // not to be used directly
|
||||
shutdownError error // may not be read or written to directly
|
||||
shutdownLock sync.Mutex
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
shutdownError error // may not be read or written to directly
|
||||
shutdownLock sync.Mutex
|
||||
)
|
||||
|
||||
func initiateShutdown(err error) {
|
||||
|
@ -23,6 +24,7 @@ func initiateShutdown(err error) {
|
|||
}
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
func getShutdownError() error {
|
||||
shutdownLock.Lock()
|
||||
defer shutdownLock.Unlock()
|
||||
|
|
|
@ -24,8 +24,7 @@ var (
|
|||
dbController *database.Controller
|
||||
dbControllerFlag = abool.NewBool(false)
|
||||
|
||||
deleteProcessesThreshold = 15 * time.Minute
|
||||
lastEstablishedUpdateThreshold = 30 * time.Second
|
||||
deleteProcessesThreshold = 15 * time.Minute
|
||||
)
|
||||
|
||||
// GetProcessFromStorage returns a process from the internal storage.
|
||||
|
|
|
@ -33,16 +33,14 @@ func (p *Process) FindProfiles(ctx context.Context) error {
|
|||
}
|
||||
|
||||
var userProfile *profile.Profile
|
||||
for r := range it.Next {
|
||||
it.Cancel()
|
||||
userProfile, err = profile.EnsureProfile(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
if it.Err() != nil {
|
||||
return it.Err()
|
||||
// get first result
|
||||
r := <-it.Next
|
||||
// cancel immediately
|
||||
it.Cancel()
|
||||
// ensure its a profile
|
||||
userProfile, err = profile.EnsureProfile(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create new profile if it does not exist.
|
||||
|
@ -54,7 +52,7 @@ func (p *Process) FindProfiles(ctx context.Context) error {
|
|||
}
|
||||
|
||||
if userProfile.MarkUsed() {
|
||||
userProfile.Save(profile.UserNamespace)
|
||||
_ = userProfile.Save(profile.UserNamespace)
|
||||
}
|
||||
|
||||
// Stamp
|
||||
|
@ -74,17 +72,7 @@ func (p *Process) FindProfiles(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func selectProfile(p *Process, profs []*profile.Profile) (selectedProfile *profile.Profile) {
|
||||
var highestScore int
|
||||
for _, prof := range profs {
|
||||
score := matchProfile(p, prof)
|
||||
if score > highestScore {
|
||||
selectedProfile = prof
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // FIXME
|
||||
func matchProfile(p *Process, prof *profile.Profile) (score int) {
|
||||
for _, fp := range prof.Fingerprints {
|
||||
score += matchFingerprint(p, fp)
|
||||
|
@ -92,6 +80,7 @@ func matchProfile(p *Process, prof *profile.Profile) (score int) {
|
|||
return
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // FIXME
|
||||
func matchFingerprint(p *Process, fp *profile.Fingerprint) (score int) {
|
||||
if !fp.MatchesOS() {
|
||||
return 0
|
||||
|
@ -100,8 +89,8 @@ func matchFingerprint(p *Process, fp *profile.Fingerprint) (score int) {
|
|||
switch fp.Type {
|
||||
case "full_path":
|
||||
if p.Path == fp.Value {
|
||||
return profile.GetFingerprintWeight(fp.Type)
|
||||
}
|
||||
return profile.GetFingerprintWeight(fp.Type)
|
||||
case "partial_path":
|
||||
// FIXME: if full_path matches, do not match partial paths
|
||||
return profile.GetFingerprintWeight(fp.Type)
|
||||
|
|
|
@ -155,7 +155,7 @@ func readDirNames(dir string) (names []string) {
|
|||
defer file.Close()
|
||||
names, err = file.Readdirnames(0)
|
||||
if err != nil {
|
||||
log.Warningf("process: could not get entries from direcotry %s: %s", dir, err)
|
||||
log.Warningf("process: could not get entries from directory %s: %s", dir, err)
|
||||
return []string{}
|
||||
}
|
||||
return
|
||||
|
|
|
@ -47,19 +47,6 @@ const (
|
|||
UDP6Data = "/proc/net/udp6"
|
||||
ICMP4Data = "/proc/net/icmp"
|
||||
ICMP6Data = "/proc/net/icmp6"
|
||||
|
||||
TCP_ESTABLISHED = iota + 1
|
||||
TCP_SYN_SENT
|
||||
TCP_SYN_RECV
|
||||
TCP_FIN_WAIT1
|
||||
TCP_FIN_WAIT2
|
||||
TCP_TIME_WAIT
|
||||
TCP_CLOSE
|
||||
TCP_CLOSE_WAIT
|
||||
TCP_LAST_ACK
|
||||
TCP_LISTEN
|
||||
TCP_CLOSING
|
||||
TCP_NEW_SYN_RECV
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
dupReqMap = make(map[int]*sync.Mutex)
|
||||
dupReqMap = make(map[int]*sync.WaitGroup)
|
||||
dupReqLock sync.Mutex
|
||||
)
|
||||
|
||||
|
@ -61,7 +61,7 @@ func (p *Process) ProfileSet() *profile.Set {
|
|||
return p.profileSet
|
||||
}
|
||||
|
||||
// Strings returns a string represenation of process.
|
||||
// Strings returns a string representation of process.
|
||||
func (p *Process) String() string {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
@ -79,7 +79,7 @@ func (p *Process) AddCommunication() {
|
|||
|
||||
// check if we should save
|
||||
save := false
|
||||
if p.LastCommEstablished < time.Now().Add(-3*time.Second).Unix() {
|
||||
if p.LastCommEstablished == 0 || p.LastCommEstablished < time.Now().Add(-3*time.Second).Unix() {
|
||||
save = true
|
||||
}
|
||||
|
||||
|
@ -206,6 +206,43 @@ func GetOrFindProcess(ctx context.Context, pid int) (*Process, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func deduplicateRequest(ctx context.Context, pid int) (finishRequest func()) {
|
||||
dupReqLock.Lock()
|
||||
defer dupReqLock.Unlock()
|
||||
|
||||
// get duplicate request waitgroup
|
||||
wg, requestActive := dupReqMap[pid]
|
||||
|
||||
// someone else is already on it!
|
||||
if requestActive {
|
||||
// log that we are waiting
|
||||
log.Tracer(ctx).Tracef("intel: waiting for duplicate request for PID %d to complete", pid)
|
||||
// wait
|
||||
wg.Wait()
|
||||
// done!
|
||||
return nil
|
||||
}
|
||||
|
||||
// we are currently the only one doing a request for this
|
||||
|
||||
// create new waitgroup
|
||||
wg = new(sync.WaitGroup)
|
||||
// add worker (us!)
|
||||
wg.Add(1)
|
||||
// add to registry
|
||||
dupReqMap[pid] = wg
|
||||
|
||||
// return function to mark request as finished
|
||||
return func() {
|
||||
dupReqLock.Lock()
|
||||
defer dupReqLock.Unlock()
|
||||
// mark request as done
|
||||
wg.Done()
|
||||
// delete from registry
|
||||
delete(dupReqMap, pid)
|
||||
}
|
||||
}
|
||||
|
||||
func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
if pid == -1 {
|
||||
return UnknownProcess, nil
|
||||
|
@ -219,35 +256,20 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
|||
return process, nil
|
||||
}
|
||||
|
||||
// dedup requests
|
||||
dupReqLock.Lock()
|
||||
mutex, requestActive := dupReqMap[pid]
|
||||
if !requestActive {
|
||||
mutex = new(sync.Mutex)
|
||||
mutex.Lock()
|
||||
dupReqMap[pid] = mutex
|
||||
dupReqLock.Unlock()
|
||||
} else {
|
||||
dupReqLock.Unlock()
|
||||
log.Tracer(ctx).Tracef("process: waiting for duplicate request for PID %d to complete", pid)
|
||||
mutex.Lock()
|
||||
// wait until duplicate request is finished, then fetch current Process and return
|
||||
mutex.Unlock()
|
||||
// dedupe!
|
||||
markRequestFinished := deduplicateRequest(ctx, pid)
|
||||
if markRequestFinished == nil {
|
||||
// we waited for another request, recheck the storage!
|
||||
process, ok = GetProcessFromStorage(pid)
|
||||
if ok {
|
||||
return process, nil
|
||||
}
|
||||
return nil, fmt.Errorf("previous request for process with PID %d failed", pid)
|
||||
// if cache is still empty, go ahead
|
||||
} else {
|
||||
// we are the first!
|
||||
defer markRequestFinished()
|
||||
}
|
||||
|
||||
// lock request for this pid
|
||||
defer func() {
|
||||
dupReqLock.Lock()
|
||||
delete(dupReqMap, pid)
|
||||
dupReqLock.Unlock()
|
||||
mutex.Unlock()
|
||||
}()
|
||||
|
||||
// create new process
|
||||
new := &Process{
|
||||
Pid: pid,
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
package process
|
||||
|
||||
// IsUser returns whether the process is run by a normal user.
|
||||
func (m *Process) IsUser() bool {
|
||||
return m.UserID >= 1000
|
||||
func (p *Process) IsUser() bool {
|
||||
return p.UserID >= 1000
|
||||
}
|
||||
|
||||
// IsAdmin returns whether the process is run by an admin user.
|
||||
func (m *Process) IsAdmin() bool {
|
||||
return m.UserID >= 0
|
||||
func (p *Process) IsAdmin() bool {
|
||||
return p.UserID >= 0
|
||||
}
|
||||
|
||||
// IsSystem returns whether the process is run by the operating system.
|
||||
func (m *Process) IsSystem() bool {
|
||||
return m.UserID == 0
|
||||
func (p *Process) IsSystem() bool {
|
||||
return p.UserID == 0
|
||||
}
|
||||
|
||||
// IsKernel returns whether the process is the Kernel.
|
||||
func (m *Process) IsKernel() bool {
|
||||
return m.Pid == 0
|
||||
func (p *Process) IsKernel() bool {
|
||||
return p.Pid == 0
|
||||
}
|
||||
|
||||
// specialOSInit does special OS specific Process initialization.
|
||||
func (m *Process) specialOSInit() {
|
||||
func (p *Process) specialOSInit() {
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ func makeDefaultFallbackProfile() *Profile {
|
|||
Related: status.SecurityLevelDynamic,
|
||||
},
|
||||
ServiceEndpoints: []*EndpointPermission{
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptAny,
|
||||
Protocol: 0,
|
||||
StartPort: 0,
|
||||
|
|
|
@ -15,8 +15,8 @@ type Endpoints []*EndpointPermission
|
|||
|
||||
// EndpointPermission holds a decision about an endpoint.
|
||||
type EndpointPermission struct {
|
||||
Type EPType
|
||||
Value string
|
||||
Type EPType
|
||||
|
||||
Protocol uint8
|
||||
StartPort uint16
|
||||
|
@ -55,10 +55,7 @@ const (
|
|||
|
||||
// IsSet returns whether the Endpoints object is "set".
|
||||
func (e Endpoints) IsSet() bool {
|
||||
if len(e) > 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return len(e) > 0
|
||||
}
|
||||
|
||||
// CheckDomain checks the if the given endpoint matches a EndpointPermission in the list.
|
||||
|
@ -246,7 +243,7 @@ func (ep EndpointPermission) MatchesIP(domain string, ip net.IP, protocol uint8,
|
|||
}
|
||||
|
||||
func (e Endpoints) String() string {
|
||||
var s []string
|
||||
s := make([]string, 0, len(e))
|
||||
for _, entry := range e {
|
||||
s = append(s, entry.String())
|
||||
}
|
||||
|
|
|
@ -155,15 +155,14 @@ func TestEndpointMatching(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEPString(t *testing.T) {
|
||||
var endpoints Endpoints
|
||||
endpoints = []*EndpointPermission{
|
||||
&EndpointPermission{
|
||||
var endpoints Endpoints = []*EndpointPermission{
|
||||
{
|
||||
Type: EptDomain,
|
||||
Value: "example.com",
|
||||
Protocol: 6,
|
||||
Permit: true,
|
||||
},
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptIPv4,
|
||||
Value: "1.1.1.1",
|
||||
Protocol: 17, // TCP
|
||||
|
@ -171,7 +170,7 @@ func TestEPString(t *testing.T) {
|
|||
EndPort: 53,
|
||||
Permit: false,
|
||||
},
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptDomain,
|
||||
Value: "example.org",
|
||||
Permit: false,
|
||||
|
@ -181,8 +180,7 @@ func TestEPString(t *testing.T) {
|
|||
t.Errorf("unexpected result: %s", endpoints.String())
|
||||
}
|
||||
|
||||
var noEndpoints Endpoints
|
||||
noEndpoints = []*EndpointPermission{}
|
||||
var noEndpoints Endpoints = []*EndpointPermission{}
|
||||
if noEndpoints.String() != "[]" {
|
||||
t.Errorf("unexpected result: %s", noEndpoints.String())
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func GetFingerprintWeight(fpType string) (weight int) {
|
|||
}
|
||||
|
||||
// AddFingerprint adds the given fingerprint to the profile.
|
||||
func (p *Profile) AddFingerprint(fp *Fingerprint) {
|
||||
func (profile *Profile) AddFingerprint(fp *Fingerprint) {
|
||||
if fp.OS == "" {
|
||||
fp.OS = osIdentifier
|
||||
}
|
||||
|
@ -44,5 +44,5 @@ func (p *Profile) AddFingerprint(fp *Fingerprint) {
|
|||
fp.LastUsed = time.Now().Unix()
|
||||
}
|
||||
|
||||
p.Fingerprints = append(p.Fingerprints, fp)
|
||||
profile.Fingerprints = append(profile.Fingerprints, fp)
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ func New() *Profile {
|
|||
}
|
||||
|
||||
// MakeProfileKey creates the correct key for a profile with the given namespace and ID.
|
||||
func MakeProfileKey(namespace, ID string) string {
|
||||
return fmt.Sprintf("core:profiles/%s/%s", namespace, ID)
|
||||
func MakeProfileKey(namespace, id string) string {
|
||||
return fmt.Sprintf("core:profiles/%s/%s", namespace, id)
|
||||
}
|
||||
|
||||
// Save saves the profile to the database
|
||||
|
@ -98,17 +98,17 @@ func (profile *Profile) DetailedString() string {
|
|||
}
|
||||
|
||||
// GetUserProfile loads a profile from the database.
|
||||
func GetUserProfile(ID string) (*Profile, error) {
|
||||
return getProfile(UserNamespace, ID)
|
||||
func GetUserProfile(id string) (*Profile, error) {
|
||||
return getProfile(UserNamespace, id)
|
||||
}
|
||||
|
||||
// GetStampProfile loads a profile from the database.
|
||||
func GetStampProfile(ID string) (*Profile, error) {
|
||||
return getProfile(StampNamespace, ID)
|
||||
func GetStampProfile(id string) (*Profile, error) {
|
||||
return getProfile(StampNamespace, id)
|
||||
}
|
||||
|
||||
func getProfile(namespace, ID string) (*Profile, error) {
|
||||
r, err := profileDB.Get(MakeProfileKey(namespace, ID))
|
||||
func getProfile(namespace, id string) (*Profile, error) {
|
||||
r, err := profileDB.Get(MakeProfileKey(namespace, id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -8,10 +8,6 @@ import (
|
|||
"github.com/safing/portmaster/status"
|
||||
)
|
||||
|
||||
var (
|
||||
emptyFlags = Flags{}
|
||||
)
|
||||
|
||||
// Set handles Profile chaining.
|
||||
type Set struct {
|
||||
sync.Mutex
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//nolint:unparam
|
||||
package profile
|
||||
|
||||
import (
|
||||
|
@ -30,25 +31,25 @@ func init() {
|
|||
Independent: status.SecurityLevelFortress,
|
||||
},
|
||||
Endpoints: []*EndpointPermission{
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptDomain,
|
||||
Value: "good.bad.example.com.",
|
||||
Permit: true,
|
||||
Created: time.Now().Unix(),
|
||||
},
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptDomain,
|
||||
Value: "*bad.example.com.",
|
||||
Permit: false,
|
||||
Created: time.Now().Unix(),
|
||||
},
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptDomain,
|
||||
Value: "example.com.",
|
||||
Permit: true,
|
||||
Created: time.Now().Unix(),
|
||||
},
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptAny,
|
||||
Permit: true,
|
||||
Protocol: 6,
|
||||
|
@ -67,13 +68,13 @@ func init() {
|
|||
// Internet: status.SecurityLevelsAll,
|
||||
// },
|
||||
Endpoints: []*EndpointPermission{
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptDomain,
|
||||
Value: "*bad2.example.com.",
|
||||
Permit: false,
|
||||
Created: time.Now().Unix(),
|
||||
},
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptAny,
|
||||
Permit: true,
|
||||
Protocol: 6,
|
||||
|
@ -83,7 +84,7 @@ func init() {
|
|||
},
|
||||
},
|
||||
ServiceEndpoints: []*EndpointPermission{
|
||||
&EndpointPermission{
|
||||
{
|
||||
Type: EptAny,
|
||||
Permit: true,
|
||||
Protocol: 17,
|
||||
|
@ -91,7 +92,7 @@ func init() {
|
|||
EndPort: 12347,
|
||||
Created: time.Now().Unix(),
|
||||
},
|
||||
&EndpointPermission{ // default deny
|
||||
{ // default deny
|
||||
Type: EptAny,
|
||||
Permit: false,
|
||||
Created: time.Now().Unix(),
|
||||
|
@ -173,6 +174,6 @@ func TestProfileSet(t *testing.T) {
|
|||
}
|
||||
|
||||
func getLineNumberOfCaller(levels int) int {
|
||||
_, _, line, _ := runtime.Caller(levels + 1)
|
||||
_, _, line, _ := runtime.Caller(levels + 1) //nolint:dogsled
|
||||
return line
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func initSpecialProfiles() (err error) {
|
|||
return err
|
||||
}
|
||||
globalProfile = makeDefaultGlobalProfile()
|
||||
globalProfile.Save(SpecialNamespace)
|
||||
_ = globalProfile.Save(SpecialNamespace)
|
||||
}
|
||||
|
||||
fallbackProfile, err = getSpecialProfile("fallback")
|
||||
|
@ -34,15 +34,15 @@ func initSpecialProfiles() (err error) {
|
|||
}
|
||||
fallbackProfile = makeDefaultFallbackProfile()
|
||||
ensureServiceEndpointsDenyAll(fallbackProfile)
|
||||
fallbackProfile.Save(SpecialNamespace)
|
||||
_ = fallbackProfile.Save(SpecialNamespace)
|
||||
}
|
||||
ensureServiceEndpointsDenyAll(fallbackProfile)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSpecialProfile(ID string) (*Profile, error) {
|
||||
return getProfile(SpecialNamespace, ID)
|
||||
func getSpecialProfile(id string) (*Profile, error) {
|
||||
return getProfile(SpecialNamespace, id)
|
||||
}
|
||||
|
||||
func ensureServiceEndpointsDenyAll(p *Profile) (changed bool) {
|
||||
|
@ -52,7 +52,7 @@ func ensureServiceEndpointsDenyAll(p *Profile) (changed bool) {
|
|||
ep.Protocol == 0 &&
|
||||
ep.StartPort == 0 &&
|
||||
ep.EndPort == 0 &&
|
||||
ep.Permit == false {
|
||||
!ep.Permit {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func updateListener(sub *database.Subscription) {
|
|||
profile.Unlock()
|
||||
|
||||
if profileChanged {
|
||||
profile.Save(SpecialNamespace)
|
||||
_ = profile.Save(SpecialNamespace)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -48,3 +48,7 @@ func initStatusHook() (err error) {
|
|||
hook, err = database.RegisterHook(query.New(statusDBKey), &statusHook{})
|
||||
return err
|
||||
}
|
||||
|
||||
func stopStatusHook() error {
|
||||
return hook.Cancel()
|
||||
}
|
||||
|
|
|
@ -9,10 +9,6 @@ import (
|
|||
_ "github.com/safing/portmaster/core"
|
||||
)
|
||||
|
||||
var (
|
||||
shutdownSignal = make(chan struct{})
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("status", nil, start, stop, "core")
|
||||
}
|
||||
|
@ -57,11 +53,5 @@ func start() error {
|
|||
}
|
||||
|
||||
func stop() error {
|
||||
select {
|
||||
case <-shutdownSignal:
|
||||
// already closed
|
||||
default:
|
||||
close(shutdownSignal)
|
||||
}
|
||||
return nil
|
||||
return stopStatusHook()
|
||||
}
|
||||
|
|
|
@ -129,7 +129,6 @@ func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName stri
|
|||
}
|
||||
|
||||
readCloser.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// RedirectToBase redirects the requests to the control app
|
||||
|
|
|
@ -49,21 +49,19 @@ func initVersionExport() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
module.RegisterEventHook(
|
||||
return module.RegisterEventHook(
|
||||
"updates",
|
||||
eventVersionUpdate,
|
||||
"export version status",
|
||||
export,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopVersionExport() error {
|
||||
return versionExportHook.Cancel()
|
||||
}
|
||||
|
||||
var exportMicroTaskName = "update version status"
|
||||
|
||||
// export is an event hook
|
||||
func export(_ context.Context, _ interface{}) error {
|
||||
// populate
|
||||
versionExport.lock.Lock()
|
||||
|
|
|
@ -100,9 +100,7 @@ func start() error {
|
|||
}).Repeat(24 * time.Hour).MaxDelay(1 * time.Hour).Schedule(time.Now().Add(10 * time.Second))
|
||||
|
||||
// react to upgrades
|
||||
initUpgrader()
|
||||
|
||||
return nil
|
||||
return initUpgrader()
|
||||
}
|
||||
|
||||
func stop() error {
|
||||
|
|
|
@ -28,16 +28,15 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
upgraderActive = abool.NewBool(false)
|
||||
dontUpgradeBefore = time.Now().Add(5 * time.Minute)
|
||||
pmCtrlUpdate *updater.File
|
||||
pmCoreUpdate *updater.File
|
||||
upgraderActive = abool.NewBool(false)
|
||||
pmCtrlUpdate *updater.File
|
||||
pmCoreUpdate *updater.File
|
||||
|
||||
rawVersionRegex = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+b?\*?$`)
|
||||
)
|
||||
|
||||
func initUpgrader() {
|
||||
module.RegisterEventHook(
|
||||
func initUpgrader() error {
|
||||
return module.RegisterEventHook(
|
||||
"updates",
|
||||
eventResourceUpdate,
|
||||
"run upgrades",
|
||||
|
|
Loading…
Add table
Reference in a new issue