Continue with the new profile integration
This commit is contained in:
@@ -40,9 +40,9 @@ func cleanLinks() (activeComms map[string]struct{}) {
|
||||
for key, link := range links {
|
||||
|
||||
// delete dead links
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
deleteThis := link.Ended > 0 && link.Ended < deleteOlderThan
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
if deleteThis {
|
||||
log.Tracef("network.clean: deleted %s (ended at %d)", link.DatabaseKey(), link.Ended)
|
||||
go link.Delete()
|
||||
@@ -51,9 +51,9 @@ func cleanLinks() (activeComms map[string]struct{}) {
|
||||
|
||||
// not yet deleted, so its still a valid link regarding link count
|
||||
comm := link.Communication()
|
||||
comm.Lock()
|
||||
comm.lock.Lock()
|
||||
markActive(activeComms, comm.DatabaseKey())
|
||||
comm.Unlock()
|
||||
comm.lock.Unlock()
|
||||
|
||||
// check if link is dead
|
||||
found = false
|
||||
@@ -66,9 +66,9 @@ func cleanLinks() (activeComms map[string]struct{}) {
|
||||
|
||||
if !found {
|
||||
// mark end time
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
link.Ended = now
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
log.Tracef("network.clean: marked %s as ended", link.DatabaseKey())
|
||||
// save
|
||||
linkToSave := link
|
||||
@@ -95,9 +95,9 @@ func cleanComms(activeLinks map[string]struct{}) (activeComms map[string]struct{
|
||||
_, hasLinks := activeLinks[comm.DatabaseKey()]
|
||||
|
||||
// comm created
|
||||
comm.Lock()
|
||||
comm.lock.Lock()
|
||||
created := comm.Meta().Created
|
||||
comm.Unlock()
|
||||
comm.lock.Unlock()
|
||||
|
||||
if !hasLinks && created < threshold {
|
||||
log.Tracef("network.clean: deleted %s", comm.DatabaseKey())
|
||||
|
||||
@@ -8,48 +8,63 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/resolver"
|
||||
|
||||
"github.com/safing/portbase/database/record"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/intel"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/portmaster/process"
|
||||
"github.com/safing/portmaster/profile"
|
||||
)
|
||||
|
||||
// Communication describes a logical connection between a process and a domain.
|
||||
//nolint:maligned // TODO: fix alignment
|
||||
type Communication struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
lock sync.Mutex
|
||||
|
||||
Domain string
|
||||
Scope string
|
||||
Entity *intel.Entity
|
||||
Direction bool
|
||||
Intel *intel.Intel
|
||||
process *process.Process
|
||||
Verdict Verdict
|
||||
Reason string
|
||||
Inspect bool
|
||||
|
||||
Verdict Verdict
|
||||
Reason string
|
||||
ReasonID string // format source[:id[:id]]
|
||||
Inspect bool
|
||||
process *process.Process
|
||||
profileRevisionCounter uint64
|
||||
|
||||
FirstLinkEstablished int64
|
||||
LastLinkEstablished int64
|
||||
|
||||
profileUpdateVersion uint32
|
||||
saveWhenFinished bool
|
||||
saveWhenFinished bool
|
||||
}
|
||||
|
||||
// Lock locks the communication and the communication's Entity.
|
||||
func (comm *Communication) Lock() {
|
||||
comm.lock.Lock()
|
||||
comm.Entity.Lock()
|
||||
}
|
||||
|
||||
// Lock unlocks the communication and the communication's Entity.
|
||||
func (comm *Communication) Unlock() {
|
||||
comm.Entity.Unlock()
|
||||
comm.lock.Unlock()
|
||||
}
|
||||
|
||||
// Process returns the process that owns the connection.
|
||||
func (comm *Communication) Process() *process.Process {
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
return comm.process
|
||||
}
|
||||
|
||||
// ResetVerdict resets the verdict to VerdictUndecided.
|
||||
func (comm *Communication) ResetVerdict() {
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
comm.Verdict = VerdictUndecided
|
||||
comm.Reason = ""
|
||||
@@ -58,8 +73,8 @@ func (comm *Communication) ResetVerdict() {
|
||||
|
||||
// GetVerdict returns the current verdict.
|
||||
func (comm *Communication) GetVerdict() Verdict {
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
return comm.Verdict
|
||||
}
|
||||
@@ -93,8 +108,8 @@ func (comm *Communication) Drop(reason string) {
|
||||
|
||||
// UpdateVerdict sets a new verdict for this link, making sure it does not interfere with previous verdicts.
|
||||
func (comm *Communication) UpdateVerdict(newVerdict Verdict) {
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
if newVerdict > comm.Verdict {
|
||||
comm.Verdict = newVerdict
|
||||
@@ -108,8 +123,8 @@ func (comm *Communication) SetReason(reason string) {
|
||||
return
|
||||
}
|
||||
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
comm.Reason = reason
|
||||
comm.saveWhenFinished = true
|
||||
}
|
||||
@@ -120,8 +135,8 @@ func (comm *Communication) AddReason(reason string) {
|
||||
return
|
||||
}
|
||||
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
if comm.Reason != "" {
|
||||
comm.Reason += " | "
|
||||
@@ -129,21 +144,18 @@ func (comm *Communication) AddReason(reason string) {
|
||||
comm.Reason += reason
|
||||
}
|
||||
|
||||
// NeedsReevaluation returns whether the decision on this communication should be re-evaluated.
|
||||
func (comm *Communication) NeedsReevaluation() bool {
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
// UpdateAndCheck updates profiles and checks whether a reevaluation is needed.
|
||||
func (comm *Communication) UpdateAndCheck() (needsReevaluation bool) {
|
||||
revCnt := comm.Process().Profile().Update()
|
||||
|
||||
oldVersion := comm.profileUpdateVersion
|
||||
comm.profileUpdateVersion = profile.GetUpdateVersion()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
if comm.profileRevisionCounter != revCnt {
|
||||
comm.profileRevisionCounter = revCnt
|
||||
needsReevaluation = true
|
||||
}
|
||||
|
||||
if oldVersion == 0 {
|
||||
return false
|
||||
}
|
||||
if oldVersion != comm.profileUpdateVersion {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
// GetCommunicationByFirstPacket returns the matching communication from the internal storage.
|
||||
@@ -153,25 +165,26 @@ func GetCommunicationByFirstPacket(pkt packet.Packet) (*Communication, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var domain string
|
||||
var scope string
|
||||
|
||||
// Incoming
|
||||
if direction {
|
||||
switch netutils.ClassifyIP(pkt.Info().Src) {
|
||||
case netutils.HostLocal:
|
||||
domain = IncomingHost
|
||||
scope = IncomingHost
|
||||
case netutils.LinkLocal, netutils.SiteLocal, netutils.LocalMulticast:
|
||||
domain = IncomingLAN
|
||||
scope = IncomingLAN
|
||||
case netutils.Global, netutils.GlobalMulticast:
|
||||
domain = IncomingInternet
|
||||
scope = IncomingInternet
|
||||
case netutils.Invalid:
|
||||
domain = IncomingInvalid
|
||||
scope = IncomingInvalid
|
||||
}
|
||||
|
||||
communication, ok := GetCommunication(proc.Pid, domain)
|
||||
communication, ok := GetCommunication(proc.Pid, scope)
|
||||
if !ok {
|
||||
communication = &Communication{
|
||||
Domain: domain,
|
||||
Scope: scope,
|
||||
Entity: (&intel.Entity{}).Init(),
|
||||
Direction: Inbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
@@ -184,7 +197,7 @@ func GetCommunicationByFirstPacket(pkt packet.Packet) (*Communication, error) {
|
||||
}
|
||||
|
||||
// get domain
|
||||
ipinfo, err := intel.GetIPInfo(pkt.FmtRemoteIP())
|
||||
ipinfo, err := resolver.GetIPInfo(pkt.FmtRemoteIP())
|
||||
|
||||
// PeerToPeer
|
||||
if err != nil {
|
||||
@@ -192,19 +205,20 @@ func GetCommunicationByFirstPacket(pkt packet.Packet) (*Communication, error) {
|
||||
|
||||
switch netutils.ClassifyIP(pkt.Info().Dst) {
|
||||
case netutils.HostLocal:
|
||||
domain = PeerHost
|
||||
scope = PeerHost
|
||||
case netutils.LinkLocal, netutils.SiteLocal, netutils.LocalMulticast:
|
||||
domain = PeerLAN
|
||||
scope = PeerLAN
|
||||
case netutils.Global, netutils.GlobalMulticast:
|
||||
domain = PeerInternet
|
||||
scope = PeerInternet
|
||||
case netutils.Invalid:
|
||||
domain = PeerInvalid
|
||||
scope = PeerInvalid
|
||||
}
|
||||
|
||||
communication, ok := GetCommunication(proc.Pid, domain)
|
||||
communication, ok := GetCommunication(proc.Pid, scope)
|
||||
if !ok {
|
||||
communication = &Communication{
|
||||
Domain: domain,
|
||||
Scope: scope,
|
||||
Entity: (&intel.Entity{}).Init(),
|
||||
Direction: Outbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
@@ -221,7 +235,10 @@ func GetCommunicationByFirstPacket(pkt packet.Packet) (*Communication, error) {
|
||||
communication, ok := GetCommunication(proc.Pid, ipinfo.Domains[0])
|
||||
if !ok {
|
||||
communication = &Communication{
|
||||
Domain: ipinfo.Domains[0],
|
||||
Scope: ipinfo.Domains[0],
|
||||
Entity: (&intel.Entity{
|
||||
Domain: ipinfo.Domains[0],
|
||||
}).Init(),
|
||||
Direction: Outbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
@@ -251,7 +268,10 @@ func GetCommunicationByDNSRequest(ctx context.Context, ip net.IP, port uint16, f
|
||||
communication, ok := GetCommunication(proc.Pid, fqdn)
|
||||
if !ok {
|
||||
communication = &Communication{
|
||||
Domain: fqdn,
|
||||
Scope: fqdn,
|
||||
Entity: (&intel.Entity{
|
||||
Domain: fqdn,
|
||||
}).Init(),
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
saveWhenFinished: true,
|
||||
@@ -271,7 +291,7 @@ func GetCommunication(pid int, domain string) (comm *Communication, ok bool) {
|
||||
}
|
||||
|
||||
func (comm *Communication) makeKey() string {
|
||||
return fmt.Sprintf("%d/%s", comm.process.Pid, comm.Domain)
|
||||
return fmt.Sprintf("%d/%s", comm.process.Pid, comm.Scope)
|
||||
}
|
||||
|
||||
// SaveWhenFinished marks the Connection for saving after all current actions are finished.
|
||||
@@ -281,12 +301,12 @@ func (comm *Communication) SaveWhenFinished() {
|
||||
|
||||
// SaveIfNeeded saves the Connection if it is marked for saving when finished.
|
||||
func (comm *Communication) SaveIfNeeded() {
|
||||
comm.Lock()
|
||||
comm.lock.Lock()
|
||||
save := comm.saveWhenFinished
|
||||
if save {
|
||||
comm.saveWhenFinished = false
|
||||
}
|
||||
comm.Unlock()
|
||||
comm.lock.Unlock()
|
||||
|
||||
if save {
|
||||
err := comm.save()
|
||||
@@ -299,14 +319,14 @@ func (comm *Communication) SaveIfNeeded() {
|
||||
// Save saves the Connection object in the storage and propagates the change.
|
||||
func (comm *Communication) save() error {
|
||||
// update comm
|
||||
comm.Lock()
|
||||
comm.lock.Lock()
|
||||
if comm.process == nil {
|
||||
comm.Unlock()
|
||||
comm.lock.Unlock()
|
||||
return errors.New("cannot save connection without process")
|
||||
}
|
||||
|
||||
if !comm.KeyIsSet() {
|
||||
comm.SetKey(fmt.Sprintf("network:tree/%d/%s", comm.process.Pid, comm.Domain))
|
||||
comm.SetKey(fmt.Sprintf("network:tree/%d/%s", comm.process.Pid, comm.Scope))
|
||||
comm.UpdateMeta()
|
||||
}
|
||||
if comm.Meta().Deleted > 0 {
|
||||
@@ -315,7 +335,7 @@ func (comm *Communication) save() error {
|
||||
}
|
||||
key := comm.makeKey()
|
||||
comm.saveWhenFinished = false
|
||||
comm.Unlock()
|
||||
comm.lock.Unlock()
|
||||
|
||||
// save comm
|
||||
commsLock.RLock()
|
||||
@@ -336,8 +356,8 @@ func (comm *Communication) save() error {
|
||||
func (comm *Communication) Delete() {
|
||||
commsLock.Lock()
|
||||
defer commsLock.Unlock()
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
delete(comms, comm.makeKey())
|
||||
|
||||
@@ -347,16 +367,18 @@ func (comm *Communication) Delete() {
|
||||
|
||||
// AddLink applies the Communication to the Link and sets timestamps.
|
||||
func (comm *Communication) AddLink(link *Link) {
|
||||
comm.lock.Lock()
|
||||
defer comm.lock.Unlock()
|
||||
|
||||
// apply comm to link
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
link.comm = comm
|
||||
link.Verdict = comm.Verdict
|
||||
link.Inspect = comm.Inspect
|
||||
// FIXME: use new copy methods
|
||||
link.Entity.Domain = comm.Entity.Domain
|
||||
link.saveWhenFinished = true
|
||||
link.Unlock()
|
||||
|
||||
// update comm LastLinkEstablished
|
||||
comm.Lock()
|
||||
link.lock.Unlock()
|
||||
|
||||
// check if we should save
|
||||
if comm.LastLinkEstablished < time.Now().Add(-3*time.Second).Unix() {
|
||||
@@ -368,8 +390,6 @@ func (comm *Communication) AddLink(link *Link) {
|
||||
if comm.FirstLinkEstablished == 0 {
|
||||
comm.FirstLinkEstablished = comm.LastLinkEstablished
|
||||
}
|
||||
|
||||
comm.Unlock()
|
||||
}
|
||||
|
||||
// String returns a string representation of Communication.
|
||||
@@ -377,7 +397,7 @@ func (comm *Communication) String() string {
|
||||
comm.Lock()
|
||||
defer comm.Unlock()
|
||||
|
||||
switch comm.Domain {
|
||||
switch comm.Scope {
|
||||
case IncomingHost, IncomingLAN, IncomingInternet, IncomingInvalid:
|
||||
if comm.process == nil {
|
||||
return "? <- *"
|
||||
@@ -390,8 +410,8 @@ func (comm *Communication) String() string {
|
||||
return fmt.Sprintf("%s -> *", comm.process.String())
|
||||
default:
|
||||
if comm.process == nil {
|
||||
return fmt.Sprintf("? -> %s", comm.Domain)
|
||||
return fmt.Sprintf("? -> %s", comm.Scope)
|
||||
}
|
||||
return fmt.Sprintf("%s -> %s", comm.process.String(), comm.Domain)
|
||||
return fmt.Sprintf("%s -> %s", comm.process.String(), comm.Scope)
|
||||
}
|
||||
}
|
||||
|
||||
144
network/link.go
144
network/link.go
@@ -7,6 +7,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/intel"
|
||||
|
||||
"github.com/safing/portbase/database/record"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
@@ -16,21 +18,22 @@ import (
|
||||
type FirewallHandler func(pkt packet.Packet, link *Link)
|
||||
|
||||
// Link describes a distinct physical connection (e.g. TCP connection) - like an instance - of a Connection.
|
||||
//nolint:maligned // TODO: fix alignment
|
||||
type Link struct {
|
||||
type Link struct { //nolint:maligned // TODO: fix alignment
|
||||
record.Base
|
||||
sync.Mutex
|
||||
lock sync.Mutex
|
||||
|
||||
ID string
|
||||
ID string
|
||||
Entity *intel.Entity
|
||||
Direction bool
|
||||
|
||||
Verdict Verdict
|
||||
Reason string
|
||||
ReasonID string // format source[:id[:id]]
|
||||
Tunneled bool
|
||||
VerdictPermanent bool
|
||||
Inspect bool
|
||||
Started int64
|
||||
Ended int64
|
||||
RemoteAddress string
|
||||
|
||||
pktQueue chan packet.Packet
|
||||
firewallHandler FirewallHandler
|
||||
@@ -41,70 +44,82 @@ type Link struct {
|
||||
saveWhenFinished bool
|
||||
}
|
||||
|
||||
// Lock locks the link and the link's Entity.
|
||||
func (link *Link) Lock() {
|
||||
link.lock.Lock()
|
||||
link.Entity.Lock()
|
||||
}
|
||||
|
||||
// Lock unlocks the link and the link's Entity.
|
||||
func (link *Link) Unlock() {
|
||||
link.Entity.Unlock()
|
||||
link.lock.Unlock()
|
||||
}
|
||||
|
||||
// Communication returns the Communication the Link is part of
|
||||
func (link *Link) Communication() *Communication {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.comm
|
||||
}
|
||||
|
||||
// GetVerdict returns the current verdict.
|
||||
func (link *Link) GetVerdict() Verdict {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.Verdict
|
||||
}
|
||||
|
||||
// FirewallHandlerIsSet returns whether a firewall handler is set or not
|
||||
func (link *Link) FirewallHandlerIsSet() bool {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.firewallHandler != nil
|
||||
}
|
||||
|
||||
// SetFirewallHandler sets the firewall handler for this link
|
||||
func (link *Link) SetFirewallHandler(handler FirewallHandler) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if link.firewallHandler == nil {
|
||||
link.firewallHandler = handler
|
||||
link.pktQueue = make(chan packet.Packet, 1000)
|
||||
|
||||
// start handling
|
||||
module.StartWorker("", func(ctx context.Context) error {
|
||||
module.StartWorker("packet handler", func(ctx context.Context) error {
|
||||
link.packetHandler()
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
link.firewallHandler = handler
|
||||
}
|
||||
|
||||
// StopFirewallHandler unsets the firewall handler
|
||||
func (link *Link) StopFirewallHandler() {
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
link.firewallHandler = nil
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
link.pktQueue <- nil
|
||||
}
|
||||
|
||||
// HandlePacket queues packet of Link for handling
|
||||
func (link *Link) HandlePacket(pkt packet.Packet) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
// get handler
|
||||
link.lock.Lock()
|
||||
handler := link.firewallHandler
|
||||
link.lock.Unlock()
|
||||
|
||||
if link.firewallHandler != nil {
|
||||
// send to queue
|
||||
if handler != nil {
|
||||
link.pktQueue <- pkt
|
||||
return
|
||||
}
|
||||
|
||||
// no handler!
|
||||
log.Warningf("network: link %s does not have a firewallHandler, dropping packet", link)
|
||||
|
||||
err := pkt.Drop()
|
||||
if err != nil {
|
||||
log.Warningf("network: failed to drop packet %s: %s", pkt, err)
|
||||
@@ -119,7 +134,7 @@ func (link *Link) Accept(reason string) {
|
||||
|
||||
// Deny blocks or drops the link depending on the connection direction and adds the given reason.
|
||||
func (link *Link) Deny(reason string) {
|
||||
if link.comm != nil && link.comm.Direction {
|
||||
if link.Direction {
|
||||
link.Drop(reason)
|
||||
} else {
|
||||
link.Block(reason)
|
||||
@@ -151,8 +166,8 @@ func (link *Link) RerouteToTunnel(reason string) {
|
||||
|
||||
// UpdateVerdict sets a new verdict for this link, making sure it does not interfere with previous verdicts
|
||||
func (link *Link) UpdateVerdict(newVerdict Verdict) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if newVerdict > link.Verdict {
|
||||
link.Verdict = newVerdict
|
||||
@@ -166,8 +181,8 @@ func (link *Link) AddReason(reason string) {
|
||||
return
|
||||
}
|
||||
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if link.Reason != "" {
|
||||
link.Reason += " | "
|
||||
@@ -185,9 +200,9 @@ func (link *Link) packetHandler() {
|
||||
return
|
||||
}
|
||||
// get handler
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
handler := link.firewallHandler
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
// execute handler or verdict
|
||||
if handler != nil {
|
||||
handler(pkt, link)
|
||||
@@ -201,8 +216,8 @@ func (link *Link) packetHandler() {
|
||||
|
||||
// ApplyVerdict appies the link verdict to a packet.
|
||||
func (link *Link) ApplyVerdict(pkt packet.Packet) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
var err error
|
||||
|
||||
@@ -251,12 +266,12 @@ func (link *Link) SaveWhenFinished() {
|
||||
|
||||
// SaveIfNeeded saves the Link if it is marked for saving when finished.
|
||||
func (link *Link) SaveIfNeeded() {
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
save := link.saveWhenFinished
|
||||
if save {
|
||||
link.saveWhenFinished = false
|
||||
}
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
|
||||
if save {
|
||||
link.saveAndLog()
|
||||
@@ -274,18 +289,18 @@ func (link *Link) saveAndLog() {
|
||||
// save saves the link object in the storage and propagates the change.
|
||||
func (link *Link) save() error {
|
||||
// update link
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
if link.comm == nil {
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
return errors.New("cannot save link without comms")
|
||||
}
|
||||
|
||||
if !link.KeyIsSet() {
|
||||
link.SetKey(fmt.Sprintf("network:tree/%d/%s/%s", link.comm.Process().Pid, link.comm.Domain, link.ID))
|
||||
link.SetKey(fmt.Sprintf("network:tree/%d/%s/%s", link.comm.Process().Pid, link.comm.Scope, link.ID))
|
||||
link.UpdateMeta()
|
||||
}
|
||||
link.saveWhenFinished = false
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
|
||||
// save link
|
||||
linksLock.RLock()
|
||||
@@ -306,8 +321,8 @@ func (link *Link) save() error {
|
||||
func (link *Link) Delete() {
|
||||
linksLock.Lock()
|
||||
defer linksLock.Unlock()
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
delete(links, link.ID)
|
||||
|
||||
@@ -339,10 +354,15 @@ func GetOrCreateLinkByPacket(pkt packet.Packet) (*Link, bool) {
|
||||
// CreateLinkFromPacket creates a new Link based on Packet.
|
||||
func CreateLinkFromPacket(pkt packet.Packet) *Link {
|
||||
link := &Link{
|
||||
ID: pkt.GetLinkID(),
|
||||
ID: pkt.GetLinkID(),
|
||||
Entity: (&intel.Entity{
|
||||
IP: pkt.Info().RemoteIP(),
|
||||
Protocol: uint8(pkt.Info().Protocol),
|
||||
Port: pkt.Info().RemotePort(),
|
||||
}).Init(),
|
||||
Direction: pkt.IsInbound(),
|
||||
Verdict: VerdictUndecided,
|
||||
Started: time.Now().Unix(),
|
||||
RemoteAddress: pkt.FmtRemoteAddress(),
|
||||
saveWhenFinished: true,
|
||||
}
|
||||
return link
|
||||
@@ -350,59 +370,59 @@ func CreateLinkFromPacket(pkt packet.Packet) *Link {
|
||||
|
||||
// GetActiveInspectors returns the list of active inspectors.
|
||||
func (link *Link) GetActiveInspectors() []bool {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.activeInspectors
|
||||
}
|
||||
|
||||
// SetActiveInspectors sets the list of active inspectors.
|
||||
func (link *Link) SetActiveInspectors(new []bool) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
link.activeInspectors = new
|
||||
}
|
||||
|
||||
// GetInspectorData returns the list of inspector data.
|
||||
func (link *Link) GetInspectorData() map[uint8]interface{} {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.inspectorData
|
||||
}
|
||||
|
||||
// SetInspectorData set the list of inspector data.
|
||||
func (link *Link) SetInspectorData(new map[uint8]interface{}) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
link.inspectorData = new
|
||||
}
|
||||
|
||||
// String returns a string representation of Link.
|
||||
func (link *Link) String() string {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if link.comm == nil {
|
||||
return fmt.Sprintf("? <-> %s", link.RemoteAddress)
|
||||
return fmt.Sprintf("? <-> %s", link.Entity.IP.String())
|
||||
}
|
||||
switch link.comm.Domain {
|
||||
case "I":
|
||||
switch link.comm.Scope {
|
||||
case IncomingHost, IncomingLAN, IncomingInternet, IncomingInvalid:
|
||||
if link.comm.process == nil {
|
||||
return fmt.Sprintf("? <- %s", link.RemoteAddress)
|
||||
return fmt.Sprintf("? <- %s", link.Entity.IP.String())
|
||||
}
|
||||
return fmt.Sprintf("%s <- %s", link.comm.process.String(), link.RemoteAddress)
|
||||
case "D":
|
||||
return fmt.Sprintf("%s <- %s", link.comm.process.String(), link.Entity.IP.String())
|
||||
case PeerHost, PeerLAN, PeerInternet, PeerInvalid:
|
||||
if link.comm.process == nil {
|
||||
return fmt.Sprintf("? -> %s", link.RemoteAddress)
|
||||
return fmt.Sprintf("? -> %s", link.Entity.IP.String())
|
||||
}
|
||||
return fmt.Sprintf("%s -> %s", link.comm.process.String(), link.RemoteAddress)
|
||||
return fmt.Sprintf("%s -> %s", link.comm.process.String(), link.Entity.IP.String())
|
||||
default:
|
||||
if link.comm.process == nil {
|
||||
return fmt.Sprintf("? -> %s (%s)", link.comm.Domain, link.RemoteAddress)
|
||||
return fmt.Sprintf("? -> %s (%s)", link.comm.Scope, link.Entity.IP.String())
|
||||
}
|
||||
return fmt.Sprintf("%s to %s (%s)", link.comm.process.String(), link.comm.Domain, link.RemoteAddress)
|
||||
return fmt.Sprintf("%s to %s (%s)", link.comm.process.String(), link.comm.Scope, link.Entity.IP.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,36 +5,38 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/intel"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/portmaster/process"
|
||||
)
|
||||
|
||||
// GetOwnComm returns the communication for the given packet, that originates from
|
||||
// GetOwnComm returns the communication for the given packet, that originates from the Portmaster itself.
|
||||
func GetOwnComm(pkt packet.Packet) (*Communication, error) {
|
||||
var domain string
|
||||
var scope string
|
||||
|
||||
// Incoming
|
||||
if pkt.IsInbound() {
|
||||
switch netutils.ClassifyIP(pkt.Info().RemoteIP()) {
|
||||
case netutils.HostLocal:
|
||||
domain = IncomingHost
|
||||
scope = IncomingHost
|
||||
case netutils.LinkLocal, netutils.SiteLocal, netutils.LocalMulticast:
|
||||
domain = IncomingLAN
|
||||
scope = IncomingLAN
|
||||
case netutils.Global, netutils.GlobalMulticast:
|
||||
domain = IncomingInternet
|
||||
scope = IncomingInternet
|
||||
case netutils.Invalid:
|
||||
domain = IncomingInvalid
|
||||
scope = IncomingInvalid
|
||||
}
|
||||
|
||||
communication, ok := GetCommunication(os.Getpid(), domain)
|
||||
communication, ok := GetCommunication(os.Getpid(), scope)
|
||||
if !ok {
|
||||
proc, err := process.GetOrFindProcess(pkt.Ctx(), os.Getpid())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get own process")
|
||||
}
|
||||
communication = &Communication{
|
||||
Domain: domain,
|
||||
Scope: scope,
|
||||
Entity: (&intel.Entity{}).Init(),
|
||||
Direction: Inbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
@@ -48,23 +50,24 @@ func GetOwnComm(pkt packet.Packet) (*Communication, error) {
|
||||
// PeerToPeer
|
||||
switch netutils.ClassifyIP(pkt.Info().RemoteIP()) {
|
||||
case netutils.HostLocal:
|
||||
domain = PeerHost
|
||||
scope = PeerHost
|
||||
case netutils.LinkLocal, netutils.SiteLocal, netutils.LocalMulticast:
|
||||
domain = PeerLAN
|
||||
scope = PeerLAN
|
||||
case netutils.Global, netutils.GlobalMulticast:
|
||||
domain = PeerInternet
|
||||
scope = PeerInternet
|
||||
case netutils.Invalid:
|
||||
domain = PeerInvalid
|
||||
scope = PeerInvalid
|
||||
}
|
||||
|
||||
communication, ok := GetCommunication(os.Getpid(), domain)
|
||||
communication, ok := GetCommunication(os.Getpid(), scope)
|
||||
if !ok {
|
||||
proc, err := process.GetOrFindProcess(pkt.Ctx(), os.Getpid())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get own process")
|
||||
}
|
||||
communication = &Communication{
|
||||
Domain: domain,
|
||||
Scope: scope,
|
||||
Entity: (&intel.Entity{}).Init(),
|
||||
Direction: Outbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
|
||||
@@ -42,7 +42,7 @@ const (
|
||||
Outbound = false
|
||||
)
|
||||
|
||||
// Non-Domain Connections
|
||||
// Non-Domain Scopes
|
||||
const (
|
||||
IncomingHost = "IH"
|
||||
IncomingLAN = "IL"
|
||||
|
||||
@@ -3,6 +3,7 @@ package network
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/intel"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/portmaster/process"
|
||||
@@ -43,11 +44,12 @@ func GetUnknownCommunication(pkt packet.Packet) (*Communication, error) {
|
||||
return getOrCreateUnknownCommunication(pkt, PeerInvalid)
|
||||
}
|
||||
|
||||
func getOrCreateUnknownCommunication(pkt packet.Packet, connClass string) (*Communication, error) {
|
||||
connection, ok := GetCommunication(process.UnknownProcess.Pid, connClass)
|
||||
func getOrCreateUnknownCommunication(pkt packet.Packet, connScope string) (*Communication, error) {
|
||||
connection, ok := GetCommunication(process.UnknownProcess.Pid, connScope)
|
||||
if !ok {
|
||||
connection = &Communication{
|
||||
Domain: connClass,
|
||||
Scope: connScope,
|
||||
Entity: (&intel.Entity{}).Init(),
|
||||
Direction: pkt.IsInbound(),
|
||||
Verdict: VerdictDrop,
|
||||
Reason: ReasonUnknownProcess,
|
||||
|
||||
Reference in New Issue
Block a user