mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-01 15:04:19 -04:00
Compare commits
2 Commits
test/conne
...
trigger-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfeb60fbb5 | ||
|
|
ea41cf2d2c |
@@ -44,6 +44,7 @@ import (
|
||||
icemaker "github.com/netbirdio/netbird/client/internal/peer/ice"
|
||||
"github.com/netbirdio/netbird/client/internal/peerstore"
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
"github.com/netbirdio/netbird/client/internal/proxy"
|
||||
"github.com/netbirdio/netbird/client/internal/relay"
|
||||
"github.com/netbirdio/netbird/client/internal/rosenpass"
|
||||
"github.com/netbirdio/netbird/client/internal/routemanager"
|
||||
@@ -140,6 +141,11 @@ type EngineConfig struct {
|
||||
ProfileConfig *profilemanager.Config
|
||||
|
||||
LogPath string
|
||||
|
||||
// ProxyConfig contains system proxy settings for macOS
|
||||
ProxyEnabled bool
|
||||
ProxyHost string
|
||||
ProxyPort int
|
||||
}
|
||||
|
||||
// Engine is a mechanism responsible for reacting on Signal and Management stream events and managing connections to the remote peers.
|
||||
@@ -223,6 +229,9 @@ type Engine struct {
|
||||
|
||||
jobExecutor *jobexec.Executor
|
||||
jobExecutorWG sync.WaitGroup
|
||||
|
||||
// proxyManager manages system-wide browser proxy settings on macOS
|
||||
proxyManager *proxy.Manager
|
||||
}
|
||||
|
||||
// Peer is an instance of the Connection Peer
|
||||
@@ -313,6 +322,12 @@ func (e *Engine) Stop() error {
|
||||
e.updateManager.Stop()
|
||||
}
|
||||
|
||||
if e.proxyManager != nil {
|
||||
if err := e.proxyManager.DisableWebProxy(); err != nil {
|
||||
log.Warnf("failed to disable system proxy: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("cleaning up status recorder states")
|
||||
e.statusRecorder.ReplaceOfflinePeers([]peer.State{})
|
||||
e.statusRecorder.UpdateDNSStates([]peer.NSGroupState{})
|
||||
@@ -448,6 +463,10 @@ func (e *Engine) Start(netbirdConfig *mgmProto.NetbirdConfig, mgmtURL *url.URL)
|
||||
}
|
||||
e.stateManager.Start()
|
||||
|
||||
// Initialize proxy manager and register state for cleanup
|
||||
proxy.RegisterState(e.stateManager)
|
||||
e.proxyManager = proxy.NewManager(e.stateManager)
|
||||
|
||||
initialRoutes, dnsConfig, dnsFeatureFlag, err := e.readInitialSettings()
|
||||
if err != nil {
|
||||
e.close()
|
||||
@@ -1312,6 +1331,9 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
|
||||
// If no server of a server group responds this will disable the respective handler and retry later.
|
||||
e.dnsServer.ProbeAvailability()
|
||||
|
||||
// Update system proxy state based on routes after network map is fully applied
|
||||
e.updateSystemProxy(clientRoutes)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2303,6 +2325,26 @@ func createFile(path string) error {
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
// updateSystemProxy triggers a proxy enable/disable cycle after the network map is updated.
|
||||
func (e *Engine) updateSystemProxy(clientRoutes route.HAMap) {
|
||||
if runtime.GOOS != "darwin" || e.proxyManager == nil {
|
||||
log.Errorf("not updating proxy")
|
||||
return
|
||||
}
|
||||
|
||||
if err := e.proxyManager.EnableWebProxy(e.config.ProxyHost, e.config.ProxyPort); err != nil {
|
||||
log.Errorf("enable system proxy: %v", err)
|
||||
return
|
||||
}
|
||||
log.Error("system proxy enabled after network map update")
|
||||
|
||||
if err := e.proxyManager.DisableWebProxy(); err != nil {
|
||||
log.Errorf("disable system proxy: %v", err)
|
||||
return
|
||||
}
|
||||
log.Error("system proxy disabled after network map update")
|
||||
}
|
||||
|
||||
func convertToOfferAnswer(msg *sProto.Message) (*peer.OfferAnswer, error) {
|
||||
remoteCred, err := signal.UnMarshalCredential(msg)
|
||||
if err != nil {
|
||||
|
||||
262
client/internal/proxy/manager_darwin.go
Normal file
262
client/internal/proxy/manager_darwin.go
Normal file
@@ -0,0 +1,262 @@
|
||||
//go:build darwin && !ios
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||
)
|
||||
|
||||
const networksetupPath = "/usr/sbin/networksetup"
|
||||
|
||||
// Manager handles system-wide proxy configuration on macOS.
|
||||
type Manager struct {
|
||||
mu sync.Mutex
|
||||
stateManager *statemanager.Manager
|
||||
modifiedServices []string
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// NewManager creates a new proxy manager.
|
||||
func NewManager(stateManager *statemanager.Manager) *Manager {
|
||||
return &Manager{
|
||||
stateManager: stateManager,
|
||||
}
|
||||
}
|
||||
|
||||
// GetActiveNetworkServices returns the list of active network services.
|
||||
func GetActiveNetworkServices() ([]string, error) {
|
||||
cmd := exec.Command(networksetupPath, "-listallnetworkservices")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list network services: %w", err)
|
||||
}
|
||||
|
||||
lines := strings.Split(string(out), "\n")
|
||||
var services []string
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" || strings.HasPrefix(line, "*") || strings.Contains(line, "asterisk") {
|
||||
continue
|
||||
}
|
||||
services = append(services, line)
|
||||
}
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// EnableWebProxy enables web proxy for all active network services.
|
||||
func (m *Manager) EnableWebProxy(host string, port int) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if m.enabled {
|
||||
log.Debug("web proxy already enabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
services, err := GetActiveNetworkServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var modifiedServices []string
|
||||
for _, service := range services {
|
||||
if err := m.enableProxyForService(service, host, port); err != nil {
|
||||
log.Warnf("enable proxy for %s: %v", service, err)
|
||||
continue
|
||||
}
|
||||
modifiedServices = append(modifiedServices, service)
|
||||
}
|
||||
|
||||
m.modifiedServices = modifiedServices
|
||||
m.enabled = true
|
||||
m.updateState()
|
||||
|
||||
log.Infof("enabled web proxy on %d services -> %s:%d", len(modifiedServices), host, port)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) enableProxyForService(service, host string, port int) error {
|
||||
portStr := fmt.Sprintf("%d", port)
|
||||
|
||||
// Set web proxy (HTTP)
|
||||
cmd := exec.Command(networksetupPath, "-setwebproxy", service, host, portStr)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("set web proxy: %w, output: %s", err, out)
|
||||
}
|
||||
|
||||
// Enable web proxy
|
||||
cmd = exec.Command(networksetupPath, "-setwebproxystate", service, "on")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("enable web proxy state: %w, output: %s", err, out)
|
||||
}
|
||||
|
||||
// Set secure web proxy (HTTPS)
|
||||
cmd = exec.Command(networksetupPath, "-setsecurewebproxy", service, host, portStr)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("set secure web proxy: %w, output: %s", err, out)
|
||||
}
|
||||
|
||||
// Enable secure web proxy
|
||||
cmd = exec.Command(networksetupPath, "-setsecurewebproxystate", service, "on")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("enable secure web proxy state: %w, output: %s", err, out)
|
||||
}
|
||||
|
||||
log.Debugf("enabled proxy for service %s", service)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableWebProxy disables web proxy for all modified network services.
|
||||
func (m *Manager) DisableWebProxy() error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if !m.enabled {
|
||||
log.Debug("web proxy already disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
services := m.modifiedServices
|
||||
if len(services) == 0 {
|
||||
services, _ = GetActiveNetworkServices()
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
if err := m.disableProxyForService(service); err != nil {
|
||||
log.Warnf("disable proxy for %s: %v", service, err)
|
||||
}
|
||||
}
|
||||
|
||||
m.modifiedServices = nil
|
||||
m.enabled = false
|
||||
m.updateState()
|
||||
|
||||
log.Info("disabled web proxy")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) disableProxyForService(service string) error {
|
||||
// Disable web proxy (HTTP)
|
||||
cmd := exec.Command(networksetupPath, "-setwebproxystate", service, "off")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("disable web proxy: %w, output: %s", err, out)
|
||||
}
|
||||
|
||||
// Disable secure web proxy (HTTPS)
|
||||
cmd = exec.Command(networksetupPath, "-setsecurewebproxystate", service, "off")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("disable secure web proxy: %w, output: %s", err, out)
|
||||
}
|
||||
|
||||
log.Debugf("disabled proxy for service %s", service)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAutoproxyURL sets the automatic proxy configuration URL (PAC file).
|
||||
func (m *Manager) SetAutoproxyURL(pacURL string) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
services, err := GetActiveNetworkServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var modifiedServices []string
|
||||
for _, service := range services {
|
||||
cmd := exec.Command(networksetupPath, "-setautoproxyurl", service, pacURL)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Warnf("set autoproxy for %s: %v, output: %s", service, err, out)
|
||||
continue
|
||||
}
|
||||
|
||||
cmd = exec.Command(networksetupPath, "-setautoproxystate", service, "on")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Warnf("enable autoproxy for %s: %v, output: %s", service, err, out)
|
||||
continue
|
||||
}
|
||||
|
||||
modifiedServices = append(modifiedServices, service)
|
||||
log.Debugf("set autoproxy URL for %s -> %s", service, pacURL)
|
||||
}
|
||||
|
||||
m.modifiedServices = modifiedServices
|
||||
m.enabled = true
|
||||
m.updateState()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableAutoproxy disables automatic proxy configuration.
|
||||
func (m *Manager) DisableAutoproxy() error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
services := m.modifiedServices
|
||||
if len(services) == 0 {
|
||||
services, _ = GetActiveNetworkServices()
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
cmd := exec.Command(networksetupPath, "-setautoproxystate", service, "off")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Warnf("disable autoproxy for %s: %v, output: %s", service, err, out)
|
||||
}
|
||||
}
|
||||
|
||||
m.modifiedServices = nil
|
||||
m.enabled = false
|
||||
m.updateState()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEnabled returns whether the proxy is currently enabled.
|
||||
func (m *Manager) IsEnabled() bool {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.enabled
|
||||
}
|
||||
|
||||
// Restore restores proxy settings from a previous state.
|
||||
func (m *Manager) Restore(services []string) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
for _, service := range services {
|
||||
if err := m.disableProxyForService(service); err != nil {
|
||||
log.Warnf("restore proxy for %s: %v", service, err)
|
||||
}
|
||||
}
|
||||
|
||||
m.modifiedServices = nil
|
||||
m.enabled = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) updateState() {
|
||||
if m.stateManager == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if m.enabled && len(m.modifiedServices) > 0 {
|
||||
state := &ShutdownState{
|
||||
ModifiedServices: m.modifiedServices,
|
||||
}
|
||||
if err := m.stateManager.UpdateState(state); err != nil {
|
||||
log.Errorf("update proxy state: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := m.stateManager.DeleteState(&ShutdownState{}); err != nil {
|
||||
log.Debugf("delete proxy state: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
45
client/internal/proxy/manager_other.go
Normal file
45
client/internal/proxy/manager_other.go
Normal file
@@ -0,0 +1,45 @@
|
||||
//go:build !darwin || ios
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||
)
|
||||
|
||||
// Manager is a no-op proxy manager for non-macOS platforms.
|
||||
type Manager struct{}
|
||||
|
||||
// NewManager creates a new proxy manager (no-op on non-macOS).
|
||||
func NewManager(_ *statemanager.Manager) *Manager {
|
||||
return &Manager{}
|
||||
}
|
||||
|
||||
// EnableWebProxy is a no-op on non-macOS platforms.
|
||||
func (m *Manager) EnableWebProxy(host string, port int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableWebProxy is a no-op on non-macOS platforms.
|
||||
func (m *Manager) DisableWebProxy() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAutoproxyURL is a no-op on non-macOS platforms.
|
||||
func (m *Manager) SetAutoproxyURL(pacURL string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableAutoproxy is a no-op on non-macOS platforms.
|
||||
func (m *Manager) DisableAutoproxy() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEnabled always returns false on non-macOS platforms.
|
||||
func (m *Manager) IsEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Restore is a no-op on non-macOS platforms.
|
||||
func (m *Manager) Restore(services []string) error {
|
||||
return nil
|
||||
}
|
||||
88
client/internal/proxy/manager_test.go
Normal file
88
client/internal/proxy/manager_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
//go:build darwin && !ios
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetActiveNetworkServices(t *testing.T) {
|
||||
services, err := GetActiveNetworkServices()
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, services, "should have at least one network service")
|
||||
|
||||
// Check that services don't contain invalid entries
|
||||
for _, service := range services {
|
||||
assert.NotEmpty(t, service)
|
||||
assert.NotContains(t, service, "*")
|
||||
}
|
||||
}
|
||||
|
||||
func TestManager_EnableDisableWebProxy(t *testing.T) {
|
||||
// Skip this test in CI as it requires admin privileges
|
||||
if testing.Short() {
|
||||
t.Skip("skipping proxy test in short mode")
|
||||
}
|
||||
|
||||
m := NewManager(nil)
|
||||
assert.NotNil(t, m)
|
||||
assert.False(t, m.IsEnabled())
|
||||
|
||||
// This test would require admin privileges to actually enable the proxy
|
||||
// So we just test the basic state management
|
||||
}
|
||||
|
||||
func TestShutdownState_Name(t *testing.T) {
|
||||
state := &ShutdownState{}
|
||||
assert.Equal(t, "proxy_state", state.Name())
|
||||
}
|
||||
|
||||
func TestShutdownState_Cleanup_EmptyServices(t *testing.T) {
|
||||
state := &ShutdownState{
|
||||
ModifiedServices: []string{},
|
||||
}
|
||||
err := state.Cleanup()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
tests := []struct {
|
||||
s string
|
||||
substr string
|
||||
want bool
|
||||
}{
|
||||
{"Enabled: Yes", "Enabled: Yes", true},
|
||||
{"Enabled: No", "Enabled: Yes", false},
|
||||
{"Server: 127.0.0.1\nEnabled: Yes\nPort: 8080", "Enabled: Yes", true},
|
||||
{"", "Enabled: Yes", false},
|
||||
{"Enabled: Yes", "", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.s+"_"+tt.substr, func(t *testing.T) {
|
||||
got := contains(tt.s, tt.substr)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsProxyEnabled(t *testing.T) {
|
||||
tests := []struct {
|
||||
output string
|
||||
want bool
|
||||
}{
|
||||
{"Enabled: Yes\nServer: 127.0.0.1\nPort: 8080", true},
|
||||
{"Enabled: No\nServer: \nPort: 0", false},
|
||||
{"Server: 127.0.0.1\nEnabled: Yes\nPort: 8080", true},
|
||||
{"", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.output, func(t *testing.T) {
|
||||
got := isProxyEnabled(tt.output)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
105
client/internal/proxy/state_darwin.go
Normal file
105
client/internal/proxy/state_darwin.go
Normal file
@@ -0,0 +1,105 @@
|
||||
//go:build darwin && !ios
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||
)
|
||||
|
||||
// ShutdownState stores proxy state for cleanup on unclean shutdown.
|
||||
type ShutdownState struct {
|
||||
ModifiedServices []string `json:"modified_services"`
|
||||
}
|
||||
|
||||
// Name returns the state name for persistence.
|
||||
func (s *ShutdownState) Name() string {
|
||||
return "proxy_state"
|
||||
}
|
||||
|
||||
// Cleanup restores proxy settings after an unclean shutdown.
|
||||
func (s *ShutdownState) Cleanup() error {
|
||||
if len(s.ModifiedServices) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("cleaning up proxy state for %d services", len(s.ModifiedServices))
|
||||
|
||||
for _, service := range s.ModifiedServices {
|
||||
// Disable web proxy (HTTP)
|
||||
cmd := exec.Command(networksetupPath, "-setwebproxystate", service, "off")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Warnf("cleanup web proxy for %s: %v, output: %s", service, err, out)
|
||||
}
|
||||
|
||||
// Disable secure web proxy (HTTPS)
|
||||
cmd = exec.Command(networksetupPath, "-setsecurewebproxystate", service, "off")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Warnf("cleanup secure web proxy for %s: %v, output: %s", service, err, out)
|
||||
}
|
||||
|
||||
// Disable autoproxy
|
||||
cmd = exec.Command(networksetupPath, "-setautoproxystate", service, "off")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Warnf("cleanup autoproxy for %s: %v, output: %s", service, err, out)
|
||||
}
|
||||
|
||||
log.Debugf("cleaned up proxy for service %s", service)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterState registers the proxy state with the state manager.
|
||||
func RegisterState(stateManager *statemanager.Manager) {
|
||||
if stateManager == nil {
|
||||
return
|
||||
}
|
||||
stateManager.RegisterState(&ShutdownState{})
|
||||
}
|
||||
|
||||
// GetProxyState returns the current proxy state from the command line.
|
||||
func GetProxyState(service string) (webProxy, secureProxy, autoProxy bool, err error) {
|
||||
// Check web proxy state
|
||||
cmd := exec.Command(networksetupPath, "-getwebproxy", service)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false, false, false, fmt.Errorf("get web proxy: %w", err)
|
||||
}
|
||||
webProxy = isProxyEnabled(string(out))
|
||||
|
||||
// Check secure web proxy state
|
||||
cmd = exec.Command(networksetupPath, "-getsecurewebproxy", service)
|
||||
out, err = cmd.Output()
|
||||
if err != nil {
|
||||
return false, false, false, fmt.Errorf("get secure web proxy: %w", err)
|
||||
}
|
||||
secureProxy = isProxyEnabled(string(out))
|
||||
|
||||
// Check autoproxy state
|
||||
cmd = exec.Command(networksetupPath, "-getautoproxyurl", service)
|
||||
out, err = cmd.Output()
|
||||
if err != nil {
|
||||
return false, false, false, fmt.Errorf("get autoproxy: %w", err)
|
||||
}
|
||||
autoProxy = isProxyEnabled(string(out))
|
||||
|
||||
return webProxy, secureProxy, autoProxy, nil
|
||||
}
|
||||
|
||||
func isProxyEnabled(output string) bool {
|
||||
return !contains(output, "Enabled: No") && contains(output, "Enabled: Yes")
|
||||
}
|
||||
|
||||
func contains(s, substr string) bool {
|
||||
for i := 0; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
24
client/internal/proxy/state_other.go
Normal file
24
client/internal/proxy/state_other.go
Normal file
@@ -0,0 +1,24 @@
|
||||
//go:build !darwin || ios
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||
)
|
||||
|
||||
// ShutdownState is a no-op state for non-macOS platforms.
|
||||
type ShutdownState struct{}
|
||||
|
||||
// Name returns the state name.
|
||||
func (s *ShutdownState) Name() string {
|
||||
return "proxy_state"
|
||||
}
|
||||
|
||||
// Cleanup is a no-op on non-macOS platforms.
|
||||
func (s *ShutdownState) Cleanup() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterState is a no-op on non-macOS platforms.
|
||||
func RegisterState(stateManager *statemanager.Manager) {
|
||||
}
|
||||
Reference in New Issue
Block a user