X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=ntsimulator%2Fntsim-ng%2Futils%2Fsys_utils.c;fp=ntsimulator%2Fntsim-ng%2Futils%2Fsys_utils.c;h=fc5c9422f9d621bb25415312d3a9b9a8b3e4c7bc;hb=f1d5c9198acde7a7ce296490087cad37e008f688;hp=0000000000000000000000000000000000000000;hpb=f2d8f1002fa93848c80a88e5658db4816cba3020;p=sim%2Fo1-interface.git diff --git a/ntsimulator/ntsim-ng/utils/sys_utils.c b/ntsimulator/ntsim-ng/utils/sys_utils.c new file mode 100644 index 0000000..fc5c942 --- /dev/null +++ b/ntsimulator/ntsim-ng/utils/sys_utils.c @@ -0,0 +1,414 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "sys_utils.h" +#include "log_utils.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char b64_encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/'}; + +static int b64_mod_table[] = {0, 2, 1}; + +bool dir_exists(const char *path) { + assert(path); + + struct stat st = {0}; + return (stat(path, &st) != -1); +} + +bool file_exists(const char *fname) { + assert(fname); + + return (access(fname, F_OK) != -1); +} + +void file_touch(const char *fname, const char *content) { + assert(fname); + + FILE *f = fopen(fname, "w"); + if(f == 0) { + log_error("fopen failed"); + return; + } + + if(content) { + fprintf(f, "%s", content); + } + fclose(f); +} + +char *file_read_content(const char *fname) { + assert(fname); + + char *buffer = 0; + long length; + FILE *f = fopen(fname, "rb"); + if(f) { + fseek(f, 0, SEEK_END); + length = ftell(f); + fseek(f, 0, SEEK_SET); + buffer = (char*)malloc(sizeof(char) * length); + if(buffer) { + fread(buffer, 1, length, f); + } + fclose(f); + } + + return buffer; +} + +int get_int_from_string_with_default(const char *string, int default_value) { + int rc; + int value = default_value; + + if(string != 0) { + rc = sscanf(string, "%d", &value); + if (rc != 1) { + value = default_value; + } + } + return value; +} + +char *get_current_date_and_time(void) { + char *date_and_time = 0; + + time_t t = time(0); + struct tm tm = *localtime(&t); + struct timeval tv; + int millisec; + + gettimeofday(&tv, 0); + millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec + if(millisec>=1000) { // Allow for rounding up to nearest second + millisec -=1000; + tv.tv_sec++; + millisec /= 100; + } + + asprintf(&date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100); + + return date_and_time; +} + +long int get_microseconds_since_epoch(void) { + time_t t = time(0); + struct timeval tv; + long int useconds; + + gettimeofday(&tv, 0); + useconds = t*1000 + tv.tv_usec; //add the microseconds to the seconds + + return useconds; +} + + +bool get_local_ips(const char *ifname, char **ipv4, char **ipv6) { + assert(ifname); + assert(ipv4); + assert(ipv6); + + int s; + struct ifaddrs *ifaddr; + struct ifaddrs *ifa; + char host[NI_MAXHOST]; + bool ret = true; + + *ipv4 = 0; + *ipv6 = 0; + + if (getifaddrs(&ifaddr) == -1) { + ret = false; + goto get_local_ips_free; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) { + continue; + } + + s = getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if((strcmp(ifa->ifa_name, ifname) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) { + if (s != 0) { + ret = false; + goto get_local_ips_free; + } + + *ipv4 = strdup(host); + break; + } + } + + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) { + continue; + } + + s = getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in6),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if((strcmp(ifa->ifa_name, ifname) == 0) && (ifa->ifa_addr->sa_family == AF_INET6)) { + if (s != 0) { + ret = false; + goto get_local_ips_free; + } + + *ipv6 = strdup(host); + break; + } + } + + get_local_ips_free: + if(ret == false) { + free(*ipv4); + free(*ipv6); + *ipv4 = 0; + *ipv6 = 0; + } + + freeifaddrs(ifaddr); + return ret; +} + +bool check_port_open(const char *host, uint16_t port) { + assert(host); + + int simpleSocket = 0; + int returnStatus = 0; + struct addrinfo simpleServer; + struct addrinfo *res; + + memset(&simpleServer, 0, sizeof simpleServer); + simpleServer.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + simpleServer.ai_socktype = SOCK_STREAM; + simpleServer.ai_flags = AI_ADDRCONFIG; + + char sport[10]; + sprintf(sport, "%d", port); + + returnStatus = getaddrinfo(host, sport, &simpleServer, &res); + if(returnStatus != 0) { + return false; + } + + simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if(simpleSocket < 0) { + freeaddrinfo(res); + return false; + } + + char s[INET6_ADDRSTRLEN]; + switch(res->ai_addr->sa_family) { + case AF_INET: { + struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr; + inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN); + returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen); + break; + } + + case AF_INET6: { + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res->ai_addr; + inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN); + returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen); + break; + } + + default: + break; + } + + freeaddrinfo(res); + if(returnStatus == 0) { + close(simpleSocket); + return true; + } + + return false; +} + +char *b64_encode(const unsigned char *data, size_t input_length) { + assert(data); + assert(input_length); + + int output_length = 4 * ((input_length + 2) / 3); + + char *encoded_data = (char *)malloc(sizeof(char) * (output_length + 1)); + if (encoded_data == 0) { + return 0; + } + + for (int i = 0, j = 0; i < input_length;) { + uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0; + uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0; + uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0; + + uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; + + encoded_data[j++] = b64_encoding_table[(triple >> 3 * 6) & 0x3F]; + encoded_data[j++] = b64_encoding_table[(triple >> 2 * 6) & 0x3F]; + encoded_data[j++] = b64_encoding_table[(triple >> 1 * 6) & 0x3F]; + encoded_data[j++] = b64_encoding_table[(triple >> 0 * 6) & 0x3F]; + } + + for (int i = 0; i < b64_mod_table[input_length % 3]; i++) { + encoded_data[output_length - 1 - i] = '='; + } + + encoded_data[output_length] = 0; + + return encoded_data; +} + +char *str_replace(const char *orig, const char *rep, const char *with) { + assert(orig); + assert(rep); + assert(with); + + char *result; // the return string + const char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if(!orig || !rep) { + return 0; + } + + len_rep = strlen(rep); + if(len_rep == 0) { + return 0; // empty rep causes infinite loop during count + } + + if (!with) { + with = ""; + } + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for(count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if(!result) { + return 0; + } + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while(count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + + strcpy(tmp, orig); + return result; +} + +char *read_key(const char *filename) { + assert(filename); + + FILE * fp = 0; + char * line = 0; + size_t len = 0; + ssize_t read; + char *key_string = 0; + + fp = fopen(filename, "r"); + if(fp == 0) { + log_error("could not open file %s", filename); + return 0; + } + + while((read = getline(&line, &len, fp)) != -1) { + // we ignore the first and last lines forPrivate keys, Public keys and Certificates + if(strstr(line, "PRIVATE KEY-----") || strstr(line, "PUBLIC KEY-----") || strstr(line, "CERTIFICATE-----")) { + free(line); + line = 0; + len = 0; + continue; + } + else { + if(key_string) { + key_string = (char *)realloc(key_string, strlen(key_string) + read + 1); + if(key_string == 0) { + log_error("bad allocation"); + free(line); + return 0; + } + + strcat(key_string, line); + } + else { + key_string = strdup(line); + if(key_string == 0) { + log_error("bad allocation"); + free(line); + return 0; + } + } + + free(line); + line = 0; + len = 0; + } + } + + fclose(fp); + if(line) { + free(line); + } + + return key_string; +}