diff --git a/status/const.go b/status/const.go new file mode 100644 index 00000000..1e8adedf --- /dev/null +++ b/status/const.go @@ -0,0 +1,14 @@ +package status + +// Definitions of Security and Status Levels +const ( + SecurityLevelOff uint8 = 0 + SecurityLevelDynamic uint8 = 1 + SecurityLevelSecure uint8 = 2 + SecurityLevelFortress uint8 = 3 + + StatusOff uint8 = 0 + StatusError uint8 = 1 + StatusWarning uint8 = 2 + StatusOk uint8 = 3 +) diff --git a/status/get.go b/status/get.go new file mode 100644 index 00000000..7666b2f1 --- /dev/null +++ b/status/get.go @@ -0,0 +1,64 @@ +package status + +import ( + "sync/atomic" + + "github.com/Safing/portbase/config" +) + +var ( + currentSecurityLevel *uint32 + selectedSecurityLevel *uint32 + threatLevel *uint32 + portmasterStatus *uint32 + gate17Status *uint32 +) + +func init() { + var ( + currentSecurityLevelValue uint32 + selectedSecurityLevelValue uint32 + threatLevelValue uint32 + portmasterStatusValue uint32 + gate17StatusValue uint32 + ) + + currentSecurityLevel = ¤tSecurityLevelValue + selectedSecurityLevel = &selectedSecurityLevelValue + threatLevel = &threatLevelValue + portmasterStatus = &portmasterStatusValue + gate17Status = &gate17StatusValue +} + +// GetCurrentSecurityLevel returns the current security level. +func GetCurrentSecurityLevel() uint8 { + return uint8(atomic.LoadUint32(currentSecurityLevel)) +} + +// GetSelectedSecurityLevel returns the selected security level. +func GetSelectedSecurityLevel() uint8 { + return uint8(atomic.LoadUint32(selectedSecurityLevel)) +} + +// GetThreatLevel returns the current threat level. +func GetThreatLevel() uint8 { + return uint8(atomic.LoadUint32(threatLevel)) +} + +// GetPortmasterStatus returns the current Portmaster status. +func GetPortmasterStatus() uint8 { + return uint8(atomic.LoadUint32(portmasterStatus)) +} + +// GetGate17Status returns the current Gate17 status. +func GetGate17Status() uint8 { + return uint8(atomic.LoadUint32(gate17Status)) +} + +// GetConfigByLevel returns whether the given security level dependent config option is on or off. +func GetConfigByLevel(name string) func() bool { + activatedLevel := config.GetAsInt(name, int64(SecurityLevelDynamic)) + return func() bool { + return uint8(activatedLevel()) <= GetCurrentSecurityLevel() + } +} diff --git a/status/get_test.go b/status/get_test.go new file mode 100644 index 00000000..e4348e2c --- /dev/null +++ b/status/get_test.go @@ -0,0 +1,16 @@ +package status + +import "testing" + +func TestGet(t *testing.T) { + + // only test for panics + GetCurrentSecurityLevel() + GetSelectedSecurityLevel() + GetThreatLevel() + GetPortmasterStatus() + GetGate17Status() + option := GetConfigByLevel("invalid") + option() + +} diff --git a/status/set.go b/status/set.go new file mode 100644 index 00000000..65a29a47 --- /dev/null +++ b/status/set.go @@ -0,0 +1,65 @@ +package status + +import "sync/atomic" + +// SetCurrentSecurityLevel sets the current security level. +func SetCurrentSecurityLevel(level uint8) { + sysStatusLock.Lock() + defer sysStatusLock.Unlock() + sysStatus.CurrentSecurityLevel = level + atomicUpdateCurrentSecurityLevel(level) +} + +// SetSelectedSecurityLevel sets the selected security level. +func SetSelectedSecurityLevel(level uint8) { + sysStatusLock.Lock() + defer sysStatusLock.Unlock() + sysStatus.SelectedSecurityLevel = level + atomicUpdateSelectedSecurityLevel(level) +} + +// SetThreatLevel sets the current threat level. +func SetThreatLevel(level uint8) { + sysStatusLock.Lock() + defer sysStatusLock.Unlock() + sysStatus.ThreatLevel = level + atomicUpdateThreatLevel(level) +} + +// SetPortmasterStatus sets the current Portmaster status. +func SetPortmasterStatus(status uint8) { + sysStatusLock.Lock() + defer sysStatusLock.Unlock() + sysStatus.PortmasterStatus = status + atomicUpdatePortmasterStatus(status) +} + +// SetGate17Status sets the current Gate17 status. +func SetGate17Status(status uint8) { + sysStatusLock.Lock() + defer sysStatusLock.Unlock() + sysStatus.Gate17Status = status + atomicUpdateGate17Status(status) +} + +// update functions for atomic stuff + +func atomicUpdateCurrentSecurityLevel(level uint8) { + atomic.StoreUint32(currentSecurityLevel, uint32(level)) +} + +func atomicUpdateSelectedSecurityLevel(level uint8) { + atomic.StoreUint32(selectedSecurityLevel, uint32(level)) +} + +func atomicUpdateThreatLevel(level uint8) { + atomic.StoreUint32(threatLevel, uint32(level)) +} + +func atomicUpdatePortmasterStatus(status uint8) { + atomic.StoreUint32(portmasterStatus, uint32(status)) +} + +func atomicUpdateGate17Status(status uint8) { + atomic.StoreUint32(gate17Status, uint32(status)) +} diff --git a/status/set_test.go b/status/set_test.go new file mode 100644 index 00000000..626882ab --- /dev/null +++ b/status/set_test.go @@ -0,0 +1,14 @@ +package status + +import "testing" + +func TestSet(t *testing.T) { + + // only test for panics + SetCurrentSecurityLevel(0) + SetSelectedSecurityLevel(0) + SetThreatLevel(0) + SetPortmasterStatus(0) + SetGate17Status(0) + +} diff --git a/status/status.go b/status/status.go new file mode 100644 index 00000000..5939e400 --- /dev/null +++ b/status/status.go @@ -0,0 +1,49 @@ +package status + +import "sync" + +var ( + sysStatusLock sync.RWMutex + sysStatus *SystemStatus +) + +func init() { + sysStatus = &SystemStatus{} +} + +// SystemStatus saves basic information about the current system status. +type SystemStatus struct { + // database.Base + CurrentSecurityLevel uint8 + SelectedSecurityLevel uint8 + + ThreatLevel uint8 `json:",omitempty" bson:",omitempty"` + ThreatReason string `json:",omitempty" bson:",omitempty"` + + PortmasterStatus uint8 `json:",omitempty" bson:",omitempty"` + PortmasterStatusMsg string `json:",omitempty" bson:",omitempty"` + + Gate17Status uint8 `json:",omitempty" bson:",omitempty"` + Gate17StatusMsg string `json:",omitempty" bson:",omitempty"` +} + +// FmtSecurityLevel returns the current security level as a string. +func FmtSecurityLevel() string { + current := GetCurrentSecurityLevel() + selected := GetSelectedSecurityLevel() + var s string + switch current { + case SecurityLevelOff: + s = "Off" + case SecurityLevelDynamic: + s = "Dynamic" + case SecurityLevelSecure: + s = "Secure" + case SecurityLevelFortress: + s = "Fortress" + } + if current != selected { + s += "*" + } + return s +} diff --git a/status/status_test.go b/status/status_test.go new file mode 100644 index 00000000..3ae7ae27 --- /dev/null +++ b/status/status_test.go @@ -0,0 +1,36 @@ +package status + +import "testing" + +func TestStatus(t *testing.T) { + + SetCurrentSecurityLevel(SecurityLevelOff) + SetSelectedSecurityLevel(SecurityLevelOff) + if FmtSecurityLevel() != "Off" { + t.Error("unexpected string representation") + } + + SetCurrentSecurityLevel(SecurityLevelDynamic) + SetSelectedSecurityLevel(SecurityLevelDynamic) + if FmtSecurityLevel() != "Dynamic" { + t.Error("unexpected string representation") + } + + SetCurrentSecurityLevel(SecurityLevelSecure) + SetSelectedSecurityLevel(SecurityLevelSecure) + if FmtSecurityLevel() != "Secure" { + t.Error("unexpected string representation") + } + + SetCurrentSecurityLevel(SecurityLevelFortress) + SetSelectedSecurityLevel(SecurityLevelFortress) + if FmtSecurityLevel() != "Fortress" { + t.Error("unexpected string representation") + } + + SetSelectedSecurityLevel(SecurityLevelDynamic) + if FmtSecurityLevel() != "Fortress*" { + t.Error("unexpected string representation") + } + +}