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"
32 #define PNF_REGISTRATION_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves/pnf-registration"
34 static int ves_pnf_sequence_number = 0;
36 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);
37 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);
39 static int ves_pnf_registration_status = 0;
41 int ves_pnf_registration_feature_get_status(void) {
42 return ves_pnf_registration_status;
45 int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) {
46 assert(current_session);
48 ves_pnf_sequence_number = 0;
52 bool pnf_registration_enabled = false;
53 rc = sr_get_item(current_session, PNF_REGISTRATION_SCHEMA_XPATH, 0, &value);
55 pnf_registration_enabled = value->data.bool_val;
58 else if(rc != SR_ERR_NOT_FOUND) {
59 log_error("sr_get_item failed\n");
60 return NTS_ERR_FAILED;
63 // if value is not set yet, feature enable means we want to start pnf-registration
64 if(strlen(framework_environment.nts.nf_standalone_start_features)) {
65 pnf_registration_enabled = true;
69 if(pnf_registration_enabled == false) {
70 log_add_verbose(2, "PNF registration is disabled\n");
74 int ssh_base_port = 0;
75 int tls_base_port = 0;
76 char nf_ip_v4_address[128];
77 char nf_ip_v6_address[128];
79 nf_ip_v4_address[0] = 0;
80 nf_ip_v6_address[0] = 0;
82 nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(current_session);
83 if(mp == UNKNOWN_MAPPING) {
84 log_error("mount-point-addressing-method failed\n");
85 return NTS_ERR_FAILED;
87 else if(mp == DOCKER_MAPPING) {
88 if (framework_environment.settings.ip_v4 != 0) {
89 strcpy(nf_ip_v4_address, framework_environment.settings.ip_v4);
91 if (framework_environment.settings.ip_v6) {
92 strcpy(nf_ip_v6_address, framework_environment.settings.ip_v6);
95 ssh_base_port = STANDARD_NETCONF_PORT;
96 tls_base_port = ssh_base_port + framework_environment.settings.ssh_connections;
99 if(framework_environment.settings.ip_v6_enabled) {
100 strcpy(nf_ip_v6_address, framework_environment.host.ip);
103 strcpy(nf_ip_v4_address, framework_environment.host.ip);
106 ssh_base_port = framework_environment.host.ssh_base_port;
107 tls_base_port = framework_environment.host.tls_base_port;
110 if((framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections) > 1) {
111 for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) {
112 int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, false);
113 if(rc != NTS_ERR_OK) {
114 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);
118 for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) {
119 int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, true);
120 if(rc != NTS_ERR_OK) {
121 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);
128 if(framework_environment.settings.tls_connections == 0) {
130 port = ssh_base_port;
134 port = tls_base_port;
137 int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, 0, mp, tls);
138 if(rc != NTS_ERR_OK) {
139 log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s\n", nf_ip_v4_address, nf_ip_v6_address, port);
143 log_add_verbose(2, "PNF registration enabled\n");
144 ves_pnf_registration_status = 1;
149 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) {
150 assert(current_session);
152 cJSON *post_data_json = cJSON_CreateObject();
153 if(post_data_json == 0) {
154 log_error("could not create cJSON object\n");
155 return NTS_ERR_FAILED;
158 cJSON *event = cJSON_CreateObject();
160 log_error("could not create cJSON object\n");
161 cJSON_Delete(post_data_json);
162 return NTS_ERR_FAILED;
165 if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
166 log_error("cJSON_AddItemToObject failed\n");
167 cJSON_Delete(post_data_json);
168 return NTS_ERR_FAILED;
171 char *hostname_string = framework_environment.settings.hostname;
172 cJSON *common_event_header = ves_create_common_event_header("pnfRegistration", "EventType5G", hostname_string, nf_port, "Normal", ves_pnf_sequence_number++);
173 if(common_event_header == 0) {
174 log_error("could not create cJSON object\n");
175 cJSON_Delete(post_data_json);
176 return NTS_ERR_FAILED;
180 if(mp == DOCKER_MAPPING) {
181 nf_port = STANDARD_NETCONF_PORT;
185 nf_port = framework_environment.host.tls_base_port;
188 nf_port = framework_environment.host.ssh_base_port;
193 if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
194 log_error("cJSON_AddItemToObject failed\n");
195 cJSON_Delete(post_data_json);
196 return NTS_ERR_FAILED;
199 cJSON *pnf_registration_fields = ves_create_pnf_registration_fields(nf_ip_v4_address, nf_ip_v6_address, nf_port, is_tls);
200 if(pnf_registration_fields == 0) {
201 log_error("could not create cJSON object\n");
202 cJSON_Delete(post_data_json);
203 return NTS_ERR_FAILED;
206 if(cJSON_AddItemToObject(event, "pnfRegistrationFields", pnf_registration_fields) == 0) {
207 log_error("cJSON_AddItemToObject failed\n");
208 cJSON_Delete(post_data_json);
209 return NTS_ERR_FAILED;
212 char *post_data = cJSON_PrintUnformatted(post_data_json);
213 cJSON_Delete(post_data_json);
215 log_error("cJSON_PrintUnformatted failed\n");
216 return NTS_ERR_FAILED;
220 ves_details_t *ves_details = ves_endpoint_details_get(current_session);
222 log_error("ves_endpoint_details_get failed\n");
224 return NTS_ERR_FAILED;
227 int rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
228 ves_details_free(ves_details);
231 if(rc != NTS_ERR_OK) {
232 log_error("http_request failed\n");
233 return NTS_ERR_FAILED;
239 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) {
241 //checkAL aici n-ar trebui niste valori "adevarate" ?
243 cJSON *pnf_registration_fields = cJSON_CreateObject();
244 if(pnf_registration_fields == 0) {
245 log_error("could not create JSON object\n");
249 if(cJSON_AddStringToObject(pnf_registration_fields, "pnfRegistrationFieldsVersion", "2.0") == 0) {
250 log_error("cJSON_AddItemToObject failed\n");
251 cJSON_Delete(pnf_registration_fields);
255 if(cJSON_AddStringToObject(pnf_registration_fields, "lastServiceDate", "2019-08-16") == 0) {
256 log_error("cJSON_AddItemToObject failed\n");
257 cJSON_Delete(pnf_registration_fields);
261 char *mac_addr = rand_mac_address();
263 log_error("rand_mac_address failed\n")
264 cJSON_Delete(pnf_registration_fields);
268 if(cJSON_AddStringToObject(pnf_registration_fields, "macAddress", mac_addr) == 0) {
269 log_error("cJSON_AddItemToObject failed\n");
270 cJSON_Delete(pnf_registration_fields);
276 if(cJSON_AddStringToObject(pnf_registration_fields, "manufactureDate", "2019-08-16") == 0) {
277 log_error("cJSON_AddItemToObject failed\n");
278 cJSON_Delete(pnf_registration_fields);
282 if(cJSON_AddStringToObject(pnf_registration_fields, "modelNumber", "Simulated Device Melacon") == 0) {
283 log_error("cJSON_AddItemToObject failed\n");
284 cJSON_Delete(pnf_registration_fields);
288 if (nf_ip_v4_address != 0 && strlen(nf_ip_v4_address) > 0) {
289 if(cJSON_AddStringToObject(pnf_registration_fields, "oamV4IpAddress", nf_ip_v4_address) == 0) {
290 log_error("cJSON_AddItemToObject failed\n");
291 cJSON_Delete(pnf_registration_fields);
296 if (nf_ip_v6_address != 0 && strlen(nf_ip_v6_address) > 0) {
297 if(cJSON_AddStringToObject(pnf_registration_fields, "oamV6IpAddress", nf_ip_v6_address) == 0) {
298 log_error("cJSON_AddItemToObject failed\n");
299 cJSON_Delete(pnf_registration_fields);
304 char serial_number[512];
305 sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", framework_environment.settings.hostname, nf_ip_v4_address, nf_port);
307 if(cJSON_AddStringToObject(pnf_registration_fields, "serialNumber", serial_number) == 0) {
308 log_error("cJSON_AddItemToObject failed\n");
309 cJSON_Delete(pnf_registration_fields);
313 if(cJSON_AddStringToObject(pnf_registration_fields, "softwareVersion", "2.3.5") == 0) {
314 log_error("cJSON_AddItemToObject failed\n");
315 cJSON_Delete(pnf_registration_fields);
319 if(cJSON_AddStringToObject(pnf_registration_fields, "unitFamily", "Simulated Device") == 0) {
320 log_error("cJSON_AddItemToObject failed\n");
321 cJSON_Delete(pnf_registration_fields);
325 if(cJSON_AddStringToObject(pnf_registration_fields, "unitType", "O-RAN-sim") == 0) {
326 log_error("cJSON_AddItemToObject failed\n");
327 cJSON_Delete(pnf_registration_fields);
331 if(cJSON_AddStringToObject(pnf_registration_fields, "vendorName", "Melacon") == 0) {
332 log_error("cJSON_AddItemToObject failed\n");
333 cJSON_Delete(pnf_registration_fields);
337 cJSON *additional_fields = cJSON_CreateObject();
338 if(additional_fields == 0) {
339 log_error("could not create JSON object\n");
340 cJSON_Delete(pnf_registration_fields);
343 cJSON_AddItemToObject(pnf_registration_fields, "additionalFields", additional_fields);
345 char port_string[10];
346 sprintf(port_string, "%d", nf_port);
348 if(cJSON_AddStringToObject(additional_fields, "oamPort", port_string) == 0) {
349 log_error("cJSON_AddItemToObject failed\n");
350 cJSON_Delete(pnf_registration_fields);
355 //TLS specific configuration
356 if(cJSON_AddStringToObject(additional_fields, "protocol", "TLS") == 0) {
357 log_error("cJSON_AddItemToObject failed\n");
358 cJSON_Delete(pnf_registration_fields);
362 if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) {
363 log_error("cJSON_AddItemToObject failed\n");
364 cJSON_Delete(pnf_registration_fields);
368 if(cJSON_AddStringToObject(additional_fields, "keyId", KS_KEY_NAME) == 0) {
369 log_error("cJSON_AddItemToObject failed\n");
370 cJSON_Delete(pnf_registration_fields);
375 //SSH specific configuration
376 if(cJSON_AddStringToObject(additional_fields, "protocol", "SSH") == 0) {
377 log_error("cJSON_AddItemToObject failed\n");
378 cJSON_Delete(pnf_registration_fields);
382 if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) {
383 log_error("cJSON_AddItemToObject failed\n");
384 cJSON_Delete(pnf_registration_fields);
388 // hardcoded password here
389 if(cJSON_AddStringToObject(additional_fields, "password", "netconf!") == 0) {
390 log_error("cJSON_AddItemToObject failed\n");
391 cJSON_Delete(pnf_registration_fields);
396 if(cJSON_AddStringToObject(additional_fields, "reconnectOnChangedSchema", "false") == 0) {
397 log_error("cJSON_AddItemToObject failed\n");
398 cJSON_Delete(pnf_registration_fields);
402 if(cJSON_AddStringToObject(additional_fields, "sleep-factor", "1.5") == 0) {
403 log_error("cJSON_AddItemToObject failed\n");
404 cJSON_Delete(pnf_registration_fields);
408 if(cJSON_AddStringToObject(additional_fields, "tcpOnly", "false") == 0) {
409 log_error("cJSON_AddItemToObject failed\n");
410 cJSON_Delete(pnf_registration_fields);
414 if(cJSON_AddStringToObject(additional_fields, "connectionTimeout", "20000") == 0) {
415 log_error("cJSON_AddItemToObject failed\n");
416 cJSON_Delete(pnf_registration_fields);
420 if(cJSON_AddStringToObject(additional_fields, "maxConnectionAttempts", "100") == 0) {
421 log_error("cJSON_AddItemToObject failed\n");
422 cJSON_Delete(pnf_registration_fields);
426 if(cJSON_AddStringToObject(additional_fields, "betweenAttemptsTimeout", "2000") == 0) {
427 log_error("cJSON_AddItemToObject failed\n");
428 cJSON_Delete(pnf_registration_fields);
432 if(cJSON_AddStringToObject(additional_fields, "keepaliveDelay", "120") == 0) {
433 log_error("cJSON_AddItemToObject failed\n");
434 cJSON_Delete(pnf_registration_fields);
438 return pnf_registration_fields;