From 965ea73a13e0566317d4bfdfe111df6aa17d7e94 Mon Sep 17 00:00:00 2001 From: stephb9959 Date: Thu, 3 Aug 2023 10:56:31 -0700 Subject: [PATCH] https://telecominfraproject.atlassian.net/browse/WIFI-12868 Signed-off-by: stephb9959 --- build | 2 +- openapi/owls.yaml | 45 +- src/framework/ConfigurationValidator.cpp | 578 +++++++++++++---------- src/framework/RESTAPI_SystemCommand.h | 85 ++-- src/framework/ow_constants.h | 3 + src/framework/utils.h | 65 +++ 6 files changed, 475 insertions(+), 303 deletions(-) diff --git a/build b/build index 3cacc0b..ca7bf83 100644 --- a/build +++ b/build @@ -1 +1 @@ -12 \ No newline at end of file +13 \ No newline at end of file diff --git a/openapi/owls.yaml b/openapi/owls.yaml index 53dcfd1..0cded52 100644 --- a/openapi/owls.yaml +++ b/openapi/owls.yaml @@ -146,12 +146,6 @@ components: - $ref: '#/components/schemas/StringList' - $ref: '#/components/schemas/TagValuePairList' - SystemCommandResults: - type: object - oneOf: - - $ref: '#/components/schemas/StringList' - - $ref: '#/components/schemas/TagValuePairList' - SystemInfoResults: type: object properties: @@ -180,6 +174,33 @@ components: type: integer format: int64 + SystemResources: + type: object + properties: + numberOfFileDescriptors: + type: integer + format: int64 + currRealMem: + type: integer + format: int64 + peakRealMem: + type: integer + format: int64 + currVirtMem: + type: integer + format: int64 + peakVirtMem: + type: integer + format: int64 + + SystemCommandResults: + type: object + oneOf: + - $ref: '#/components/schemas/SystemResources' + - $ref: '#/components/schemas/SystemInfoResults' + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + SystemCommandSetLogLevel: type: object properties: @@ -686,18 +707,12 @@ paths: type: string enum: - info + - extraConfiguration + - resources required: true - responses: 200: - description: Successful command execution - content: - application/json: - schema: - oneOf: - - $ref: '#/components/schemas/SystemInfoResults' - 400: - $ref: '#/components/responses/BadRequest' + $ref: '#/components/schemas/SystemCommandResults' 403: $ref: '#/components/responses/Unauthorized' 404: diff --git a/src/framework/ConfigurationValidator.cpp b/src/framework/ConfigurationValidator.cpp index db7cc3c..46b0f06 100644 --- a/src/framework/ConfigurationValidator.cpp +++ b/src/framework/ConfigurationValidator.cpp @@ -37,6 +37,10 @@ static std::string DefaultUCentralSchema = R"foo( "uuid": { "type": "integer" }, + "public_ip_lookup": { + "type": "string", + "format": "uc-fqdn" + }, "unit": { "$ref": "#/$defs/unit" }, @@ -634,26 +638,6 @@ static std::string DefaultUCentralSchema = R"foo( "type": "string", "format": "uc-timeout", "default": "6h" - }, - "relay-server": { - "type": "string", - "format": "ipv4", - "example": "192.168.2.1" - }, - "circuit-id-format": { - "type": "string", - "example": [ - "\\{Interface\\}:\\{VLAN-Id\\}:\\{SSID\\}:\\{Model\\}:\\{Name\\}:\\{AP-MAC\\}:\\{Location\\}", - "\\{AP-MAC\\};\\{SSID\\};\\{Crypto\\}", - "\\{Name\\} \\{ESSID\\}" - ] - }, - "remote-id-format": { - "type": "string", - "example": [ - "\\{Client-MAC-hex\\} \\{SSID\\}", - "\\{AP-MAC-hex\\} \\{SSID\\}" - ] } } }, @@ -1232,6 +1216,32 @@ static std::string DefaultUCentralSchema = R"foo( "secret" ] }, + "secondary": { + "type": "object", + "properties": { + "host": { + "type": "string", + "format": "uc-host", + "examples": [ + "192.168.1.10" + ] + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1024, + "examples": [ + 1812 + ] + }, + "secret": { + "type": "string", + "examples": [ + "secret" + ] + } + } + }, "request-attribute": { "type": "array", "items": { @@ -1309,6 +1319,25 @@ static std::string DefaultUCentralSchema = R"foo( "value": "Example Operator" } ] + }, + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "maximum": 255, + "minimum": 1 + }, + "hex-value": { + "type": "string" + } + }, + "examples": [ + { + "id": 32, + "value": "0a0b0c0d" + } + ] } ] } @@ -1658,6 +1687,236 @@ static std::string DefaultUCentralSchema = R"foo( } } }, + "service.captive.click": { + "type": "object", + "properties": { + "auth-mode": { + "type": "string", + "const": "click-to-continue" + } + } + }, + "service.captive.radius": { + "type": "object", + "properties": { + "auth-mode": { + "type": "string", + "const": "radius" + }, + "auth-server": { + "type": "string", + "format": "uc-host", + "examples": [ + "192.168.1.10" + ] + }, + "auth-port": { + "type": "integer", + "maximum": 65535, + "minimum": 1024, + "default": 1812 + }, + "auth-secret": { + "type": "string", + "examples": [ + "secret" + ] + }, + "acct-server": { + "type": "string", + "format": "uc-host", + "examples": [ + "192.168.1.10" + ] + }, + "acct-port": { + "type": "integer", + "maximum": 65535, + "minimum": 1024, + "default": 1812 + }, + "acct-secret": { + "type": "string", + "examples": [ + "secret" + ] + }, + "acct-interval": { + "type": "integer", + "default": 600 + } + } + }, + "service.captive.credentials": { + "type": "object", + "properties": { + "auth-mode": { + "type": "string", + "const": "credentials" + }, + "credentials": { + "type": "array", + "items": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string" + } + } + } + } + } + }, + "service.captive.uam": { + "type": "object", + "properties": { + "auth-mode": { + "type": "string", + "const": "uam" + }, + "uam-port": { + "type": "integer", + "maximum": 65535, + "minimum": 1024, + "default": 3990 + }, + "uam-secret": { + "type": "string" + }, + "uam-server": { + "type": "string" + }, + "nasid": { + "type": "string" + }, + "nasmac": { + "type": "string" + }, + "auth-server": { + "type": "string", + "format": "uc-host", + "examples": [ + "192.168.1.10" + ] + }, + "auth-port": { + "type": "integer", + "maximum": 65535, + "minimum": 1024, + "default": 1812 + }, + "auth-secret": { + "type": "string", + "examples": [ + "secret" + ] + }, + "acct-server": { + "type": "string", + "format": "uc-host", + "examples": [ + "192.168.1.10" + ] + }, + "acct-port": { + "type": "integer", + "maximum": 65535, + "minimum": 1024, + "default": 1812 + }, + "acct-secret": { + "type": "string", + "examples": [ + "secret" + ] + }, + "acct-interval": { + "type": "integer", + "default": 600 + }, + "ssid": { + "type": "string" + }, + "mac-format": { + "type": "string", + "enum": [ + "aabbccddeeff", + "aa-bb-cc-dd-ee-ff", + "aa:bb:cc:dd:ee:ff", + "AABBCCDDEEFF", + "AA:BB:CC:DD:EE:FF", + "AA-BB-CC-DD-EE-FF" + ] + }, + "final-redirect-url": { + "type": "string", + "enum": [ + "default", + "uam" + ] + }, + "mac-auth": { + "type": "boolean", + "default": "default" + }, + "radius-gw-proxy": { + "type": "boolean", + "default": false + } + } + }, + "service.captive": { + "allOf": [ + { + "oneOf": [ + { + "$ref": "#/$defs/service.captive.click" + }, + { + "$ref": "#/$defs/service.captive.radius" + }, + { + "$ref": "#/$defs/service.captive.credentials" + }, + { + "$ref": "#/$defs/service.captive.uam" + } + ] + }, + { + "type": "object", + "properties": { + "walled-garden-fqdn": { + "type": "array", + "items": { + "type": "string" + } + }, + "walled-garden-ipaddr": { + "type": "array", + "items": { + "type": "string", + "format": "uc-ip" + } + }, + "web-root": { + "type": "string", + "format": "uc-base64" + }, + "idle-timeout": { + "type": "integer", + "default": 600 + }, + "session-timeout": { + "type": "integer" + } + } + } + ] + }, "interface.ssid": { "type": "object", "properties": { @@ -1710,6 +1969,10 @@ static std::string DefaultUCentralSchema = R"foo( "isolate-clients": { "type": "boolean" }, + "strict-forwarding": { + "type": "boolean", + "default": false + }, "power-save": { "type": "boolean" }, @@ -1778,7 +2041,14 @@ static std::string DefaultUCentralSchema = R"foo( "$ref": "#/$defs/interface.ssid.rate-limit" }, "roaming": { - "$ref": "#/$defs/interface.ssid.roaming" + "anyOf": [ + { + "$ref": "#/$defs/interface.ssid.roaming" + }, + { + "type": "boolean" + } + ] }, "radius": { "$ref": "#/$defs/interface.ssid.radius" @@ -1795,6 +2065,9 @@ static std::string DefaultUCentralSchema = R"foo( "access-control-list": { "$ref": "#/$defs/interface.ssid.acl" }, + "captive": { + "$ref": "#/$defs/service.captive" + }, "hostapd-bss-raw": { "type": "array", "items": { @@ -2084,6 +2357,10 @@ static std::string DefaultUCentralSchema = R"foo( "examples": [ "01234567890123456789012345678901" ] + }, + "mutual-tls": { + "type": "boolean", + "default": true } } }, @@ -2693,236 +2970,6 @@ static std::string DefaultUCentralSchema = R"foo( } } }, - "service.captive.click": { - "type": "object", - "properties": { - "auth-mode": { - "type": "string", - "const": "click-to-continue" - } - } - }, - "service.captive.radius": { - "type": "object", - "properties": { - "auth-mode": { - "type": "string", - "const": "radius" - }, - "auth-server": { - "type": "string", - "format": "uc-host", - "examples": [ - "192.168.1.10" - ] - }, - "auth-port": { - "type": "integer", - "maximum": 65535, - "minimum": 1024, - "default": 1812 - }, - "auth-secret": { - "type": "string", - "examples": [ - "secret" - ] - }, - "acct-server": { - "type": "string", - "format": "uc-host", - "examples": [ - "192.168.1.10" - ] - }, - "acct-port": { - "type": "integer", - "maximum": 65535, - "minimum": 1024, - "default": 1812 - }, - "acct-secret": { - "type": "string", - "examples": [ - "secret" - ] - }, - "acct-interval": { - "type": "integer", - "default": 600 - } - } - }, - "service.captive.credentials": { - "type": "object", - "properties": { - "auth-mode": { - "type": "string", - "const": "credentials" - }, - "credentials": { - "type": "array", - "items": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "password": { - "type": "string" - } - } - } - } - } - }, - "service.captive.uam": { - "type": "object", - "properties": { - "auth-mode": { - "type": "string", - "const": "uam" - }, - "uam-port": { - "type": "integer", - "maximum": 65535, - "minimum": 1024, - "default": 3990 - }, - "uam-secret": { - "type": "string" - }, - "uam-server": { - "type": "string" - }, - "nasid": { - "type": "string" - }, - "nasmac": { - "type": "string" - }, - "auth-server": { - "type": "string", - "format": "uc-host", - "examples": [ - "192.168.1.10" - ] - }, - "auth-port": { - "type": "integer", - "maximum": 65535, - "minimum": 1024, - "default": 1812 - }, - "auth-secret": { - "type": "string", - "examples": [ - "secret" - ] - }, - "acct-server": { - "type": "string", - "format": "uc-host", - "examples": [ - "192.168.1.10" - ] - }, - "acct-port": { - "type": "integer", - "maximum": 65535, - "minimum": 1024, - "default": 1812 - }, - "acct-secret": { - "type": "string", - "examples": [ - "secret" - ] - }, - "acct-interval": { - "type": "integer", - "default": 600 - }, - "ssid": { - "type": "string" - }, - "mac-format": { - "type": "string", - "enum": [ - "aabbccddeeff", - "aa-bb-cc-dd-ee-ff", - "aa:bb:cc:dd:ee:ff", - "AABBCCDDEEFF", - "AA:BB:CC:DD:EE:FF", - "AA-BB-CC-DD-EE-FF" - ] - }, - "final-redirect-url": { - "type": "string", - "enum": [ - "default", - "uam" - ] - }, - "mac-auth": { - "type": "boolean", - "default": "default" - }, - "radius-gw-proxy": { - "type": "boolean", - "default": false - } - } - }, - "service.captive": { - "allOf": [ - { - "oneOf": [ - { - "$ref": "#/$defs/service.captive.click" - }, - { - "$ref": "#/$defs/service.captive.radius" - }, - { - "$ref": "#/$defs/service.captive.credentials" - }, - { - "$ref": "#/$defs/service.captive.uam" - } - ] - }, - { - "type": "object", - "properties": { - "walled-garden-fqdn": { - "type": "array", - "items": { - "type": "string" - } - }, - "walled-garden-ipaddr": { - "type": "array", - "items": { - "type": "string", - "format": "uc-ip" - } - }, - "web-root": { - "type": "string", - "format": "uc-base64" - }, - "idle-timeout": { - "type": "integer", - "default": 600 - }, - "session-timeout": { - "type": "integer" - } - } - } - ] - }, "service.gps": { "type": "object", "properties": { @@ -2941,6 +2988,32 @@ static std::string DefaultUCentralSchema = R"foo( } } }, + "service.dhcp-relay": { + "type": "object", + "properties": { + "select-ports": { + "type": "array", + "items": { + "type": "string" + } + }, + "vlans": { + "type": "array", + "items": { + "type": "object", + "properties": { + "vlan": { + "type": "number" + }, + "relay-server": { + "type": "string", + "format": "uc-ip" + } + } + } + } + } + }, "service": { "type": "object", "properties": { @@ -3000,6 +3073,9 @@ static std::string DefaultUCentralSchema = R"foo( }, "gps": { "$ref": "#/$defs/service.gps" + }, + "dhcp-relay": { + "$ref": "#/$defs/service.dhcp-relay" } } }, diff --git a/src/framework/RESTAPI_SystemCommand.h b/src/framework/RESTAPI_SystemCommand.h index f86f57d..5dc206d 100644 --- a/src/framework/RESTAPI_SystemCommand.h +++ b/src/framework/RESTAPI_SystemCommand.h @@ -24,50 +24,63 @@ namespace OpenWifi { Server, TransactionId, Internal) {} static auto PathName() { return std::list{"/api/v1/system"}; } - inline void DoGet() { + inline void DoGet() final { std::string Arg; - if (HasParameter("command", Arg) && Arg == "info") { - Poco::JSON::Object Answer; - Answer.set(RESTAPI::Protocol::VERSION, MicroServiceVersion()); - Answer.set(RESTAPI::Protocol::UPTIME, MicroServiceUptimeTotalSeconds()); - Answer.set(RESTAPI::Protocol::START, MicroServiceStartTimeEpochTime()); - Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName()); - Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount()); - Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName()); - Answer.set(RESTAPI::Protocol::UI, MicroServiceGetUIURI()); + if (HasParameter("command", Arg)) { + if (Arg == "info") { + Poco::JSON::Object Answer; + Answer.set(RESTAPI::Protocol::VERSION, MicroServiceVersion()); + Answer.set(RESTAPI::Protocol::UPTIME, MicroServiceUptimeTotalSeconds()); + Answer.set(RESTAPI::Protocol::START, MicroServiceStartTimeEpochTime()); + Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName()); + Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount()); + Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName()); + Answer.set(RESTAPI::Protocol::UI, MicroServiceGetUIURI()); - Poco::JSON::Array Certificates; - auto SubSystems = MicroServiceGetFullSubSystems(); - std::set CertNames; + Poco::JSON::Array Certificates; + auto SubSystems = MicroServiceGetFullSubSystems(); + std::set CertNames; - for (const auto &i : SubSystems) { - auto Hosts = i->HostSize(); - for (uint64_t j = 0; j < Hosts; ++j) { - auto CertFileName = i->Host(j).CertFile(); - if (!CertFileName.empty()) { - Poco::File F1(CertFileName); - if (F1.exists()) { - auto InsertResult = CertNames.insert(CertFileName); - if (InsertResult.second) { - Poco::JSON::Object Inner; - Poco::Path F(CertFileName); - Inner.set("filename", F.getFileName()); - Poco::Crypto::X509Certificate C(CertFileName); - auto ExpiresOn = C.expiresOn(); - Inner.set("expiresOn", ExpiresOn.timestamp().epochTime()); - Certificates.add(Inner); + for (const auto &i : SubSystems) { + auto Hosts = i->HostSize(); + for (uint64_t j = 0; j < Hosts; ++j) { + auto CertFileName = i->Host(j).CertFile(); + if (!CertFileName.empty()) { + Poco::File F1(CertFileName); + if (F1.exists()) { + auto InsertResult = CertNames.insert(CertFileName); + if (InsertResult.second) { + Poco::JSON::Object Inner; + Poco::Path F(CertFileName); + Inner.set("filename", F.getFileName()); + Poco::Crypto::X509Certificate C(CertFileName); + auto ExpiresOn = C.expiresOn(); + Inner.set("expiresOn", ExpiresOn.timestamp().epochTime()); + Certificates.add(Inner); + } } } } } + Answer.set("certificates", Certificates); + return ReturnObject(Answer); + } + if (Arg == "extraConfiguration") { + Poco::JSON::Object Answer; + MicroServiceGetExtraConfiguration(Answer); + return ReturnObject(Answer); + } + if (Arg == "resources") { + Poco::JSON::Object Answer; + Answer.set("numberOfFileDescriptors", Utils::get_open_fds()); + std::uint64_t currRealMem, peakRealMem, currVirtMem, peakVirtMem; + Utils::getMemory(currRealMem, peakRealMem, currVirtMem, peakVirtMem); + Answer.set("currRealMem", currRealMem); + Answer.set("peakRealMem", peakRealMem); + Answer.set("currVirtMem", currVirtMem); + Answer.set("peakVirtMem", peakVirtMem); + return ReturnObject(Answer); } - Answer.set("certificates", Certificates); - return ReturnObject(Answer); - } - if (GetBoolParameter("extraConfiguration")) { - Poco::JSON::Object Answer; - MicroServiceGetExtraConfiguration(Answer); - return ReturnObject(Answer); } BadRequest(RESTAPI::Errors::InvalidCommand); } diff --git a/src/framework/ow_constants.h b/src/framework/ow_constants.h index 2b01edd..365fb70 100644 --- a/src/framework/ow_constants.h +++ b/src/framework/ow_constants.h @@ -401,6 +401,9 @@ namespace OpenWifi::RESTAPI::Errors { 1171, "Command not supported on simulated device." }; + + static const struct msg DefFirmwareNameExists { 1172, "Firmware name already exists." }; + static const struct msg SimulationDoesNotExist { 7000, "Simulation Instance ID does not exist." }; diff --git a/src/framework/utils.h b/src/framework/utils.h index 0228bff..b464989 100644 --- a/src/framework/utils.h +++ b/src/framework/utils.h @@ -13,6 +13,8 @@ #include #include +#include + #include "Poco/Base64Decoder.h" #include "Poco/Base64Encoder.h" #include "Poco/File.h" @@ -181,4 +183,67 @@ namespace OpenWifi::Utils { return false; } + static inline std::uint64_t GetValue(FILE *file) { + unsigned long v=0; + char factor[32]; + if(fscanf(file, " %lu %31s", &v, factor)==2) { + switch (factor[0]) { + case 'k': + return v * 1000; + case 'M': + return v * 1000000; + case 'G': + return v * 1000000000; + } + } + return v; + } + + inline bool getMemory( + std::uint64_t &currRealMem, std::uint64_t &peakRealMem, + std::uint64_t &currVirtMem, std::uint64_t &peakVirtMem) { + + // stores each word in status file + char buffer[1024] = ""; + + currRealMem = peakRealMem = currVirtMem = peakVirtMem = 0; + + // linux file contains this-process info + FILE * file = std::fopen("/proc/self/status", "r"); + if (file == nullptr) { + return false; + } + + // read the entire file, recording mems in kB + while (fscanf(file, " %1023s", buffer) == 1) { + + if (strcmp(buffer, "VmRSS:") == 0) { + currRealMem= GetValue(file); + } else if (strcmp(buffer, "VmHWM:") == 0) { + peakRealMem= GetValue(file); + } else if (strcmp(buffer, "VmSize:") == 0) { + currVirtMem= GetValue(file); + } else if (strcmp(buffer, "VmPeak:") == 0) { + peakVirtMem= GetValue(file); + } + } + fclose(file); + + return true; + } + + inline int get_open_fds() { + DIR *dp = opendir("/proc/self/fd"); + struct dirent *de; + int count = -3; // '.', '..', dp + + if (dp == nullptr) + return -1; + while ((de = readdir(dp)) != nullptr) + count++; + (void)closedir(dp); + + return count; + } + } // namespace OpenWifi::Utils