mirror of
https://github.com/safing/portmaster
synced 2025-09-02 10:39:22 +00:00
Revamp Connection.ID
Add Connection.Type and Connection.External Deprecate Connection.Scope
This commit is contained in:
parent
20383226f8
commit
fbf666ee68
6 changed files with 196 additions and 76 deletions
|
@ -100,18 +100,27 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
|
||||||
// Authenticate request - only requests from the local host, but with any of its IPs, are allowed.
|
// Authenticate request - only requests from the local host, but with any of its IPs, are allowed.
|
||||||
local, err := netenv.IsMyIP(remoteAddr.IP)
|
local, err := netenv.IsMyIP(remoteAddr.IP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tracer.Warningf("nameserver: failed to check if request for %s%s is local: %s", q.FQDN, q.QType, err)
|
tracer.Warningf("nameserver: failed to check if request for %s is local: %s", q.ID(), err)
|
||||||
return nil // Do no reply, drop request immediately.
|
return nil // Do no reply, drop request immediately.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create connection ID for dns request.
|
||||||
|
connID := fmt.Sprintf(
|
||||||
|
"%s-%d-#%d-%s",
|
||||||
|
remoteAddr.IP,
|
||||||
|
remoteAddr.Port,
|
||||||
|
request.Id,
|
||||||
|
q.ID(),
|
||||||
|
)
|
||||||
|
|
||||||
// Get connection for this request. This identifies the process behind the request.
|
// Get connection for this request. This identifies the process behind the request.
|
||||||
var conn *network.Connection
|
var conn *network.Connection
|
||||||
switch {
|
switch {
|
||||||
case local:
|
case local:
|
||||||
conn = network.NewConnectionFromDNSRequest(ctx, q.FQDN, nil, remoteAddr.IP, uint16(remoteAddr.Port))
|
conn = network.NewConnectionFromDNSRequest(ctx, q.FQDN, nil, connID, remoteAddr.IP, uint16(remoteAddr.Port))
|
||||||
|
|
||||||
case networkServiceMode():
|
case networkServiceMode():
|
||||||
conn, err = network.NewConnectionFromExternalDNSRequest(ctx, q.FQDN, nil, remoteAddr.IP)
|
conn, err = network.NewConnectionFromExternalDNSRequest(ctx, q.FQDN, nil, connID, remoteAddr.IP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tracer.Warningf("nameserver: failed to get host/profile for request for %s%s: %s", q.FQDN, q.QType, err)
|
tracer.Warningf("nameserver: failed to get host/profile for request for %s%s: %s", q.FQDN, q.QType, err)
|
||||||
return nil // Do no reply, drop request immediately.
|
return nil // Do no reply, drop request immediately.
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"github.com/safing/portbase/api"
|
"github.com/safing/portbase/api"
|
||||||
"github.com/safing/portbase/database/query"
|
"github.com/safing/portbase/database/query"
|
||||||
"github.com/safing/portbase/utils/debug"
|
"github.com/safing/portbase/utils/debug"
|
||||||
|
"github.com/safing/portmaster/network/state"
|
||||||
|
"github.com/safing/portmaster/process"
|
||||||
"github.com/safing/portmaster/status"
|
"github.com/safing/portmaster/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,6 +47,18 @@ func registerAPIEndpoints() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := api.RegisterEndpoint(api.Endpoint{
|
||||||
|
Path: "debug/network/state",
|
||||||
|
Read: api.PermitUser,
|
||||||
|
StructFunc: func(ar *api.Request) (i interface{}, err error) {
|
||||||
|
return state.GetInfo(), nil
|
||||||
|
},
|
||||||
|
Name: "Get Network State Table Data",
|
||||||
|
Description: "Returns the current network state tables from the OS.",
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,28 +170,30 @@ func AddNetworkDebugData(di *debug.Info, profile, where string) {
|
||||||
|
|
||||||
func buildNetworkDebugInfoData(debugConns []*Connection) string {
|
func buildNetworkDebugInfoData(debugConns []*Connection) string {
|
||||||
// Sort
|
// Sort
|
||||||
sort.Sort(connectionsByStarted(debugConns))
|
sort.Sort(connectionsByGroup(debugConns))
|
||||||
|
|
||||||
// Format lines
|
// Format lines
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
currentBinaryPath := "__"
|
currentPID := process.UndefinedProcessID
|
||||||
for _, conn := range debugConns {
|
for _, conn := range debugConns {
|
||||||
conn.Lock()
|
conn.Lock()
|
||||||
|
|
||||||
// Add process infomration if it differs from previous connection.
|
// Add process infomration if it differs from previous connection.
|
||||||
if currentBinaryPath != conn.ProcessContext.BinaryPath {
|
if currentPID != conn.ProcessContext.PID {
|
||||||
if currentBinaryPath != "__" {
|
if currentPID != process.UndefinedProcessID {
|
||||||
buf.WriteString("\n\n\n")
|
buf.WriteString("\n\n\n")
|
||||||
}
|
}
|
||||||
buf.WriteString("ProcessName: " + conn.ProcessContext.ProcessName)
|
buf.WriteString("ProfileName: " + conn.ProcessContext.ProfileName)
|
||||||
buf.WriteString("\nProfileName: " + conn.ProcessContext.ProfileName)
|
|
||||||
buf.WriteString("\nBinaryPath: " + conn.ProcessContext.BinaryPath)
|
|
||||||
buf.WriteString("\nProfile: " + conn.ProcessContext.Profile)
|
buf.WriteString("\nProfile: " + conn.ProcessContext.Profile)
|
||||||
buf.WriteString("\nSource: " + conn.ProcessContext.Source)
|
buf.WriteString("\nSource: " + conn.ProcessContext.Source)
|
||||||
|
buf.WriteString("\nProcessName: " + conn.ProcessContext.ProcessName)
|
||||||
|
buf.WriteString("\nBinaryPath: " + conn.ProcessContext.BinaryPath)
|
||||||
|
buf.WriteString("\nCmdLine: " + conn.ProcessContext.CmdLine)
|
||||||
|
buf.WriteString("\nPID: " + strconv.Itoa(conn.ProcessContext.PID))
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
|
|
||||||
// Set current path in order to not print the process information again.
|
// Set current PID in order to not print the process information again.
|
||||||
currentBinaryPath = conn.ProcessContext.BinaryPath
|
currentPID = conn.ProcessContext.PID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add connection.
|
// Add connection.
|
||||||
|
@ -192,7 +208,7 @@ func buildNetworkDebugInfoData(debugConns []*Connection) string {
|
||||||
|
|
||||||
func (conn *Connection) debugInfoLine() string {
|
func (conn *Connection) debugInfoLine() string {
|
||||||
var connectionData string
|
var connectionData string
|
||||||
if conn.ID != "" {
|
if conn.Type == DNSRequest { // conn.ID !=
|
||||||
// Format IP/Port pair for connections.
|
// Format IP/Port pair for connections.
|
||||||
connectionData = fmt.Sprintf(
|
connectionData = fmt.Sprintf(
|
||||||
"% 15s:%- 5s %s % 15s:%- 5s",
|
"% 15s:%- 5s %s % 15s:%- 5s",
|
||||||
|
@ -272,13 +288,28 @@ func (conn *Connection) fmtReasonProfileComponent() string {
|
||||||
return conn.Reason.Profile
|
return conn.Reason.Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
type connectionsByStarted []*Connection
|
type connectionsByGroup []*Connection
|
||||||
|
|
||||||
func (a connectionsByStarted) Len() int { return len(a) }
|
func (a connectionsByGroup) Len() int { return len(a) }
|
||||||
func (a connectionsByStarted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a connectionsByGroup) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a connectionsByStarted) Less(i, j int) bool {
|
func (a connectionsByGroup) Less(i, j int) bool {
|
||||||
|
// Sort by:
|
||||||
|
|
||||||
|
// 1. Profile ID
|
||||||
|
if a[i].ProcessContext.Profile != a[j].ProcessContext.Profile {
|
||||||
|
return a[i].ProcessContext.Profile < a[j].ProcessContext.Profile
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Process Binary
|
||||||
if a[i].ProcessContext.BinaryPath != a[j].ProcessContext.BinaryPath {
|
if a[i].ProcessContext.BinaryPath != a[j].ProcessContext.BinaryPath {
|
||||||
return a[i].ProcessContext.BinaryPath < a[j].ProcessContext.BinaryPath
|
return a[i].ProcessContext.BinaryPath < a[j].ProcessContext.BinaryPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Process ID
|
||||||
|
if a[i].ProcessContext.PID != a[j].ProcessContext.PID {
|
||||||
|
return a[i].ProcessContext.PID < a[j].ProcessContext.PID
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Started
|
||||||
return a[i].Started < a[j].Started
|
return a[i].Started < a[j].Started
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ type ProcessContext struct {
|
||||||
ProfileName string
|
ProfileName string
|
||||||
// BinaryPath is the path to the process binary.
|
// BinaryPath is the path to the process binary.
|
||||||
BinaryPath string
|
BinaryPath string
|
||||||
|
// CmdLine holds the execution parameters.
|
||||||
|
CmdLine string
|
||||||
// PID is the process identifier.
|
// PID is the process identifier.
|
||||||
PID int
|
PID int
|
||||||
// Profile is the ID of the main profile that
|
// Profile is the ID of the main profile that
|
||||||
|
@ -42,21 +44,37 @@ type ProcessContext struct {
|
||||||
Source string
|
Source string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConnectionType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Undefined ConnectionType = iota
|
||||||
|
IPConnection
|
||||||
|
DNSRequest
|
||||||
|
// ProxyRequest
|
||||||
|
)
|
||||||
|
|
||||||
// Connection describes a distinct physical network connection
|
// Connection describes a distinct physical network connection
|
||||||
// identified by the IP/Port pair.
|
// identified by the IP/Port pair.
|
||||||
type Connection struct { //nolint:maligned // TODO: fix alignment
|
type Connection struct { //nolint:maligned // TODO: fix alignment
|
||||||
record.Base
|
record.Base
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
// ID may hold unique connection id. It is only set for non-DNS
|
// ID holds a unique request/connection id and is considered immutable after
|
||||||
// request connections and is considered immutable after a
|
// creation.
|
||||||
// connection object has been created.
|
|
||||||
ID string
|
ID string
|
||||||
|
// Type defines the connection type.
|
||||||
|
Type ConnectionType
|
||||||
|
// External defines if the connection represents an external request or
|
||||||
|
// connection.
|
||||||
|
External bool
|
||||||
// Scope defines the scope of a connection. For DNS requests, the
|
// Scope defines the scope of a connection. For DNS requests, the
|
||||||
// scope is always set to the domain name. For direct packet
|
// scope is always set to the domain name. For direct packet
|
||||||
// connections the scope consists of the involved network environment
|
// connections the scope consists of the involved network environment
|
||||||
// and the packet direction. Once a connection object is created,
|
// and the packet direction. Once a connection object is created,
|
||||||
// Scope is considered immutable.
|
// Scope is considered immutable.
|
||||||
|
// Deprecated: This field holds duplicate information, which is accessible
|
||||||
|
// clearer through other attributes. Please use conn.Type, conn.Inbound
|
||||||
|
// and conn.Entity.Domain instead.
|
||||||
Scope string
|
Scope string
|
||||||
// IPVersion is set to the packet IP version. It is not set (0) for
|
// IPVersion is set to the packet IP version. It is not set (0) for
|
||||||
// connections created from a DNS request.
|
// connections created from a DNS request.
|
||||||
|
@ -176,8 +194,9 @@ type Reason struct {
|
||||||
func getProcessContext(ctx context.Context, proc *process.Process) ProcessContext {
|
func getProcessContext(ctx context.Context, proc *process.Process) ProcessContext {
|
||||||
// Gather process information.
|
// Gather process information.
|
||||||
pCtx := ProcessContext{
|
pCtx := ProcessContext{
|
||||||
BinaryPath: proc.Path,
|
|
||||||
ProcessName: proc.Name,
|
ProcessName: proc.Name,
|
||||||
|
BinaryPath: proc.Path,
|
||||||
|
CmdLine: proc.CmdLine,
|
||||||
PID: proc.Pid,
|
PID: proc.Pid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +215,7 @@ func getProcessContext(ctx context.Context, proc *process.Process) ProcessContex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConnectionFromDNSRequest returns a new connection based on the given dns request.
|
// NewConnectionFromDNSRequest returns a new connection based on the given dns request.
|
||||||
func NewConnectionFromDNSRequest(ctx context.Context, fqdn string, cnames []string, localIP net.IP, localPort uint16) *Connection {
|
func NewConnectionFromDNSRequest(ctx context.Context, fqdn string, cnames []string, connID string, localIP net.IP, localPort uint16) *Connection {
|
||||||
// Determine IP version.
|
// Determine IP version.
|
||||||
ipVersion := packet.IPv6
|
ipVersion := packet.IPv6
|
||||||
if localIP.To4() != nil {
|
if localIP.To4() != nil {
|
||||||
|
@ -223,6 +242,8 @@ func NewConnectionFromDNSRequest(ctx context.Context, fqdn string, cnames []stri
|
||||||
|
|
||||||
timestamp := time.Now().Unix()
|
timestamp := time.Now().Unix()
|
||||||
dnsConn := &Connection{
|
dnsConn := &Connection{
|
||||||
|
ID: connID,
|
||||||
|
Type: DNSRequest,
|
||||||
Scope: fqdn,
|
Scope: fqdn,
|
||||||
Entity: &intel.Entity{
|
Entity: &intel.Entity{
|
||||||
Domain: fqdn,
|
Domain: fqdn,
|
||||||
|
@ -239,10 +260,15 @@ func NewConnectionFromDNSRequest(ctx context.Context, fqdn string, cnames []stri
|
||||||
dnsConn.Internal = localProfile.Internal
|
dnsConn.Internal = localProfile.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always mark dns queries from the system resolver as internal.
|
||||||
|
if proc.IsSystemResolver() {
|
||||||
|
dnsConn.Internal = true
|
||||||
|
}
|
||||||
|
|
||||||
return dnsConn
|
return dnsConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnectionFromExternalDNSRequest(ctx context.Context, fqdn string, cnames []string, remoteIP net.IP) (*Connection, error) {
|
func NewConnectionFromExternalDNSRequest(ctx context.Context, fqdn string, cnames []string, connID string, remoteIP net.IP) (*Connection, error) {
|
||||||
remoteHost, err := process.GetNetworkHost(ctx, remoteIP)
|
remoteHost, err := process.GetNetworkHost(ctx, remoteIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -250,6 +276,9 @@ func NewConnectionFromExternalDNSRequest(ctx context.Context, fqdn string, cname
|
||||||
|
|
||||||
timestamp := time.Now().Unix()
|
timestamp := time.Now().Unix()
|
||||||
dnsConn := &Connection{
|
dnsConn := &Connection{
|
||||||
|
ID: connID,
|
||||||
|
Type: DNSRequest,
|
||||||
|
External: true,
|
||||||
Scope: fqdn,
|
Scope: fqdn,
|
||||||
Entity: &intel.Entity{
|
Entity: &intel.Entity{
|
||||||
Domain: fqdn,
|
Domain: fqdn,
|
||||||
|
@ -280,6 +309,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||||
|
|
||||||
var scope string
|
var scope string
|
||||||
var entity *intel.Entity
|
var entity *intel.Entity
|
||||||
|
var resolverInfo *resolver.ResolverInfo
|
||||||
|
|
||||||
if inbound {
|
if inbound {
|
||||||
|
|
||||||
|
@ -316,7 +346,11 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||||
entity.SetDstPort(entity.Port)
|
entity.SetDstPort(entity.Port)
|
||||||
|
|
||||||
// check if we can find a domain for that IP
|
// check if we can find a domain for that IP
|
||||||
ipinfo, err := resolver.GetIPInfo(proc.LocalProfileKey, pkt.Info().Dst.String())
|
ipinfo, err := resolver.GetIPInfo(proc.Profile().LocalProfile().ID, pkt.Info().Dst.String())
|
||||||
|
if err != nil {
|
||||||
|
// Try again with the global scope, in case DNS went through the system resolver.
|
||||||
|
ipinfo, err = resolver.GetIPInfo(resolver.IPInfoProfileScopeGlobal, pkt.Info().Dst.String())
|
||||||
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
lastResolvedDomain := ipinfo.MostRecentDomain()
|
lastResolvedDomain := ipinfo.MostRecentDomain()
|
||||||
if lastResolvedDomain != nil {
|
if lastResolvedDomain != nil {
|
||||||
|
@ -358,6 +392,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||||
// Create new connection object.
|
// Create new connection object.
|
||||||
newConn := &Connection{
|
newConn := &Connection{
|
||||||
ID: pkt.GetConnectionID(),
|
ID: pkt.GetConnectionID(),
|
||||||
|
Type: IPConnection,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
IPVersion: pkt.Info().Version,
|
IPVersion: pkt.Info().Version,
|
||||||
Inbound: inbound,
|
Inbound: inbound,
|
||||||
|
@ -493,14 +528,11 @@ func (conn *Connection) Save() {
|
||||||
conn.UpdateMeta()
|
conn.UpdateMeta()
|
||||||
|
|
||||||
if !conn.KeyIsSet() {
|
if !conn.KeyIsSet() {
|
||||||
// A connection without an ID has been created from
|
if conn.Type == DNSRequest {
|
||||||
// a DNS request rather than a packet. Choose the correct
|
conn.SetKey(makeKey(conn.process.Pid, "dns", conn.ID))
|
||||||
// connection store here.
|
|
||||||
if conn.ID == "" {
|
|
||||||
conn.SetKey(fmt.Sprintf("network:tree/%d/%s", conn.process.Pid, conn.Scope))
|
|
||||||
dnsConns.add(conn)
|
dnsConns.add(conn)
|
||||||
} else {
|
} else {
|
||||||
conn.SetKey(fmt.Sprintf("network:tree/%d/%s/%s", conn.process.Pid, conn.Scope, conn.ID))
|
conn.SetKey(makeKey(conn.process.Pid, "ip", conn.ID))
|
||||||
conns.add(conn)
|
conns.add(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,25 +15,18 @@ func newConnectionStore() *connectionStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *connectionStore) getID(conn *Connection) string {
|
|
||||||
if conn.ID != "" {
|
|
||||||
return conn.ID
|
|
||||||
}
|
|
||||||
return strconv.Itoa(conn.process.Pid) + "/" + conn.Scope
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cs *connectionStore) add(conn *Connection) {
|
func (cs *connectionStore) add(conn *Connection) {
|
||||||
cs.rw.Lock()
|
cs.rw.Lock()
|
||||||
defer cs.rw.Unlock()
|
defer cs.rw.Unlock()
|
||||||
|
|
||||||
cs.items[cs.getID(conn)] = conn
|
cs.items[conn.ID] = conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *connectionStore) delete(conn *Connection) {
|
func (cs *connectionStore) delete(conn *Connection) {
|
||||||
cs.rw.Lock()
|
cs.rw.Lock()
|
||||||
defer cs.rw.Unlock()
|
defer cs.rw.Unlock()
|
||||||
|
|
||||||
delete(cs.items, cs.getID(conn))
|
delete(cs.items, conn.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *connectionStore) get(id string) (*Connection, bool) {
|
func (cs *connectionStore) get(id string) (*Connection, bool) {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/safing/portmaster/network/state"
|
|
||||||
|
|
||||||
"github.com/safing/portbase/database"
|
"github.com/safing/portbase/database"
|
||||||
"github.com/safing/portbase/database/iterator"
|
"github.com/safing/portbase/database/iterator"
|
||||||
"github.com/safing/portbase/database/query"
|
"github.com/safing/portbase/database/query"
|
||||||
|
@ -27,39 +26,88 @@ type StorageInterface struct {
|
||||||
storage.InjectBase
|
storage.InjectBase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Database prefixes:
|
||||||
|
// Processes: network:tree/<PID>
|
||||||
|
// DNS Requests: network:tree/<PID>/dns/<ID>
|
||||||
|
// IP Connections: network:tree/<PID>/ip/<ID>
|
||||||
|
|
||||||
|
func makeKey(pid int, scope, id string) string {
|
||||||
|
if scope == "" {
|
||||||
|
return "network:tree/" + strconv.Itoa(pid)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("network:tree/%d/%s/%s", pid, scope, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDBKey(key string) (pid int, scope, id string, ok bool) {
|
||||||
|
// Split into segments.
|
||||||
|
segments := strings.Split(key, "/")
|
||||||
|
// Check for valid prefix.
|
||||||
|
if !strings.HasPrefix("tree", segments[0]) {
|
||||||
|
return 0, "", "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys have 2 or 4 segments.
|
||||||
|
switch len(segments) {
|
||||||
|
case 4:
|
||||||
|
id = segments[3]
|
||||||
|
|
||||||
|
fallthrough
|
||||||
|
case 3:
|
||||||
|
scope = segments[2]
|
||||||
|
// Sanity check.
|
||||||
|
switch scope {
|
||||||
|
case "dns", "ip", "":
|
||||||
|
// Parsed id matches possible values.
|
||||||
|
// The empty string is for matching a trailing slash for in query prefix.
|
||||||
|
// TODO: For queries, also prefixes of these values are valid.
|
||||||
|
default:
|
||||||
|
// Unknown scope.
|
||||||
|
return 0, "", "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
fallthrough
|
||||||
|
case 2:
|
||||||
|
var err error
|
||||||
|
if segments[1] == "" {
|
||||||
|
pid = process.UndefinedProcessID
|
||||||
|
} else {
|
||||||
|
pid, err = strconv.Atoi(segments[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, "", "", false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid, scope, id, true
|
||||||
|
case 1:
|
||||||
|
// This is a valid query prefix, but not process ID was given.
|
||||||
|
return process.UndefinedProcessID, "", "", true
|
||||||
|
default:
|
||||||
|
return 0, "", "", false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns a database record.
|
// Get returns a database record.
|
||||||
func (s *StorageInterface) Get(key string) (record.Record, error) {
|
func (s *StorageInterface) Get(key string) (record.Record, error) {
|
||||||
|
// Parse key and check if valid.
|
||||||
|
pid, scope, id, ok := parseDBKey(strings.TrimPrefix(key, "network:"))
|
||||||
|
if !ok || pid == process.UndefinedProcessID {
|
||||||
|
return nil, storage.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
splitted := strings.Split(key, "/")
|
switch scope {
|
||||||
switch splitted[0] { //nolint:gocritic // TODO: implement full key space
|
case "dns":
|
||||||
case "tree":
|
if r, ok := dnsConns.get(id); ok {
|
||||||
switch len(splitted) {
|
return r, nil
|
||||||
case 2:
|
}
|
||||||
pid, err := strconv.Atoi(splitted[1])
|
case "ip":
|
||||||
if err == nil {
|
if r, ok := conns.get(id); ok {
|
||||||
proc, ok := process.GetProcessFromStorage(pid)
|
return r, nil
|
||||||
if ok {
|
}
|
||||||
|
case "":
|
||||||
|
if proc, ok := process.GetProcessFromStorage(pid); ok {
|
||||||
return proc, nil
|
return proc, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 3:
|
|
||||||
if r, ok := dnsConns.get(splitted[1] + "/" + splitted[2]); ok {
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
if r, ok := conns.get(splitted[3]); ok {
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "system":
|
|
||||||
if len(splitted) >= 2 {
|
|
||||||
switch splitted[1] {
|
|
||||||
case "state":
|
|
||||||
return state.GetInfo(), nil
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, storage.ErrNotFound
|
return nil, storage.ErrNotFound
|
||||||
}
|
}
|
||||||
|
@ -74,9 +122,13 @@ func (s *StorageInterface) Query(q *query.Query, local, internal bool) (*iterato
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
|
func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
|
||||||
slashes := strings.Count(q.DatabaseKeyPrefix(), "/")
|
pid, scope, _, ok := parseDBKey(q.DatabaseKeyPrefix())
|
||||||
|
if !ok {
|
||||||
|
it.Finish(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if slashes <= 1 {
|
if pid == process.UndefinedProcessID {
|
||||||
// processes
|
// processes
|
||||||
for _, proc := range process.All() {
|
for _, proc := range process.All() {
|
||||||
proc.Lock()
|
proc.Lock()
|
||||||
|
@ -87,7 +139,7 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if slashes <= 2 {
|
if scope == "" || scope == "dns" {
|
||||||
// dns scopes only
|
// dns scopes only
|
||||||
for _, dnsConn := range dnsConns.clone() {
|
for _, dnsConn := range dnsConns.clone() {
|
||||||
dnsConn.Lock()
|
dnsConn.Lock()
|
||||||
|
@ -98,7 +150,7 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if slashes <= 3 {
|
if scope == "" || scope == "ip" {
|
||||||
// connections
|
// connections
|
||||||
for _, conn := range conns.clone() {
|
for _, conn := range conns.clone() {
|
||||||
conn.Lock()
|
conn.Lock()
|
||||||
|
|
|
@ -14,6 +14,10 @@ const (
|
||||||
// attributed to a PID for any reason.
|
// attributed to a PID for any reason.
|
||||||
UnidentifiedProcessID = -1
|
UnidentifiedProcessID = -1
|
||||||
|
|
||||||
|
// UndefinedProcessID is not used by any (virtual) process and signifies that
|
||||||
|
// the PID is unset.
|
||||||
|
UndefinedProcessID = -2
|
||||||
|
|
||||||
// NetworkHostProcessID is the PID used for requests served to the network.
|
// NetworkHostProcessID is the PID used for requests served to the network.
|
||||||
NetworkHostProcessID = -255
|
NetworkHostProcessID = -255
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue