mirror of
https://github.com/safing/portmaster
synced 2025-04-23 20:39:10 +00:00
* [service] Subscribe to systemd-resolver events * [service] Add disabled state to the resolver * [service] Add ETW DNS event listener * [service] DNS listener refactoring * [service] Add windows core dll project * [service] DNSListener refactoring, small bugfixes * [service] Change dns bypass rule * [service] Update gitignore * [service] Remove shim from integration module * [service] Add DNS packet analyzer * [service] Add self-check in dns monitor * [service] Fix go linter errors * [CI] Add github workflow for the windows core dll * [service] Minor fixes to the dns monitor
99 lines
2.5 KiB
Go
99 lines
2.5 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package dnsmonitor
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/safing/portmaster/service/integration"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
type ETWSession struct {
|
|
i integration.ETWFunctions
|
|
|
|
shutdownGuard atomic.Bool
|
|
shutdownMutex sync.Mutex
|
|
|
|
state uintptr
|
|
}
|
|
|
|
// NewSession creates new ETW event listener and initilizes it. This is a low level interface, make sure to call DestorySession when you are done using it.
|
|
func NewSession(etwInterface integration.ETWFunctions, callback func(domain string, result string)) (*ETWSession, error) {
|
|
etwSession := &ETWSession{
|
|
i: etwInterface,
|
|
}
|
|
|
|
// Make sure session from previous instances are not running.
|
|
_ = etwSession.i.StopOldSession()
|
|
|
|
// Initialize notification activated callback
|
|
win32Callback := windows.NewCallback(func(domain *uint16, result *uint16) uintptr {
|
|
callback(windows.UTF16PtrToString(domain), windows.UTF16PtrToString(result))
|
|
return 0
|
|
})
|
|
// The function only allocates memory it will not fail.
|
|
etwSession.state = etwSession.i.CreateState(win32Callback)
|
|
|
|
// Make sure DestroySession is called even if caller forgets to call it.
|
|
runtime.SetFinalizer(etwSession, func(s *ETWSession) {
|
|
_ = s.i.DestroySession(s.state)
|
|
})
|
|
|
|
// Initialize session.
|
|
err := etwSession.i.InitializeSession(etwSession.state)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to initialzie session: %q", err)
|
|
}
|
|
|
|
return etwSession, nil
|
|
}
|
|
|
|
// StartTrace starts the tracing session of dns events. This is a blocking call. It will not return until the trace is stopped.
|
|
func (l *ETWSession) StartTrace() error {
|
|
return l.i.StartTrace(l.state)
|
|
}
|
|
|
|
// IsRunning returns true if DestroySession has NOT been called.
|
|
func (l *ETWSession) IsRunning() bool {
|
|
return !l.shutdownGuard.Load()
|
|
}
|
|
|
|
// FlushTrace flushes the trace buffer.
|
|
func (l *ETWSession) FlushTrace() error {
|
|
l.shutdownMutex.Lock()
|
|
defer l.shutdownMutex.Unlock()
|
|
|
|
// Make sure session is still running.
|
|
if l.shutdownGuard.Load() {
|
|
return nil
|
|
}
|
|
|
|
return l.i.FlushTrace(l.state)
|
|
}
|
|
|
|
// StopTrace stopes the trace. This will cause StartTrace to return.
|
|
func (l *ETWSession) StopTrace() error {
|
|
return l.i.StopTrace(l.state)
|
|
}
|
|
|
|
// DestroySession closes the session and frees the allocated memory. Listener cannot be used after this function is called.
|
|
func (l *ETWSession) DestroySession() error {
|
|
l.shutdownMutex.Lock()
|
|
defer l.shutdownMutex.Unlock()
|
|
|
|
if l.shutdownGuard.Swap(true) {
|
|
return nil
|
|
}
|
|
|
|
err := l.i.DestroySession(l.state)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
l.state = 0
|
|
return nil
|
|
}
|