Kea 3.1.8
translator_control_socket.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10#include <yang/yang_models.h>
11
12#include <sstream>
13
14using namespace std;
15using namespace isc::data;
16using namespace libyang;
17using namespace sysrepo;
18
19namespace isc {
20namespace yang {
21
22TranslatorControlSocket::TranslatorControlSocket(Session session, const string& model)
23 : Translator(session, model) {
24}
25
28 try {
29 if ((model_ == KEA_DHCP4_SERVER) ||
30 (model_ == KEA_DHCP6_SERVER) ||
31 (model_ == KEA_DHCP_DDNS)) {
32 return (getControlSocketsKea(data_node));
33 }
34 } catch (Error const& ex) {
36 "getting control socket: " << ex.what());
37 }
39 "getControlSocket not implemented for the model: " << model_);
40}
41
44 try {
45 if ((model_ == KEA_DHCP4_SERVER) ||
46 (model_ == KEA_DHCP6_SERVER) ||
47 (model_ == KEA_DHCP_DDNS)) {
48 return (getControlSocketKea(data_node));
49 }
50 } catch (Error const& ex) {
52 "getting control socket: " << ex.what());
53 }
55 "getControlSocket not implemented for the model: " << model_);
56}
57
60 return (getList(data_node, "control-sockets", *this, &TranslatorControlSocket::getControlSocketKea));
61}
62
66 checkAndGetLeaf(result, data_node, "socket-name");
67 checkAndGetLeaf(result, data_node, "socket-type");
68 checkAndGetLeaf(result, data_node, "socket-address");
69 checkAndGetLeaf(result, data_node, "socket-port");
70 checkAndGetLeaf(result, data_node, "trust-anchor");
71 checkAndGetLeaf(result, data_node, "cert-file");
72 checkAndGetLeaf(result, data_node, "key-file");
73 checkAndGetLeaf(result, data_node, "cert-required");
74 checkAndGet(result, data_node, "authentication",
75 [&](DataNode const& node) -> ElementPtr const {
76 // If it exists, add to the existing compatibility map created in getServerKeaDhcpCommon.
77 ConstElementPtr const_authentication(result->get("authentication"));
78 ElementPtr authentication;
79 if (const_authentication) {
80 authentication = copy(const_authentication);
81 } else {
82 authentication = Element::createMap();
83 }
84
85 checkAndGetDivergingLeaf(authentication, node, "type", "auth-type");
86 checkAndGetLeaf(authentication, node, "realm");
87 checkAndGetLeaf(authentication, node, "directory");
88 checkAndGetAndJsonifyLeaf(authentication, node, "user-context");
90 if (clients) {
91 authentication->set("clients", clients);
92 }
93 return (authentication);
94 });
96 if (headers && !headers->empty()) {
97 result->set("http-headers", headers);
98 }
99 checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
100 return (result->empty() ? ElementPtr() : result);
101}
102
105 return getList(data_node, "http-headers", *this,
107}
108
112 checkAndGetLeaf(result, data_node, "name");
113 checkAndGetLeaf(result, data_node, "value");
114 checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
115 return (result->empty() ? ElementPtr() : result);
116}
117
123
127 getMandatoryLeaf(result, data_node, "user");
128 getMandatoryLeaf(result, data_node, "password");
129 getMandatoryLeaf(result, data_node, "user-file");
130 getMandatoryLeaf(result, data_node, "password-file");
131 checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
132 if (result->get("user") && result->get("user")->stringValue().empty()) {
133 result->remove("user");
134 }
135 if (result->get("password") && result->get("password")->stringValue().empty()) {
136 result->remove("password");
137 }
138 if (result->get("user-file") && result->get("user-file")->stringValue().empty()) {
139 result->remove("user-file");
140 }
141 if (result->get("password-file") && result->get("password-file")->stringValue().empty()) {
142 result->remove("password-file");
143 }
144 return (result->empty() ? ElementPtr() : result);
145}
146
149 try {
150 return getControlSocket(findXPath(xpath));
151 } catch (NetconfError const&) {
152 return ElementPtr();
153 }
154}
155
156void
158 ConstElementPtr elem) {
159 try {
160 if ((model_ == KEA_DHCP4_SERVER) ||
161 (model_ == KEA_DHCP6_SERVER) ||
162 (model_ == KEA_DHCP_DDNS)) {
163 setControlSocketsKea(xpath, elem);
164 } else {
166 "setControlSocket not implemented for the model: "
167 << model_);
168 }
169 } catch (Error const& ex) {
171 "setting control socket '" << elem->str()
172 << "' at '" << xpath << "': " << ex.what());
173 }
174}
175
176void
178 ConstElementPtr elem) {
179 try {
180 if ((model_ == KEA_DHCP4_SERVER) ||
181 (model_ == KEA_DHCP6_SERVER) ||
182 (model_ == KEA_DHCP_DDNS)) {
183 setControlSocketKea(xpath, elem, /* has_mandatory_key = */ false);
184 } else {
186 "setControlSocket not implemented for the model: "
187 << model_);
188 }
189 } catch (Error const& ex) {
191 "setting control socket '" << elem->str()
192 << "' at '" << xpath << "': " << ex.what());
193 }
194}
195
196void
198 ConstElementPtr elem) {
199 if (!elem) {
200 deleteItem(xpath);
201 return;
202 }
203 for (size_t i = 0; i < elem->size(); ++i) {
204 ElementPtr control_socket = elem->getNonConst(i);
205 if (!control_socket->contains("socket-type")) {
206 isc_throw(BadValue, "control-socket without socket-type: " << control_socket->str());
207 }
208 string type = control_socket->get("socket-type")->stringValue();
209 ostringstream key;
210 key << xpath << "[socket-type='" << type << "']";
211 setControlSocketKea(key.str(), control_socket, /* has_mandatory_key = */ true);
212 }
213}
214
215void
217 ConstElementPtr elem,
218 bool has_mandatory_key) {
219 if (!elem) {
220 deleteItem(xpath);
221 return;
222 }
223
224 if (has_mandatory_key) {
225 // Set the list element. This is important in case we have no other elements except the key.
226 setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
227 } else {
228 checkAndSetLeaf(elem, xpath, "socket-type", LeafBaseType::String);
229 }
230
231 checkAndSetLeaf(elem, xpath, "socket-name", LeafBaseType::String);
232 checkAndSetLeaf(elem, xpath, "socket-address", LeafBaseType::String);
233 checkAndSetLeaf(elem, xpath, "socket-port", LeafBaseType::Uint16);
234 checkAndSetLeaf(elem, xpath, "trust-anchor", LeafBaseType::String);
235 checkAndSetLeaf(elem, xpath, "cert-file", LeafBaseType::String);
236 checkAndSetLeaf(elem, xpath, "key-file", LeafBaseType::String);
237 checkAndSetLeaf(elem, xpath, "cert-required", LeafBaseType::Bool);
238 ConstElementPtr authentication = elem->get("authentication");
239 if (authentication && !authentication->empty()) {
240 setMandatoryDivergingLeaf(authentication, xpath +"/authentication" , "type", "auth-type", LeafBaseType::String);
241 checkAndSetLeaf(authentication, xpath + "/authentication", "realm", LeafBaseType::String);
242 checkAndSetLeaf(authentication, xpath + "/authentication", "directory", LeafBaseType::String);
243 checkAndSetUserContext(authentication, xpath + "/authentication");
244 ConstElementPtr clients = authentication->get("clients");
245 setControlSocketAuthenticationClients(xpath + "/authentication/clients", clients);
246 }
247 ConstElementPtr http_headers = elem->get("http-headers");
248 if (http_headers && !http_headers->empty()) {
249 setControlSocketHttpHeaders(xpath + "/http-headers", http_headers);
250 }
251 checkAndSetUserContext(elem, xpath);
252}
253
254void
256 ConstElementPtr elem) {
257 if (!elem) {
258 deleteItem(xpath);
259 return;
260 }
261 for (size_t i = 0; i < elem->size(); ++i) {
262 ElementPtr client = elem->getNonConst(i);
263 auto user = client->get("user");
264 string user_str;
265 if (user) {
266 user_str = user->stringValue();
267 }
268 auto password = client->get("password");
269 string password_str;
270 if (password) {
271 password_str = password->stringValue();
272 }
273 auto user_file = client->get("user-file");
274 string user_file_str;
275 if (user_file) {
276 user_file_str = user_file->stringValue();
277 }
278 auto password_file = client->get("password-file");
279 string password_file_str;
280 if (password_file) {
281 password_file_str = password_file->stringValue();
282 }
283 ostringstream key;
284 key << xpath << "[user='" << user_str << "'][password='" << password_str
285 << "'][user-file='" << user_file_str << "'][password-file='"
286 << password_file_str << "']";
287 setControlSocketAuthenticationClient(key.str(), client);
288 }
289}
290
291void
293 ConstElementPtr elem) {
294 setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
295 checkAndSetUserContext(elem, xpath);
296}
297
298void
301 if (!elem) {
302 deleteItem(xpath);
303 return;
304 }
305 for (ConstElementPtr header : elem->listValue()) {
306 ConstElementPtr name(header->get("name"));
307 if (!name) {
308 isc_throw(BadValue, "http header without name: " << header->str());
309 }
310 ostringstream key;
311 key << xpath << "[name='" << name->stringValue() << "']";
312 setControlSocketHttpHeader(key.str(), header);
313 }
314}
315
316void
319 setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
320
321 checkAndSetLeaf(elem, xpath, "value", LeafBaseType::String);
322 checkAndSetUserContext(elem, xpath);
323}
324
325} // namespace yang
326} // namespace isc
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when a function is not implemented.
void setControlSocket(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set control socket from JSON to YANG.
TranslatorControlSocket(sysrepo::Session session, const std::string &model)
Constructor.
void setControlSockets(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set control sockets from JSON to YANG.
isc::data::ElementPtr getControlSocketAuthenticationClients(libyang::DataNode const &data_node)
getControlSocketsAuthenticationClients JSON for kea models.
isc::data::ElementPtr getControlSocket(libyang::DataNode const &data_node)
Translate a control socket from YANG to JSON.
isc::data::ElementPtr getControlSocketAuthenticationClient(libyang::DataNode const &data_node)
getControlSocketsAuthenticationClients JSON for kea models.
isc::data::ElementPtr getControlSocketKea(libyang::DataNode const &data_node)
getControlSocket JSON for kea models.
isc::data::ElementPtr getControlSockets(libyang::DataNode const &data_node)
Translate a control socket from YANG to JSON.
isc::data::ElementPtr getControlSocketFromAbsoluteXpath(std::string const &xpath)
Translate a control socket from YANG to JSON.
isc::data::ElementPtr getControlSocketsKea(libyang::DataNode const &data_node)
getControlSocket JSON for kea models.
void setControlSocketHttpHeader(const std::string &xpath, isc::data::ConstElementPtr elem)
setControlSocketHttpHeader for kea models.
void setControlSocketAuthenticationClients(const std::string &xpath, isc::data::ConstElementPtr elem)
setControlSocketAuthenticationClients for kea models.
void setControlSocketKea(const std::string &xpath, isc::data::ConstElementPtr elem, bool has_mandatory_key)
setControlSocket for kea models.
isc::data::ElementPtr getControlSocketHttpHeader(libyang::DataNode const &data_node)
getControlSocketsAuthenticationClients JSON for kea models.
isc::data::ElementPtr getControlSocketHttpHeaders(libyang::DataNode const &data_node)
getControlSocketsAuthenticationClients JSON for kea models.
void setControlSocketsKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setControlSocket for kea models.
void setControlSocketAuthenticationClient(const std::string &xpath, isc::data::ConstElementPtr elem)
setControlSocketAuthenticationClient for kea models.
void setControlSocketHttpHeaders(const std::string &xpath, isc::data::ConstElementPtr elem)
setControlSocketHttpHeaders for kea models.
isc::data::ElementPtr getList(libyang::DataNode const &data_node, std::string const &xpath, T &t, isc::data::ElementPtr(T::*f)(libyang::DataNode const &)) const
Retrieve a list as ElementPtr from sysrepo from a certain xpath.
Definition translator.h:281
void checkAndSetLeaf(isc::data::ConstElementPtr const &from, std::string const &xpath, std::string const &name, libyang::LeafBaseType const type)
Get an element from given ElementPtr node and set it in sysrepo at given xpath.
Definition translator.cc:63
void checkAndGet(isc::data::ElementPtr const &storage, libyang::DataNode const &data_node, std::string const &xpath, T translate) const
Calls {translate} for the element found at {xpath} relative to {data_node} and sets the result in {st...
Definition translator.h:51
void setMandatoryDivergingLeaf(isc::data::ConstElementPtr const &from, std::string const &xpath, std::string const &name, std::string const &yang_name, libyang::LeafBaseType const type)
Get an element from given ElementPtr node and set it in sysrepo at given xpath.
libyang::DataNode findXPath(std::string const &xpath) const
Retrieves a YANG data node by xpath.
void getMandatoryLeaf(isc::data::ElementPtr &storage, libyang::DataNode const &data_node, std::string const &name) const
Retrieves a child YANG data node identified by name from the given parent YANG container node and sto...
void checkAndGetLeaf(isc::data::ElementPtr &storage, libyang::DataNode const &data_node, std::string const &name) const
Retrieves a child YANG data node identified by name from the given parent YANG container node and sto...
Definition translator.cc:32
void checkAndSetUserContext(isc::data::ConstElementPtr const &from, std::string const &xpath)
Get an element from given ElementPtr node and set it in sysrepo at given xpath.
Definition translator.cc:99
void deleteItem(const std::string &xpath)
Delete basic value from YANG.
void checkAndGetDivergingLeaf(isc::data::ElementPtr &storage, libyang::DataNode const &data_node, std::string const &name, std::string const &yang_name) const
Retrieves a child YANG data node identified by name from the given parent YANG container node and sto...
Definition translator.cc:42
void setItem(const std::string &xpath, isc::data::ConstElementPtr const elem, libyang::LeafBaseType const type)
Translate and set basic value from JSON to YANG.
std::string model_
The model.
Definition translator.h:434
void checkAndGetAndJsonifyLeaf(isc::data::ElementPtr &storage, libyang::DataNode const &data_node, const std::string &name) const
Retrieves a child YANG data node identified by name from the given parent YANG container node,...
Definition translator.cc:53
Translator(sysrepo::Session session, const std::string &model)
Constructor.
Definition translator.cc:27
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
Definition data.cc:1516
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
Defines the logger used by the top-level component of kea-lfc.
Generic NETCONF error.