From c573601a91cbfb62385a820d2c3b33f8b2dec598 Mon Sep 17 00:00:00 2001 From: stephb9959 Date: Wed, 4 Oct 2023 22:20:36 -0700 Subject: [PATCH] https://telecominfraproject.atlassian.net/browse/WIFI-7831 Signed-off-by: stephb9959 --- src/RESTObjects/RESTAPI_GWobjects.cpp | 46 +++++ src/RESTObjects/RESTAPI_GWobjects.h | 35 +++- src/RadiusEndpointUpdater.h | 260 ++++++++++++-------------- src/sdks/SDK_gw.cpp | 8 +- src/sdks/SDK_gw.h | 4 +- 5 files changed, 205 insertions(+), 148 deletions(-) diff --git a/src/RESTObjects/RESTAPI_GWobjects.cpp b/src/RESTObjects/RESTAPI_GWobjects.cpp index 7d42e74..6010d8d 100644 --- a/src/RESTObjects/RESTAPI_GWobjects.cpp +++ b/src/RESTObjects/RESTAPI_GWobjects.cpp @@ -171,6 +171,31 @@ namespace OpenWifi::GWObjects { field_to_json(Obj, "lastModified", LastModified); } + void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const { + field_to_json(Obj, "deviceType", deviceType); + field_to_json(Obj, "description", Description); + field_to_json(Obj, "uri", uri); + field_to_json(Obj, "revision", revision); + field_to_json(Obj, "imageCreationDate", imageCreationDate); + field_to_json(Obj, "created", Created); + field_to_json(Obj, "lastModified", LastModified); + } + + bool DefaultFirmware::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + field_from_json(Obj, "deviceType", deviceType); + field_from_json(Obj, "description", Description); + field_from_json(Obj, "uri", uri); + field_from_json(Obj, "revision", revision); + field_from_json(Obj, "imageCreationDate", imageCreationDate); + field_from_json(Obj, "created", Created); + field_from_json(Obj, "lastModified", LastModified); + return true; + } catch (const Poco::Exception &E) { + } + return false; + } + void CommandDetails::to_json(Poco::JSON::Object &Obj) const { EmbedDocument("details", Obj, Details); EmbedDocument("results", Obj, Results); @@ -246,6 +271,8 @@ namespace OpenWifi::GWObjects { field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime); field_to_json(Obj, "totalConnectionTime", Utils::Now() - started); field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate); + field_to_json(Obj, "connectReason", connectReason); + #ifdef TIP_GATEWAY_SERVICE hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber); AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity, @@ -403,6 +430,10 @@ namespace OpenWifi::GWObjects { field_to_json(Obj, "acctConfig", acctConfig); field_to_json(Obj, "coaConfig", coaConfig); field_to_json(Obj, "useByDefault", useByDefault); + field_to_json(Obj, "radsecKeepAlive", radsecKeepAlive); + field_to_json(Obj, "poolProxyIp", poolProxyIp); + field_to_json(Obj, "radsecPoolType", radsecPoolType); + field_to_json(Obj, "enabled", enabled); } bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) { @@ -413,6 +444,10 @@ namespace OpenWifi::GWObjects { field_from_json(Obj, "acctConfig", acctConfig); field_from_json(Obj, "coaConfig", coaConfig); field_from_json(Obj, "useByDefault", useByDefault); + field_from_json(Obj, "radsecKeepAlive", radsecKeepAlive); + field_from_json(Obj, "poolProxyIp", poolProxyIp); + field_from_json(Obj, "radsecPoolType", radsecPoolType); + field_from_json(Obj, "enabled", enabled); return true; } catch (const Poco::Exception &E) { } @@ -630,18 +665,29 @@ namespace OpenWifi::GWObjects { field_to_json(Obj, "chargeableUserIdentity", chargeableUserIdentity); field_to_json(Obj, "interface", interface); field_to_json(Obj, "secret", secret); + field_to_json(Obj, "nasId", nasId); + field_to_json(Obj, "calledStationId", calledStationId); } void RADIUSSessionList::to_json(Poco::JSON::Object &Obj) const { field_to_json(Obj, "sessions", sessions); } + void RadiusCoADMParameters::to_json(Poco::JSON::Object &Obj) const { + field_to_json(Obj, "accountingSessionId", accountingSessionId); + field_to_json(Obj, "accountingMultiSessionId", accountingMultiSessionId); + field_to_json(Obj, "callingStationId", callingStationId); + field_to_json(Obj, "chargeableUserIdentity", chargeableUserIdentity); + field_to_json(Obj, "userName", userName); + } + bool RadiusCoADMParameters::from_json(const Poco::JSON::Object::Ptr &Obj) { try { field_from_json(Obj, "accountingSessionId", accountingSessionId); field_from_json(Obj, "accountingMultiSessionId", accountingMultiSessionId); field_from_json(Obj, "callingStationId", callingStationId); field_from_json(Obj, "chargeableUserIdentity", chargeableUserIdentity); + field_from_json(Obj, "userName", userName); return true; } catch (const Poco::Exception &E) { } diff --git a/src/RESTObjects/RESTAPI_GWobjects.h b/src/RESTObjects/RESTAPI_GWobjects.h index 7740db1..9b4cdc5 100644 --- a/src/RESTObjects/RESTAPI_GWobjects.h +++ b/src/RESTObjects/RESTAPI_GWobjects.h @@ -42,12 +42,13 @@ namespace OpenWifi::GWObjects { uint64_t sessionId = 0; double connectionCompletionTime = 0.0; std::uint64_t certificateExpiryDate = 0; - bool hasRADIUSSessions = false; + std::uint64_t hasRADIUSSessions = 0; bool hasGPS = false; std::uint64_t sanity=0; std::double_t memoryUsed=0.0; std::double_t load=0.0; std::double_t temperature=0.0; + std::string connectReason; void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ; }; @@ -181,6 +182,26 @@ namespace OpenWifi::GWObjects { bool from_json(const Poco::JSON::Object::Ptr &Obj); }; + struct DefaultFirmware { + std::string deviceType; + std::string Description; + std::string uri; + std::string revision; + uint64_t imageCreationDate; + uint64_t Created; + uint64_t LastModified; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct DefaultFirmwareList { + std::vector firmwares; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + struct CommandDetails { std::string UUID; std::string SerialNumber; @@ -339,6 +360,10 @@ namespace OpenWifi::GWObjects { RadiusProxyServerConfig acctConfig; RadiusProxyServerConfig coaConfig; bool useByDefault = false; + std::string radsecPoolType; + std::string poolProxyIp; + std::uint64_t radsecKeepAlive=25; + bool enabled=true; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); @@ -393,7 +418,8 @@ namespace OpenWifi::GWObjects { callingStationId, chargeableUserIdentity, secret, - interface; + interface, + nasId; std::uint64_t inputPackets = 0, outputPackets = 0, inputOctets = 0, @@ -401,6 +427,7 @@ namespace OpenWifi::GWObjects { inputGigaWords = 0, outputGigaWords = 0; std::uint32_t sessionTime = 0; + std::string calledStationId; #ifdef TIP_GATEWAY_SERVICE RADIUS::RadiusPacket accountingPacket; @@ -418,9 +445,11 @@ namespace OpenWifi::GWObjects { std::string accountingSessionId, accountingMultiSessionId, callingStationId, - chargeableUserIdentity; + chargeableUserIdentity, + userName; bool from_json(const Poco::JSON::Object::Ptr &Obj); + void to_json(Poco::JSON::Object &Obj) const; }; } // namespace OpenWifi::GWObjects diff --git a/src/RadiusEndpointUpdater.h b/src/RadiusEndpointUpdater.h index 55e4c82..a5c854a 100644 --- a/src/RadiusEndpointUpdater.h +++ b/src/RadiusEndpointUpdater.h @@ -15,176 +15,158 @@ namespace OpenWifi { class RadiusEndpointUpdater { public: - void AddServers(const std::vector &ServerList, Poco::JSON::Object &O) { - O.set("methodParameters", Poco::JSON::Array()); - O.set("monitor" , false); - O.set("monitorMethod", "none"); - O.set("strategy", "random"); - Poco::JSON::Array ServerArray; - for(const auto &server:ServerList) { - Poco::JSON::Object InnerServer; - InnerServer.set("allowSelfSigned", false); - InnerServer.set("certificate", ""); - InnerServer.set("ignore", false); - InnerServer.set("ip",server.IP); - InnerServer.set("port", server.Port); - InnerServer.set("secret", server.Secret); - InnerServer.set("name", server.Hostname); - InnerServer.set("radsec", false); - ServerArray.add(InnerServer); - } - O.set("servers", ServerArray); - } - inline bool UpdateEndpoints( RESTAPIHandler *Client, [[maybe_unused]] std::string & Error, [[maybe_unused]] uint64_t &ErrorNum ) { std::vector Endpoints; + GWObjects::RadiusProxyPoolList Pools; StorageService()->RadiusEndpointDB().GetRecords(0,500,Endpoints); - Poco::JSON::Array RadiusPools; for(const auto &Endpoint:Endpoints) { - Poco::JSON::Object PoolEntry; - PoolEntry.set("description", Endpoint.info.description); - PoolEntry.set("name", Endpoint.info.name); - PoolEntry.set("useByDefault", false); - PoolEntry.set("poolProxyIp", Endpoint.Index); - PoolEntry.set("radsecPoolKeepAlive",25); - if(Endpoint.Type=="orion") { - PoolEntry.set("radsecPoolType","orion"); - auto Servers = OpenRoaming_Orion()->GetServers(); - Poco::JSON::Object AuthConfig; - AuthConfig.set("methodParameters", Poco::JSON::Array() ); - AuthConfig.set("monitor", false ); - AuthConfig.set("monitorMethod", "none" ); - AuthConfig.set("strategy","random"); - Poco::JSON::Array ServerArray; + GWObjects::RadiusProxyPool PP; + auto & AUTH = PP.authConfig; + auto & ACCT = PP.acctConfig; + auto & COA = PP.coaConfig; + + PP.name = Endpoint.info.name; + PP.description = Endpoint.info.description; + PP.useByDefault = false; + PP.poolProxyIp = Endpoint.Index; + PP.radsecKeepAlive = 25; + PP.enabled = true; + + if(Endpoint.Type=="orion" && !Endpoint.RadsecServers.empty()) { + auto Svrs = OpenRoaming_Orion()->GetServers(); + PP.radsecPoolType="orion"; ProvObjects::GooglOrionAccountInfo OA; - StorageService()->OrionAccountsDB().GetRecord("id",Endpoint.RadsecServers[0].UseOpenRoamingAccount,OA); - int i=1; - for(const auto &Server:Servers) { - Poco::JSON::Object InnerServer; - InnerServer.set("allowSelfSigned", false); - InnerServer.set("ignore", false); - InnerServer.set("name", fmt::format("Server {}",i)); - InnerServer.set("ip", Server.Hostname); - InnerServer.set("radsecPort", Server.Port); - InnerServer.set("port", Server.Port); - InnerServer.set("radsec", true); - InnerServer.set("radsecCert", Utils::base64encode((const u_char *)OA.certificate.c_str(),OA.certificate.size())); - InnerServer.set("radsecKey", Utils::base64encode((const u_char *)OA.privateKey.c_str(),OA.privateKey.size())); - Poco::JSON::Array CaCerts; - for(const auto &cert:OA.cacerts) { - CaCerts.add(Utils::base64encode((const u_char *)cert.c_str(),cert.size())); + if(StorageService()->OrionAccountsDB().GetRecord("id", Endpoint.RadsecServers[0].UseOpenRoamingAccount, OA)) { + for(auto ServerType:{ AUTH, ACCT, COA}) { + ServerType.monitor = false; + ServerType.strategy = Endpoint.PoolStrategy; + int i=1; + for (const auto &Server: Svrs) { + GWObjects::RadiusProxyServerEntry PE; + PE.radsecCert = Utils::base64encode((const u_char *)OA.certificate.c_str(),OA.certificate.size()); + PE.radsecKey = Utils::base64encode((const u_char *)OA.privateKey.c_str(),OA.privateKey.size()); + for(const auto &cert:OA.cacerts) { + PE.radsecCacerts.emplace_back(Utils::base64encode((const u_char *)cert.c_str(),cert.size())); + } + PE.radsec = true; + PE.name = fmt::format("Server {}",i++); + PE.ignore = false; + PE.ip = Server.Hostname; + PE.port = PE.radsecPort = Server.Port; + PE.allowSelfSigned = false; + PE.weight = 10; + PE.secret = PE.radsecSecret = "radsec"; + ServerType.servers.emplace_back(PE); + } } - InnerServer.set("radsecCacerts", CaCerts); - InnerServer.set("radsecSecret","radsec"); - i++; - ServerArray.add(InnerServer); + Pools.pools.emplace_back(PP); } - AuthConfig.set("servers",ServerArray); - PoolEntry.set("authConfig", AuthConfig); - RadiusPools.add(PoolEntry); - } else if(Endpoint.Type=="globalreach") { - PoolEntry.set("radsecPoolType","globalreach"); - auto Servers = OpenRoaming_GlobalReach()->GetServers(); - Poco::JSON::Object AuthConfig; - AuthConfig.set("methodParameters", Poco::JSON::Array() ); - AuthConfig.set("monitor", false ); - AuthConfig.set("monitorMethod", "none" ); - AuthConfig.set("strategy","random"); - Poco::JSON::Array ServerArray; + } else if(Endpoint.Type=="globalreach" && !Endpoint.RadsecServers.empty()) { + auto Svrs = OpenRoaming_GlobalReach()->GetServers(); + PP.radsecPoolType="globalreach"; ProvObjects::GLBLRCertificateInfo GRCertificate; ProvObjects::GLBLRAccountInfo GRAccountInfo; - StorageService()->GLBLRCertsDB().GetRecord("id",Endpoint.RadsecServers[0].UseOpenRoamingAccount,GRCertificate); - StorageService()->GLBLRAccountInfoDB().GetRecord("id",GRCertificate.accountId,GRAccountInfo); - int i=1; - for(const auto &Server:Servers) { - Poco::JSON::Object InnerServer; - InnerServer.set("allowSelfSigned", false); - InnerServer.set("ignore", false); - InnerServer.set("name", fmt::format("Server {}",i)); - InnerServer.set("ip", Server.Hostname); - InnerServer.set("radsec", true); - InnerServer.set("radsecPort", Server.Port); - InnerServer.set("port", Server.Port); - InnerServer.set("radsecCert", Utils::base64encode((const u_char *)GRCertificate.certificate.c_str(),GRCertificate.certificate.size())); - InnerServer.set("radsecKey", Utils::base64encode((const u_char *)GRAccountInfo.CSRPrivateKey.c_str(),GRAccountInfo.CSRPrivateKey.size())); - InnerServer.set("radsecCacerts", Utils::base64encode((const u_char *)GRCertificate.certificateChain.c_str(),GRCertificate.certificateChain.size())); - InnerServer.set("radsecSecret","radsec"); - i++; - ServerArray.add(InnerServer); + if( StorageService()->GLBLRCertsDB().GetRecord("id",Endpoint.RadsecServers[0].UseOpenRoamingAccount,GRCertificate) && + StorageService()->GLBLRAccountInfoDB().GetRecord("id",GRCertificate.accountId,GRAccountInfo)) { + for(auto ServerType:{ AUTH, ACCT, COA}) { + ServerType.monitor = false; + ServerType.strategy = Endpoint.PoolStrategy; + int i = 1; + for (const auto &Server: Svrs) { + GWObjects::RadiusProxyServerEntry PE; + PE.radsecCert = Utils::base64encode((const u_char *)GRCertificate.certificate.c_str(),GRCertificate.certificate.size()); + PE.radsecKey = Utils::base64encode((const u_char *)GRAccountInfo.CSRPrivateKey.c_str(),GRAccountInfo.CSRPrivateKey.size()); + PE.radsecCacerts.emplace_back( Utils::base64encode((const u_char *)GRCertificate.certificateChain.c_str(),GRCertificate.certificateChain.size())); + PE.radsec = true; + PE.name = fmt::format("Server {}", i++); + PE.ignore = false; + PE.ip = Server.Hostname; + PE.port = PE.radsecPort = Server.Port; + PE.allowSelfSigned = false; + PE.weight = 10; + PE.secret = PE.radsecSecret = "radsec"; + ServerType.servers.emplace_back(PE); + } + } + Pools.pools.emplace_back(PP); } - AuthConfig.set("servers",ServerArray); - PoolEntry.set("authConfig", AuthConfig); - RadiusPools.add(PoolEntry); - } else if(Endpoint.Type=="radsec") { - PoolEntry.set("radsecPoolType","generic"); - Poco::JSON::Object AuthConfig; - AuthConfig.set("methodParameters", Poco::JSON::Array() ); - AuthConfig.set("monitor", false ); - AuthConfig.set("monitorMethod", "none" ); - AuthConfig.set("strategy","random"); - Poco::JSON::Array ServerArray; - int i=1; - for(const auto &Server:Endpoint.RadsecServers) { - Poco::JSON::Object InnerServer; - InnerServer.set("allowSelfSigned", false); - InnerServer.set("ignore", false); - InnerServer.set("name", fmt::format("Server {}",i)); - InnerServer.set("ip", Server.IP); - InnerServer.set("radsec", true); - InnerServer.set("radsecPort", Server.Port); - InnerServer.set("port", Server.Port); - InnerServer.set("radsecCert", Utils::base64encode((const u_char *)Server.Certificate.c_str(), Server.Certificate.size())); - InnerServer.set("radsecKey", Utils::base64encode((const u_char *)Server.PrivateKey.c_str(), Server.PrivateKey.size())); - Poco::JSON::Array CertArray; - for(const auto & cert : Server.CaCerts) { - CertArray.add(Utils::base64encode((const u_char *)cert.c_str(), cert.size())); + } else if(Endpoint.Type=="radsec" && !Endpoint.RadsecServers.empty()) { + PP.radsecPoolType="radsec"; + for(auto ServerType:{ AUTH, ACCT, COA}) { + ServerType.monitor = false; + ServerType.strategy = Endpoint.PoolStrategy; + for (const auto &Server: Endpoint.RadsecServers) { + GWObjects::RadiusProxyServerEntry PE; + PE.radsecCert = Utils::base64encode((const u_char *)Server.Certificate.c_str(), Server.Certificate.size()); + PE.radsecKey = Utils::base64encode((const u_char *)Server.PrivateKey.c_str(),Server.PrivateKey.size()); + for(const auto &C:Server.CaCerts) { + PE.radsecCacerts.emplace_back(Utils::base64encode( + (const u_char *) C.c_str(), + C.size())); + } + PE.radsec = true; + PE.name = Server.Hostname; + PE.ignore = false; + PE.ip = Server.IP; + PE.port = PE.radsecPort = Server.Port; + PE.allowSelfSigned = false; + PE.weight = 10; + PE.secret = PE.radsecSecret = "radsec"; + ServerType.servers.emplace_back(PE); } - InnerServer.set("radsecCacerts", CertArray); - InnerServer.set("radsecSecret","radsec"); - i++; - ServerArray.add(InnerServer); } - AuthConfig.set("servers",ServerArray); - PoolEntry.set("authConfig", AuthConfig); - RadiusPools.add(PoolEntry); - } else if(Endpoint.Type=="radius") { - PoolEntry.set("radsecPoolType", "radius"); - const auto &server = Endpoint.RadiusServers[0]; - Poco::JSON::Object ServerEntry; - Poco::JSON::Object AcctConfig, AuthConfig, CoAConfig, InnerServer; - AddServers(server.Authentication,AuthConfig); - AddServers(server.Accounting,AcctConfig); - AddServers(server.CoA,CoAConfig); - PoolEntry.set("authConfig", AuthConfig); - PoolEntry.set("acctConfig", AcctConfig); - PoolEntry.set("coaConfig", CoAConfig); - } + Pools.pools.emplace_back(PP); + } else if(Endpoint.Type=="radius" && !Endpoint.RadiusServers.empty()) { + PP.radsecPoolType="generic"; +/* const auto &server = Endpoint.RadiusServers[0]; + for(auto &[ServerType,ServerInfo] : { + {}AUTH, Endpoint.RadiusServers[0].Authentication[0]) , + std::pair(ACCT, Endpoint.RadiusServers[0].Accounting[0] ), + std::pair(COA, Endpoint.RadiusServers[0].Accounting[0]) } + ) { + ServerType. + ServerType.monitor = false; + ServerType.strategy = Endpoint.PoolStrategy; + GWObjects::RadiusProxyServerEntry PE; + PE.radsec = false; + PE.name = ServerInfo.Hostname; + PE.ignore = false; + PE.ip = ServerInfo.IP; + PE.port = PE.radsecPort = ServerInfo.Port; + PE.allowSelfSigned = false; + PE.weight = 10; + PE.secret = PE.radsecSecret = "radsec"; + ServerType.servers.emplace_back(PE); + } + Pools.pools.emplace_back(PP); + */ } } - Poco::JSON::Object RadiusConfig; - RadiusConfig.set("pools", RadiusPools); - RadiusConfig.stringify(std::cout,4,2); - - DBGLINE GWObjects::RadiusProxyPoolList NewPools; - DBGLINE - if(SDK::GW::RADIUS::SetConfiguration(Client,RadiusConfig,NewPools)) { + Poco::JSON::Object ErrorObj; + if(SDK::GW::RADIUS::SetConfiguration(Client, Pools, NewPools, ErrorObj)) { DBGLINE AppServiceRegistry().Set("radiusEndpointLastUpdate", Utils::Now()); DBGLINE return true; } + DBGLINE Error = "Could not update the controller."; ErrorNum = 1; DBGLINE + return false; } + private: }; + + + } // OpenWifi diff --git a/src/sdks/SDK_gw.cpp b/src/sdks/SDK_gw.cpp index 1e7b1ad..03fe70b 100644 --- a/src/sdks/SDK_gw.cpp +++ b/src/sdks/SDK_gw.cpp @@ -255,14 +255,14 @@ namespace OpenWifi::SDK::GW { } bool SetConfiguration(RESTAPIHandler *client, const Poco::JSON::Object &Configuration, - GWObjects::RadiusProxyPoolList &NewPools) { + GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj) { OpenWifi::OpenAPIRequestPut R(OpenWifi::uSERVICE_GATEWAY, "/api/v1/radiusProxyConfig", {}, Configuration, 60000); auto CallResponse = Poco::makeShared(); auto ResponseStatus = R.Do(CallResponse, client ? client->UserInfo_.webtoken.access_token_ : ""); - CallResponse->stringify(std::cout,2,2); + ErrorObj = *CallResponse; if(ResponseStatus == Poco::Net::HTTPResponse::HTTP_OK) { return NewPools.from_json(CallResponse); } @@ -270,10 +270,10 @@ namespace OpenWifi::SDK::GW { } bool SetConfiguration(RESTAPIHandler *client, const GWObjects::RadiusProxyPoolList &Pools, - GWObjects::RadiusProxyPoolList &NewPools) { + GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj) { Poco::JSON::Object Body; Pools.to_json(Body); - return SetConfiguration(client,Body,NewPools); + return SetConfiguration(client,Body,NewPools, ErrorObj); } } diff --git a/src/sdks/SDK_gw.h b/src/sdks/SDK_gw.h index fd0b57d..b3c3048 100644 --- a/src/sdks/SDK_gw.h +++ b/src/sdks/SDK_gw.h @@ -41,8 +41,8 @@ namespace OpenWifi::SDK::GW { namespace RADIUS { bool GetConfiguration(RESTAPIHandler *client, GWObjects::RadiusProxyPoolList &Pools); bool SetConfiguration(RESTAPIHandler *client, const GWObjects::RadiusProxyPoolList &Pools, - GWObjects::RadiusProxyPoolList &NewPools); + GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj); bool SetConfiguration(RESTAPIHandler *client, const Poco::JSON::Object &Configuration, - GWObjects::RadiusProxyPoolList &NewPools); + GWObjects::RadiusProxyPoolList &NewPools, Poco::JSON::Object &ErrorObj); } } // namespace OpenWifi::SDK::GW