1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "ves_pnf_registration.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/rand_utils.h"
24 #include "utils/http_client.h"
25 #include "utils/nts_utils.h"
29 #include "core/session.h"
30 #include "core/framework.h"
31 #include "core/xpath.h"
33 static int ves_pnf_sequence_number = 0;
35 static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, nts_mount_point_addressing_method_t mp, bool is_tls);
36 static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls);
38 static int ves_pnf_registration_status = 0;
40 int ves_pnf_registration_feature_get_status(void) {
41 return ves_pnf_registration_status;
44 int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) {
45 assert(current_session);
47 ves_pnf_sequence_number = 0;
51 bool pnf_registration_enabled = false;
52 rc = sr_get_item(current_session, NTS_NF_VES_PNF_REGISTRATION_SCHEMA_XPATH, 0, &value);
54 pnf_registration_enabled = value->data.bool_val;
57 else if(rc != SR_ERR_NOT_FOUND) {
58 log_error("sr_get_item failed\n");
59 return NTS_ERR_FAILED;
62 // if value is not set yet, feature enable means we want to start pnf-registration
63 if(strlen(framework_environment.nts.nf_standalone_start_features)) {
64 pnf_registration_enabled = true;
68 if(pnf_registration_enabled == false) {
69 log_add_verbose(2, "PNF registration is disabled\n");
73 int ssh_base_port = 0;
74 int tls_base_port = 0;
75 char nf_ip_v4_address[128];
76 char nf_ip_v6_address[128];
78 nf_ip_v4_address[0] = 0;
79 nf_ip_v6_address[0] = 0;
81 nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(current_session);
82 if(mp == UNKNOWN_MAPPING) {
83 log_error("mount-point-addressing-method failed\n");
84 return NTS_ERR_FAILED;
86 else if(mp == DOCKER_MAPPING) {
87 if (framework_environment.settings.ip_v4 != 0) {
88 strcpy(nf_ip_v4_address, framework_environment.settings.ip_v4);
90 if (framework_environment.settings.ip_v6) {
91 strcpy(nf_ip_v6_address, framework_environment.settings.ip_v6);
94 ssh_base_port = STANDARD_NETCONF_PORT;
95 tls_base_port = ssh_base_port + framework_environment.settings.ssh_connections;
98 if(framework_environment.settings.ip_v6_enabled) {
99 strcpy(nf_ip_v6_address, framework_environment.host.ip);
102 strcpy(nf_ip_v4_address, framework_environment.host.ip);
105 ssh_base_port = framework_environment.host.ssh_base_port;
106 tls_base_port = framework_environment.host.tls_base_port;
109 if((framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections) > 1) {
110 for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) {
111 int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, false);
112 if(rc != NTS_ERR_OK) {
113 log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s and port=%d and protocol SSH\n", nf_ip_v4_address, nf_ip_v6_address, port);
117 for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) {
118 int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, true);
119 if(rc != NTS_ERR_OK) {
120 log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s and port=%d and protocol TLS\n", nf_ip_v4_address, nf_ip_v6_address, port);
127 if(framework_environment.settings.tls_connections == 0) {
129 port = ssh_base_port;
133 port = tls_base_port;
136 int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, 0, mp, tls);
137 if(rc != NTS_ERR_OK) {
138 log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s\n", nf_ip_v4_address, nf_ip_v6_address, port);
142 log_add_verbose(2, "PNF registration enabled\n");
143 ves_pnf_registration_status = 1;
148 static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, nts_mount_point_addressing_method_t mp, bool is_tls) {
149 assert(current_session);
151 cJSON *post_data_json = cJSON_CreateObject();
152 if(post_data_json == 0) {
153 log_error("could not create cJSON object\n");
154 return NTS_ERR_FAILED;
157 cJSON *event = cJSON_CreateObject();
159 log_error("could not create cJSON object\n");
160 cJSON_Delete(post_data_json);
161 return NTS_ERR_FAILED;
164 if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
165 log_error("cJSON_AddItemToObject failed\n");
166 cJSON_Delete(post_data_json);
167 return NTS_ERR_FAILED;
170 char *hostname_string = framework_environment.settings.hostname;
171 cJSON *common_event_header = ves_create_common_event_header("pnfRegistration", "EventType5G", hostname_string, nf_port, "Normal", ves_pnf_sequence_number++);
172 if(common_event_header == 0) {
173 log_error("could not create cJSON object\n");
174 cJSON_Delete(post_data_json);
175 return NTS_ERR_FAILED;
179 if(mp == DOCKER_MAPPING) {
180 nf_port = STANDARD_NETCONF_PORT;
184 nf_port = framework_environment.host.tls_base_port;
187 nf_port = framework_environment.host.ssh_base_port;
192 if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
193 log_error("cJSON_AddItemToObject failed\n");
194 cJSON_Delete(post_data_json);
195 return NTS_ERR_FAILED;
198 cJSON *pnf_registration_fields = ves_create_pnf_registration_fields(nf_ip_v4_address, nf_ip_v6_address, nf_port, is_tls);
199 if(pnf_registration_fields == 0) {
200 log_error("could not create cJSON object\n");
201 cJSON_Delete(post_data_json);
202 return NTS_ERR_FAILED;
205 if(cJSON_AddItemToObject(event, "pnfRegistrationFields", pnf_registration_fields) == 0) {
206 log_error("cJSON_AddItemToObject failed\n");
207 cJSON_Delete(post_data_json);
208 return NTS_ERR_FAILED;
211 char *post_data = cJSON_PrintUnformatted(post_data_json);
212 cJSON_Delete(post_data_json);
214 log_error("cJSON_PrintUnformatted failed\n");
215 return NTS_ERR_FAILED;
219 ves_details_t *ves_details = ves_endpoint_details_get(current_session);
221 log_error("ves_endpoint_details_get failed\n");
223 return NTS_ERR_FAILED;
226 int rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
227 ves_details_free(ves_details);
230 if(rc != NTS_ERR_OK) {
231 log_error("http_request failed\n");
232 return NTS_ERR_FAILED;
238 static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls) {
240 //checkAL aici n-ar trebui niste valori "adevarate" ?
242 cJSON *pnf_registration_fields = cJSON_CreateObject();
243 if(pnf_registration_fields == 0) {
244 log_error("could not create JSON object\n");
248 if(cJSON_AddStringToObject(pnf_registration_fields, "pnfRegistrationFieldsVersion", "2.0") == 0) {
249 log_error("cJSON_AddItemToObject failed\n");
250 cJSON_Delete(pnf_registration_fields);
254 if(cJSON_AddStringToObject(pnf_registration_fields, "lastServiceDate", "2019-08-16") == 0) {
255 log_error("cJSON_AddItemToObject failed\n");
256 cJSON_Delete(pnf_registration_fields);
260 char *mac_addr = rand_mac_address();
262 log_error("rand_mac_address failed\n")
263 cJSON_Delete(pnf_registration_fields);
267 if(cJSON_AddStringToObject(pnf_registration_fields, "macAddress", mac_addr) == 0) {
268 log_error("cJSON_AddItemToObject failed\n");
269 cJSON_Delete(pnf_registration_fields);
275 if(cJSON_AddStringToObject(pnf_registration_fields, "manufactureDate", "2019-08-16") == 0) {
276 log_error("cJSON_AddItemToObject failed\n");
277 cJSON_Delete(pnf_registration_fields);
281 if(cJSON_AddStringToObject(pnf_registration_fields, "modelNumber", "Simulated Device Melacon") == 0) {
282 log_error("cJSON_AddItemToObject failed\n");
283 cJSON_Delete(pnf_registration_fields);
287 if (nf_ip_v4_address != 0 && strlen(nf_ip_v4_address) > 0) {
288 if(cJSON_AddStringToObject(pnf_registration_fields, "oamV4IpAddress", nf_ip_v4_address) == 0) {
289 log_error("cJSON_AddItemToObject failed\n");
290 cJSON_Delete(pnf_registration_fields);
295 if (nf_ip_v6_address != 0 && strlen(nf_ip_v6_address) > 0) {
296 if(cJSON_AddStringToObject(pnf_registration_fields, "oamV6IpAddress", nf_ip_v6_address) == 0) {
297 log_error("cJSON_AddItemToObject failed\n");
298 cJSON_Delete(pnf_registration_fields);
303 char serial_number[512];
304 sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", framework_environment.settings.hostname, nf_ip_v4_address, nf_port);
306 if(cJSON_AddStringToObject(pnf_registration_fields, "serialNumber", serial_number) == 0) {
307 log_error("cJSON_AddItemToObject failed\n");
308 cJSON_Delete(pnf_registration_fields);
312 if(cJSON_AddStringToObject(pnf_registration_fields, "softwareVersion", "2.3.5") == 0) {
313 log_error("cJSON_AddItemToObject failed\n");
314 cJSON_Delete(pnf_registration_fields);
318 if(cJSON_AddStringToObject(pnf_registration_fields, "unitFamily", "Simulated Device") == 0) {
319 log_error("cJSON_AddItemToObject failed\n");
320 cJSON_Delete(pnf_registration_fields);
324 if(cJSON_AddStringToObject(pnf_registration_fields, "unitType", "O-RAN-sim") == 0) {
325 log_error("cJSON_AddItemToObject failed\n");
326 cJSON_Delete(pnf_registration_fields);
330 if(cJSON_AddStringToObject(pnf_registration_fields, "vendorName", "Melacon") == 0) {
331 log_error("cJSON_AddItemToObject failed\n");
332 cJSON_Delete(pnf_registration_fields);
336 cJSON *additional_fields = cJSON_CreateObject();
337 if(additional_fields == 0) {
338 log_error("could not create JSON object\n");
339 cJSON_Delete(pnf_registration_fields);
342 cJSON_AddItemToObject(pnf_registration_fields, "additionalFields", additional_fields);
344 char port_string[10];
345 sprintf(port_string, "%d", nf_port);
347 if(cJSON_AddStringToObject(additional_fields, "oamPort", port_string) == 0) {
348 log_error("cJSON_AddItemToObject failed\n");
349 cJSON_Delete(pnf_registration_fields);
354 //TLS specific configuration
355 if(cJSON_AddStringToObject(additional_fields, "protocol", "TLS") == 0) {
356 log_error("cJSON_AddItemToObject failed\n");
357 cJSON_Delete(pnf_registration_fields);
361 if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) {
362 log_error("cJSON_AddItemToObject failed\n");
363 cJSON_Delete(pnf_registration_fields);
367 if(cJSON_AddStringToObject(additional_fields, "keyId", KS_KEY_NAME) == 0) {
368 log_error("cJSON_AddItemToObject failed\n");
369 cJSON_Delete(pnf_registration_fields);
374 //SSH specific configuration
375 if(cJSON_AddStringToObject(additional_fields, "protocol", "SSH") == 0) {
376 log_error("cJSON_AddItemToObject failed\n");
377 cJSON_Delete(pnf_registration_fields);
381 if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) {
382 log_error("cJSON_AddItemToObject failed\n");
383 cJSON_Delete(pnf_registration_fields);
387 // hardcoded password here
388 if(cJSON_AddStringToObject(additional_fields, "password", "netconf!") == 0) {
389 log_error("cJSON_AddItemToObject failed\n");
390 cJSON_Delete(pnf_registration_fields);
395 if(cJSON_AddStringToObject(additional_fields, "reconnectOnChangedSchema", "false") == 0) {
396 log_error("cJSON_AddItemToObject failed\n");
397 cJSON_Delete(pnf_registration_fields);
401 if(cJSON_AddStringToObject(additional_fields, "sleep-factor", "1.5") == 0) {
402 log_error("cJSON_AddItemToObject failed\n");
403 cJSON_Delete(pnf_registration_fields);
407 if(cJSON_AddStringToObject(additional_fields, "tcpOnly", "false") == 0) {
408 log_error("cJSON_AddItemToObject failed\n");
409 cJSON_Delete(pnf_registration_fields);
413 if(cJSON_AddStringToObject(additional_fields, "connectionTimeout", "20000") == 0) {
414 log_error("cJSON_AddItemToObject failed\n");
415 cJSON_Delete(pnf_registration_fields);
419 if(cJSON_AddStringToObject(additional_fields, "maxConnectionAttempts", "100") == 0) {
420 log_error("cJSON_AddItemToObject failed\n");
421 cJSON_Delete(pnf_registration_fields);
425 if(cJSON_AddStringToObject(additional_fields, "betweenAttemptsTimeout", "2000") == 0) {
426 log_error("cJSON_AddItemToObject failed\n");
427 cJSON_Delete(pnf_registration_fields);
431 if(cJSON_AddStringToObject(additional_fields, "keepaliveDelay", "120") == 0) {
432 log_error("cJSON_AddItemToObject failed\n");
433 cJSON_Delete(pnf_registration_fields);
437 return pnf_registration_fields;