Kea 3.0.0
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 } else if (model_ == KEA_CTRL_AGENT) {
34 return (getControlSocketKea(data_node));
35 }
36 } catch (Error const& ex) {
38 "getting control socket: " << ex.what());
39 }
41 "getControlSocket not implemented for the model: " << model_);
42}
43
46 try {
47 if ((model_ == KEA_DHCP4_SERVER) ||
48 (model_ == KEA_DHCP6_SERVER) ||
49 (model_ == KEA_DHCP_DDNS) ||
50 (model_ == KEA_CTRL_AGENT)) {
51 return (getControlSocketKea(data_node));
52 }
53 } catch (Error const& ex) {
55 "getting control socket: " << ex.what());
56 }
58 "getControlSocket not implemented for the model: " << model_);
59}
60
63 return (getList(data_node, "control-sockets", *this, &TranslatorControlSocket::getControlSocketKea));
64}
65
69 checkAndGetLeaf(result, data_node, "socket-name");
70 checkAndGetLeaf(result, data_node, "socket-type");
71 if (model_ != KEA_CTRL_AGENT) {
72 checkAndGetLeaf(result, data_node, "socket-address");
73 checkAndGetLeaf(result, data_node, "socket-port");
74 checkAndGetLeaf(result, data_node, "trust-anchor");
75 checkAndGetLeaf(result, data_node, "cert-file");
76 checkAndGetLeaf(result, data_node, "key-file");
77 checkAndGetLeaf(result, data_node, "cert-required");
78 checkAndGet(result, data_node, "authentication",
79 [&](DataNode const& node) -> ElementPtr const {
80 // If it exists, add to the existing compatibility map created in getServerKeaDhcpCommon.
81 ConstElementPtr const_authentication(result->get("authentication"));
82 ElementPtr authentication;
83 if (const_authentication) {
84 authentication = copy(const_authentication);
85 } else {
86 authentication = Element::createMap();
87 }
88
89 checkAndGetDivergingLeaf(authentication, node, "type", "auth-type");
90 checkAndGetLeaf(authentication, node, "realm");
91 checkAndGetLeaf(authentication, node, "directory");
92 checkAndGetAndJsonifyLeaf(authentication, node, "user-context");
94 if (clients) {
95 authentication->set("clients", clients);
96 }
97 return (authentication);
98 });
100 if (headers && !headers->empty()) {
101 result->set("http-headers", headers);
102 }
103 }
104 checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
105 return (result->empty() ? ElementPtr() : result);
106}
107
110 return getList(data_node, "http-headers", *this,
112}
113
117 checkAndGetLeaf(result, data_node, "name");
118 checkAndGetLeaf(result, data_node, "value");
119 checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
120 return (result->empty() ? ElementPtr() : result);
121}
122
128
132 getMandatoryLeaf(result, data_node, "user");
133 getMandatoryLeaf(result, data_node, "password");
134 getMandatoryLeaf(result, data_node, "user-file");
135 getMandatoryLeaf(result, data_node, "password-file");
136 checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
137 if (result->get("user") && result->get("user")->stringValue().empty()) {
138 result->remove("user");
139 }
140 if (result->get("password") && result->get("password")->stringValue().empty()) {
141 result->remove("password");
142 }
143 if (result->get("user-file") && result->get("user-file")->stringValue().empty()) {
144 result->remove("user-file");
145 }
146 if (result->get("password-file") && result->get("password-file")->stringValue().empty()) {
147 result->remove("password-file");
148 }
149 return (result->empty() ? ElementPtr() : result);
150}
151
154 try {
155 return getControlSocket(findXPath(xpath));
156 } catch (NetconfError const&) {
157 return ElementPtr();
158 }
159}
160
161void
163 ConstElementPtr elem) {
164 try {
165 if ((model_ == KEA_DHCP4_SERVER) ||
166 (model_ == KEA_DHCP6_SERVER) ||
167 (model_ == KEA_DHCP_DDNS)) {
168 setControlSocketsKea(xpath, elem);
169 } else if (model_ == KEA_CTRL_AGENT) {
170 setControlSocketKea(xpath, elem, /* has_mandatory_key = */ true);
171 } else {
173 "setControlSocket not implemented for the model: "
174 << model_);
175 }
176 } catch (Error const& ex) {
178 "setting control socket '" << elem->str()
179 << "' at '" << xpath << "': " << ex.what());
180 }
181}
182
183void
185 ConstElementPtr elem) {
186 try {
187 if ((model_ == KEA_DHCP4_SERVER) ||
188 (model_ == KEA_DHCP6_SERVER) ||
189 (model_ == KEA_DHCP_DDNS) ||
190 (model_ == KEA_CTRL_AGENT)) {
191 setControlSocketKea(xpath, elem, /* has_mandatory_key = */ false);
192 } else {
194 "setControlSocket not implemented for the model: "
195 << model_);
196 }
197 } catch (Error const& ex) {
199 "setting control socket '" << elem->str()
200 << "' at '" << xpath << "': " << ex.what());
201 }
202}
203
204void
206 ConstElementPtr elem) {
207 if (!elem) {
208 deleteItem(xpath);
209 return;
210 }
211 for (size_t i = 0; i < elem->size(); ++i) {
212 ElementPtr control_socket = elem->getNonConst(i);
213 if (!control_socket->contains("socket-type")) {
214 isc_throw(BadValue, "control-socket without socket-type: " << control_socket->str());
215 }
216 string type = control_socket->get("socket-type")->stringValue();
217 ostringstream key;
218 key << xpath << "[socket-type='" << type << "']";
219 setControlSocketKea(key.str(), control_socket, /* has_mandatory_key = */ true);
220 }
221}
222
223void
225 ConstElementPtr elem,
226 bool has_mandatory_key) {
227 if (!elem) {
228 deleteItem(xpath);
229 return;
230 }
231
232 if (has_mandatory_key) {
233 // Set the list element. This is important in case we have no other elements except the key.
234 setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
235 } else {
236 checkAndSetLeaf(elem, xpath, "socket-type", LeafBaseType::String);
237 }
238
239 checkAndSetLeaf(elem, xpath, "socket-name", LeafBaseType::String);
240 if (model_ != KEA_CTRL_AGENT) {
241 checkAndSetLeaf(elem, xpath, "socket-address", LeafBaseType::String);
242 checkAndSetLeaf(elem, xpath, "socket-port", LeafBaseType::Uint16);
243 checkAndSetLeaf(elem, xpath, "trust-anchor", LeafBaseType::String);
244 checkAndSetLeaf(elem, xpath, "cert-file", LeafBaseType::String);
245 checkAndSetLeaf(elem, xpath, "key-file", LeafBaseType::String);
246 checkAndSetLeaf(elem, xpath, "cert-required", LeafBaseType::Bool);
247 ConstElementPtr authentication = elem->get("authentication");
248 if (authentication && !authentication->empty()) {
249 setMandatoryDivergingLeaf(authentication, xpath +"/authentication" , "type", "auth-type", LeafBaseType::String);
250 checkAndSetLeaf(authentication, xpath + "/authentication", "realm", LeafBaseType::String);
251 checkAndSetLeaf(authentication, xpath + "/authentication", "directory", LeafBaseType::String);
252 checkAndSetUserContext(authentication, xpath + "/authentication");
253 ConstElementPtr clients = authentication->get("clients");
254 setControlSocketAuthenticationClients(xpath + "/authentication/clients", clients);
255 }
256 ConstElementPtr http_headers = elem->get("http-headers");
257 if (http_headers && !http_headers->empty()) {
258 setControlSocketHttpHeaders(xpath + "/http-headers", http_headers);
259 }
260 }
261 checkAndSetUserContext(elem, xpath);
262}
263
264void
266 ConstElementPtr elem) {
267 if (!elem) {
268 deleteItem(xpath);
269 return;
270 }
271 for (size_t i = 0; i < elem->size(); ++i) {
272 ElementPtr client = elem->getNonConst(i);
273 auto user = client->get("user");
274 string user_str;
275 if (user) {
276 user_str = user->stringValue();
277 }
278 auto password = client->get("password");
279 string password_str;
280 if (password) {
281 password_str = password->stringValue();
282 }
283 auto user_file = client->get("user-file");
284 string user_file_str;
285 if (user_file) {
286 user_file_str = user_file->stringValue();
287 }
288 auto password_file = client->get("password-file");
289 string password_file_str;
290 if (password_file) {
291 password_file_str = password_file->stringValue();
292 }
293 ostringstream key;
294 key << xpath << "[user='" << user_str << "'][password='" << password_str
295 << "'][user-file='" << user_file_str << "'][password-file='"
296 << password_file_str << "']";
297 setControlSocketAuthenticationClient(key.str(), client);
298 }
299}
300
301void
303 ConstElementPtr elem) {
304 setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
305 checkAndSetUserContext(elem, xpath);
306}
307
308void
311 if (!elem) {
312 deleteItem(xpath);
313 return;
314 }
315 for (ConstElementPtr header : elem->listValue()) {
316 ConstElementPtr name(header->get("name"));
317 if (!name) {
318 isc_throw(BadValue, "http header without name: " << header->str());
319 }
320 ostringstream key;
321 key << xpath << "[name='" << name->stringValue() << "']";
322 setControlSocketHttpHeader(key.str(), header);
323 }
324}
325
326void
329 setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
330
331 checkAndSetLeaf(elem, xpath, "value", LeafBaseType::String);
332 checkAndSetUserContext(elem, xpath);
333}
334
335} // namespace yang
336} // namespace isc
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
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:274
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:44
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:427
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, int level)
Copy the data up to a nesting level.
Definition data.cc:1420
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
Defines the logger used by the top-level component of kea-lfc.
Generic NETCONF error.