From fdb523a02680f5aa0727b862f0616ba5f8cb24cf Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Tue, 12 Nov 2019 00:03:08 +0100 Subject: [HICN-386] Improve API error management in libhicnctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I332e74ebcd89798c93de50ae7a20f7af8f59f54c Signed-off-by: Jordan Augé --- lib/includes/CMakeLists.txt | 4 + lib/includes/hicn/util/array.h | 199 ++++++++++++++++++++++++++++++++ lib/includes/hicn/util/log.h | 66 +++++++++++ lib/includes/hicn/util/map.h | 250 +++++++++++++++++++++++++++++++++++++++++ lib/includes/hicn/util/set.h | 228 +++++++++++++++++++++++++++++++++++++ lib/src/CMakeLists.txt | 1 + lib/src/policy.c | 2 + lib/src/util/ip_address.c | 70 +++++------- lib/src/util/log.c | 178 +++++++++++++++++++++++++++++ 9 files changed, 958 insertions(+), 40 deletions(-) create mode 100644 lib/includes/hicn/util/array.h create mode 100644 lib/includes/hicn/util/log.h create mode 100644 lib/includes/hicn/util/map.h create mode 100644 lib/includes/hicn/util/set.h create mode 100644 lib/src/util/log.c (limited to 'lib') diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt index d1eaa0b57..60247909c 100644 --- a/lib/includes/CMakeLists.txt +++ b/lib/includes/CMakeLists.txt @@ -47,7 +47,11 @@ set(LIBHICN_HEADER_FILES_PROTOCOL ) set(LIBHICN_HEADER_FILES_UTIL + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/array.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ip_address.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/map.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/set.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/token.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/types.h PARENT_SCOPE diff --git a/lib/includes/hicn/util/array.h b/lib/includes/hicn/util/array.h new file mode 100644 index 000000000..ab8852ed8 --- /dev/null +++ b/lib/includes/hicn/util/array.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * 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. + */ + +/** + * \file array.h + * \brief Generic array template + */ + +#ifndef UTIL_ARRAY_H +#define UTIL_ARRAY_H + +#include +#include +#include // log2 +#include // memmove + +#define BUFSIZE 1024 + +typedef int(*cmp_t)(const void * x, const void * y); + +#define TYPEDEF_ARRAY_H(NAME, T) \ + \ +typedef struct { \ + size_t size; \ + size_t max_size_log; \ + T * elements; \ +} NAME ## _t; \ + \ +int NAME ## _initialize(NAME ## _t * array); \ + \ +int NAME ## _finalize(NAME ## _t * array); \ + \ +NAME ## _t * NAME ## _create(); \ + \ +void NAME ## _free(NAME ## _t * array); \ + \ +int NAME ## _add(NAME ## _t * array, T element); \ + \ +int NAME ## _remove_index(NAME ## _t * array, int index, T * element); \ + \ +int NAME ## _remove(NAME ## _t * array, const T search, T * element); \ + \ +int NAME ## _get(const NAME ## _t * array, const T search, T * element); \ + \ +int NAME ## _get_index(const NAME ## _t * array, int index, T * element); \ + \ +int NAME ## _get_elements(const NAME ## _t * array, T ** elements); \ + \ +size_t NAME ## _len(const NAME ## _t * array); + + +#define ARRAY_MAX_SIZE_LOG_INIT 0 + +#define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \ +int \ +NAME ## _initialize(NAME ## _t * array) \ +{ \ + array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \ + array->size = 0; \ + if (array->max_size_log == 0) { \ + array->elements = NULL; \ + return 0; \ + } \ + array->elements = malloc((1 << array->max_size_log) * sizeof(T)); \ + if (!array->elements) \ + return -1; \ + return 0; \ +} \ + \ +int \ +NAME ## _finalize(NAME ## _t * array) \ +{ \ + for (unsigned i = 0; i < array->size; i++) { \ + NAME ## _remove_index(array, i, NULL); \ + } \ + return 0; \ +} \ + \ +NAME ## _t * \ +NAME ## _create() \ +{ \ + NAME ## _t * array = malloc(sizeof(NAME ## _t)); \ + if (!array) \ + goto ERR_MALLOC; \ + \ + if (NAME ## _initialize(array) < 0) \ + goto ERR_INITIALIZE; \ + \ + return array; \ + \ +ERR_INITIALIZE: \ + free(array); \ +ERR_MALLOC: \ + return NULL; \ +} \ + \ +void \ +NAME ## _free(NAME ## _t * array) \ +{ \ + NAME ## _finalize(array); \ + free(array->elements); \ + free(array); \ +} \ + \ +int \ +NAME ## _add(NAME ## _t * array, T element) \ +{ \ + /* Ensure sufficient space for next addition */ \ + size_t new_size_log = (array->size > 0) ? log2(array->size)+1 : 1; \ + if (new_size_log > array->max_size_log) { \ + array->max_size_log = new_size_log; \ + array->elements = realloc(array->elements, \ + (1 << new_size_log) * sizeof(T)); \ + } \ + \ + if (!array->elements) \ + goto ERR_REALLOC; \ + \ + array->elements[array->size++] = element; \ + return 0; \ + \ +ERR_REALLOC: \ + return -1; \ +} \ + \ +int \ +NAME ## _remove_index(NAME ## _t * array, int index, T * element) \ +{ \ + if (index > NAME ## _len(array)) \ + return -1; \ + if (element) \ + *element = array->elements[index]; \ + if (index < array->size) \ + memmove(array->elements + index, array->elements + index + 1, \ + array->size - index); \ + array->size--; \ + return 0; \ +} \ + \ +int \ +NAME ## _remove(NAME ## _t * array, const T search, T * element) \ +{ \ + for (unsigned i = 0; i < array->size; i++) { \ + if (CMP(search, array->elements[i]) == 0) \ + return facelet_array_remove_index(array, i, element); \ + } \ + /* Not found */ \ + if (element) \ + *element = NULL; \ + return 0; \ +} \ + \ +int \ +NAME ## _get(const NAME ## _t * array, const T search, T * element) \ +{ \ + assert(element); \ + for (unsigned i = 0; i < array->size; i++) \ + if (CMP(search, array->elements[i]) == 0) \ + *element = array->elements[i]; \ + return 0; \ + /* Not found */ \ + *element = NULL; \ + return 0; \ +} \ + \ +int \ +NAME ## _get_index(const NAME ## _t * array, int index, T * element) \ +{ \ + assert(element); \ + *element = array->elements[index]; \ + return 0; \ +} \ + \ +int \ +NAME ## _get_elements(const NAME ## _t * array, T ** elements) \ +{ \ + *elements = array->elements; \ + return 0; \ +} \ + \ +size_t \ +NAME ## _len(const NAME ## _t * array) \ +{ \ + return array->size; \ +} + +#endif /* UTIL_ARRAY_H */ diff --git a/lib/includes/hicn/util/log.h b/lib/includes/hicn/util/log.h new file mode 100644 index 000000000..f1cafba47 --- /dev/null +++ b/lib/includes/hicn/util/log.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * 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. + */ + +#ifndef UTIL_LOG_H +#define UTIL_LOG_H + +#include // va_* +#include // FILE +#include // time, localtime + +#define LOG_FATAL 0 +#define LOG_ERROR 1 +#define LOG_WARN 2 +#define LOG_INFO 3 +#define LOG_DEBUG 4 +#define LOG_TRACE 5 + +typedef struct { + int log_level; + int debug; + FILE * log_file; +} log_conf_t; + +#define DEFAULT_LOG_CONF { \ + .log_level = LOG_DEBUG, \ + .debug = 0, \ + .log_file = NULL, \ +}; + +extern log_conf_t log_conf; + +#define WITH_DEBUG(BLOCK) \ + if (log_conf.log_level >= LOG_DEBUG) \ + BLOCK + +#define FATAL(fmt, ...) (_log(LOG_FATAL, fmt, ##__VA_ARGS__ )) +#define ERROR(fmt, ...) (_log(LOG_ERROR, fmt, ##__VA_ARGS__ )) +#define WARN(fmt, ...) (_log(LOG_WARN, fmt, ##__VA_ARGS__ )) +#define INFO(fmt, ...) (_log(LOG_INFO, fmt, ##__VA_ARGS__ )) +#define DEBUG(fmt, ...) (_log(LOG_DEBUG, fmt, ##__VA_ARGS__ )) +#define TRACE(fmt, ...) (_log(LOG_TRACE, fmt, ##__VA_ARGS__ )) + +void _log_va(int level, const char *fmt, va_list ap); + +void _log(int level, const char *fmt, ...); + +void fatal(char *fmt, ...); + +#ifdef HAVE_BACKTRACE +#include +void print_trace(void); +#endif + +#endif // UTIL_LOG_H diff --git a/lib/includes/hicn/util/map.h b/lib/includes/hicn/util/map.h new file mode 100644 index 000000000..1ac5812ef --- /dev/null +++ b/lib/includes/hicn/util/map.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * 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. + */ + +#ifndef UTIL_MAP_H +#define UTIL_MAP_H + +#include + +#include "set.h" + +#define ERR_MAP_EXISTS -2 +#define ERR_MAP_NOT_FOUND -3 + +#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \ + \ +typedef struct { \ + KEY_T key; \ + VAL_T value; \ +} NAME ## _pair_t; \ + \ +NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value); \ + \ +void NAME ## _pair_free(NAME ## _pair_t * pair); \ + \ +int NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2); \ + \ +TYPEDEF_SET_H(NAME ## _pair_set, NAME ## _pair_t *) \ + \ +typedef struct NAME ## _s { \ + NAME ## _pair_set_t pair_set; \ +} NAME ## _t; \ + \ +int NAME ## _initialize(NAME ## _t * map); \ + \ +int NAME ## _finalize(NAME ## _t * map); \ + \ +NAME ## _t * NAME ## _create(); \ + \ +void NAME ## _free(NAME ## _t * map); \ + \ +int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value); \ + \ +int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value); \ + \ +int NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value); \ + \ +void NAME ## _dump(NAME ## _t * map); + + + + +#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \ + \ +NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value) \ +{ \ + /* Create pair */ \ + NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t)); \ + if (!pair) \ + return NULL; \ + \ + pair->key = key; \ + pair->value = value; \ + \ + return pair; \ +} \ + \ +void NAME ## _pair_free(NAME ## _pair_t * pair) \ +{ \ + free(pair); \ +} \ + \ +int \ +NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2) \ +{ \ + return (CMP(p1->key, p2->key)); \ +} \ + \ +int \ +NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) { \ + int rc; \ + rc = KEY_SNPRINTF(buf, BUFSIZE/2, (KEY_T)pair->key); \ + if (rc < 0) \ + return rc; \ + rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value); \ + return rc; \ +} \ + \ +TYPEDEF_SET(NAME ## _pair_set, NAME ## _pair_t *, NAME ## _pair_cmp, NAME ## _pair_snprintf); \ + \ +int \ +NAME ## _initialize(NAME ## _t * map) \ +{ \ + return NAME ## _pair_set_initialize(&map->pair_set); \ +} \ + \ +int \ +NAME ## _finalize(NAME ## _t * map) \ +{ \ + NAME ## _pair_t ** array; \ + int n = NAME ## _pair_set_get_array(&map->pair_set, &array); \ + if (n < 0) \ + return -1; \ + for (unsigned i = 0; i < n; i++) { \ + NAME ## _pair_t * pair = array[i]; \ + NAME ## _pair_set_remove(&map->pair_set, pair, NULL); \ + NAME ## _pair_free(pair); \ + } \ + free(array); \ + return NAME ## _pair_set_finalize(&map->pair_set); \ +} \ + \ +NAME ## _t * \ +NAME ## _create() \ +{ \ + NAME ## _t * map = malloc(sizeof(NAME ## _t)); \ + if (!map) \ + goto ERR_MALLOC; \ + \ + if (NAME ## _initialize(map) < 0) \ + goto ERR_INITIALIZE; \ + \ + return map; \ + \ +ERR_INITIALIZE: \ + free(map); \ +ERR_MALLOC: \ + return NULL; \ +} \ + \ +void \ +NAME ## _free(NAME ## _t * map) \ +{ \ + NAME ## _finalize(map); \ + free(map); \ +} \ + \ +int \ +NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value) \ +{ \ + int rc; \ + NAME ## _pair_t * found = NULL; \ + \ + NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \ + if (!pair) \ + return -1; \ + \ + rc = NAME ## _pair_set_get(&map->pair_set, pair, &found); \ + if (rc < 0) \ + return -1; \ + if (found) { \ + NAME ## _pair_free(pair); \ + return ERR_MAP_EXISTS; \ + } \ + \ + rc = NAME ## _pair_set_add(&map->pair_set, pair); \ + if (rc < 0) { \ + NAME ## _pair_free(pair); \ + return -1; \ + } \ + return 0; \ +} \ + \ +int \ +NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value) \ +{ \ + NAME ## _pair_t * found = NULL; \ + NAME ## _pair_t search = { .key = key }; \ + int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found); \ + if (rc < 0) \ + return ERR_MAP_NOT_FOUND; \ + if (value) \ + *value = found->value; \ + NAME ## _pair_free(found); \ + return 0; \ +} \ + \ +int \ +NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value) \ +{ \ + NAME ## _pair_t * found = NULL, search = { .key = key }; \ + int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found); \ + if (rc < 0) \ + return -1; \ + if (found) \ + *value = found->value; \ + return 0; \ +} \ + \ +void \ +NAME ## _dump(NAME ## _t * map) { \ + NAME ## _pair_set_dump(&map->pair_set); \ +} \ + \ +int \ +NAME ## _get_key_array(NAME ## _t * map, KEY_T **array) { \ + NAME ## _pair_t ** pair_array; \ + int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \ + if (n < 0) \ + return -1; \ + if (!array) \ + goto END; \ + /* Allocate result array */ \ + *array = malloc(n * sizeof(KEY_T)); \ + if (!array) { \ + free(pair_array); \ + return -1; \ + } \ + /* Copy keys */ \ + for (int i = 0; i < n; i++) \ + (*array)[i] = pair_array[i]->key; \ + free(pair_array); \ +END: \ + return n; \ +} \ + \ +int \ +NAME ## _get_value_array(NAME ## _t * map, VAL_T **array) { \ + NAME ## _pair_t ** pair_array; \ + int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \ + if (n < 0) \ + return -1; \ + if (!array) \ + goto END; \ + /* Allocate result array */ \ + *array = malloc(n * sizeof(VAL_T)); \ + if (!array) { \ + free(pair_array); \ + return -1; \ + } \ + /* Copy values */ \ + for (int i = 0; i < n; i++) \ + (*array)[i] = pair_array[i]->value; \ + free(pair_array); \ +END: \ + return n; \ +} + +#endif /* UTIL_MAP_H */ diff --git a/lib/includes/hicn/util/set.h b/lib/includes/hicn/util/set.h new file mode 100644 index 000000000..c1f43918b --- /dev/null +++ b/lib/includes/hicn/util/set.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * 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. + */ + +#ifndef UTIL_SET_H +#define UTIL_SET_H + +#include +#include +#include +//#if !defined(__ANDROID__) && !defined(__APPLE__) +//#include +//#else +#define thread_local _Thread_local +//#endif /* ! __ANDROID__ */ + +#define ERR_SET_EXISTS -2 +#define ERR_SET_NOT_FOUND -3 + +/* FIXME: buffer overflow when this is too small... investigate */ +#define BUFSIZE 1024 + +static inline +int +int_cmp(const int x, const int y) +{ + return x - y; +} + +static inline +int +int_snprintf(char * buf, size_t size, int value) { + return snprintf(buf, size, "%d", value); +} + +static inline +int +string_snprintf(char * buf, size_t size, const char * s) { + return snprintf(buf, size, "%s", s); +} + +static inline +int +generic_snprintf(char * buf, size_t size, const void * value) { + return snprintf(buf, BUFSIZE, "%p", value); +} + +typedef int(*cmp_t)(const void * x, const void * y); + +#define TYPEDEF_SET_H(NAME, T) \ + \ +typedef struct { \ + size_t size; \ + void * root; \ +} NAME ## _t; \ + \ +int NAME ## _initialize(NAME ## _t * set); \ + \ +int NAME ## _finalize(NAME ## _t * set); \ + \ +NAME ## _t * NAME ## _create(); \ + \ +void NAME ## _free(NAME ## _t * set); \ + \ +int NAME ## _add(NAME ## _t * set, const T element); \ + \ +int NAME ## _remove(NAME ## _t * set, const T search, T * element); \ + \ +int NAME ## _get(const NAME ## _t * set, const T search, T * element); \ + \ +int NAME ## _get_array(const NAME ## _t * set, T ** element); \ + \ +void NAME ## _dump(NAME ## _t * set); + + + + +#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \ +int \ +NAME ## _initialize(NAME ## _t * set) \ +{ \ + set->root = NULL; \ + set->size = 0; \ + return 0; \ +} \ + \ +int \ +NAME ## _finalize(NAME ## _t * set) \ +{ \ + T * array; \ + int n = NAME ## _get_array(set, &array); \ + if (n < 0) \ + return -1; \ + for (unsigned i = 0; i < n; i++) { \ + T element = array[i]; \ + NAME ## _remove(set, element, NULL); \ + } \ + free(array); \ + return 0; \ +} \ + \ +NAME ## _t * \ +NAME ## _create() \ +{ \ + NAME ## _t * set = malloc(sizeof(NAME ## _t)); \ + if (!set) \ + goto ERR_MALLOC; \ + \ + if (NAME ## _initialize(set) < 0) \ + goto ERR_INITIALIZE; \ + \ + return set; \ + \ +ERR_INITIALIZE: \ + free(set); \ +ERR_MALLOC: \ + return NULL; \ +} \ + \ +void \ +NAME ## _free(NAME ## _t * set) \ +{ \ + NAME ## _finalize(set); \ + free(set); \ +} \ + \ +int \ +NAME ## _add(NAME ## _t * set, const T element) \ +{ \ + void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \ + if (!ptr) \ + return -1; \ + set->size++; \ + return 0; \ +} \ + \ +int \ +NAME ## _remove(NAME ## _t * set, const T search, T * element) \ +{ \ + T * found = tfind(search, &set->root, (cmp_t)CMP); \ + if (!found) \ + return ERR_SET_NOT_FOUND; \ + if (element) \ + *element = *found; \ + tdelete(search, &set->root, (cmp_t)CMP); \ + set->size--; \ + return 0; \ +} \ + \ +int \ +NAME ## _get(const NAME ## _t * set, const T search, T * element) \ +{ \ + T * found = tfind(search, &set->root, (cmp_t)CMP); \ + if (element) \ + *element = found ? *found : NULL; \ + return 0; \ +} \ + \ +static void \ +NAME ## _dump_node(const void *nodep, const VISIT which, \ + const int depth) \ +{ \ + char buf[BUFSIZE]; \ + switch (which) { \ + case preorder: \ + case endorder: \ + break; \ + case postorder: \ + case leaf: \ + SNPRINTF(buf, BUFSIZE, *(T*)nodep); \ + INFO("%s", buf); \ + break; \ + } \ +} \ + \ +void \ +NAME ## _dump(NAME ## _t * set) { \ + twalk(set->root, NAME ## _dump_node); \ +} \ + \ +thread_local \ +T * NAME ## _array_pos = NULL; \ + \ +static void \ +NAME ## _add_node_to_array(const void *nodep, const VISIT which, \ + const int depth) \ +{ \ + if (!NAME ## _array_pos) \ + return; \ + switch (which) { \ + case preorder: \ + case endorder: \ + break; \ + case postorder: \ + case leaf: \ + *NAME ## _array_pos = *(T*)nodep; \ + NAME ## _array_pos++; \ + break; \ + } \ +} \ + \ +int \ +NAME ## _get_array(const NAME ## _t * set, T ** element) \ +{ \ + if (!element) \ + goto END; \ + *element = malloc(set->size * sizeof(T)); \ + if (!*element) \ + return -1; \ + NAME ## _array_pos = *element; \ + twalk(set->root, NAME ## _add_node_to_array); \ + NAME ## _array_pos = NULL; \ +END: \ + return set->size; \ +} + +#endif /* UTIL_SET_H */ diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt index d8c7b11e0..f68e7a551 100644 --- a/lib/src/CMakeLists.txt +++ b/lib/src/CMakeLists.txt @@ -27,6 +27,7 @@ list(APPEND LIBHICN_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv6.c ${CMAKE_CURRENT_SOURCE_DIR}/protocol/tcp.c ${CMAKE_CURRENT_SOURCE_DIR}/util/ip_address.c + ${CMAKE_CURRENT_SOURCE_DIR}/util/log.c ) set (COMPILER_DEFINITIONS "-DWITH_MAPME") diff --git a/lib/src/policy.c b/lib/src/policy.c index 336249bbb..edbb02bea 100644 --- a/lib/src/policy.c +++ b/lib/src/policy.c @@ -49,6 +49,8 @@ policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t * tag_ return -1; rc = snprintf(cur, s + size - cur, "%s%s", (tag_state->disabled == 1) ? "!" : "", policy_state_str[tag_state->state]); + if (rc >= s + size - cur) + return s + size - cur; if (rc < 0) return rc; cur += rc; diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c index 062ff8c75..2b7c69bb5 100644 --- a/lib/src/util/ip_address.c +++ b/lib/src/util/ip_address.c @@ -19,6 +19,7 @@ */ #include +#include #if __BYTE_ORDER == __LITTLE_ENDIAN #ifdef __ANDROID__ @@ -110,11 +111,13 @@ ip_address_pton (const char *ip_address_str, ip_address_t * ip_address) int pton_fd; int family; - family = ip_address_get_family (ip_address_str); switch (family) { case AF_INET: + ip_address->pad[0] = 0; + ip_address->pad[1] = 0; + ip_address->pad[2] = 0; pton_fd = inet_pton (AF_INET, ip_address_str, &ip_address->v4.buffer); break; case AF_INET6: @@ -135,18 +138,26 @@ ip_address_pton (const char *ip_address_str, ip_address_t * ip_address) int ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address, int family) { + const char * rc; switch(family) { case AF_INET: + if (size <= INET_ADDRSTRLEN) + return -1; rc = inet_ntop (AF_INET, ip_address->v4.buffer, s, INET_ADDRSTRLEN); - break; + if (!rc) + return -1; + return INET_ADDRSTRLEN; case AF_INET6: + if (size <= INET6_ADDRSTRLEN) + return -1; rc = inet_ntop (AF_INET6, ip_address->v6.buffer, s, INET6_ADDRSTRLEN); - break; + if (!rc) + return -1; + return INET6_ADDRSTRLEN; default: return -1; } - return rc ? strlen(rc) : -1; } int @@ -269,9 +280,10 @@ ip_prefix_ntop_short(const ip_prefix_t * ip_prefix, char *dst, size_t size) } if (!s) return -1; - size_t n = snprintf(dst, size, "%s", ip_s); - - return (n > 0 ? 1 : -1); + int rc = snprintf(dst, size, "%s", ip_s); + if (rc >= size) + return size; + return rc; } int @@ -291,9 +303,10 @@ ip_prefix_ntop(const ip_prefix_t * ip_prefix, char *dst, size_t size) } if (!s) return -1; - size_t n = snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len); - - return (n > 0 ? 1 : -1); + int rc = snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len); + if (rc >= size) + return size; + return rc; } int @@ -361,42 +374,19 @@ int url_snprintf(char * s, size_t size, int family, const ip_address_t * ip_address, u16 port) { - char * cur = s; + char ip_address_s[MAXSZ_IP_ADDRESS]; int rc; /* Other address are currently not supported */ - if (!IS_VALID_FAMILY(family)) { + if (!IS_VALID_FAMILY(family)) return -1; - } - - rc = snprintf(cur, s + size - cur, "inet%c://", - (family == AF_INET) ? '4' : '6'); - if (rc < 0) - return rc; - cur += rc; - if (size != 0 && cur >= s + size) - return cur - s; - - rc = ip_address_snprintf(cur, s + size - cur, ip_address, family); - if (rc < 0) - return rc; - cur += rc; - if (size != 0 && cur >= s + size) - return cur - s; - - rc = snprintf(cur, s + size - cur, ":"); - if (rc < 0) - return rc; - cur += rc; - if (size != 0 && cur >= s + size) - return cur - s; - rc = snprintf(cur, s + size - cur, "%d", port); + rc = ip_address_snprintf(ip_address_s, MAXSZ_IP_ADDRESS, ip_address, family); + if (rc >= MAXSZ_IP_ADDRESS) + WARN("[url_snprintf] Unexpected ip_address truncation"); if (rc < 0) return rc; - cur += rc; - if (size != 0 && cur >= s + size) - return cur - s; - return cur - s; + return snprintf(s, size, "inet%c://%s:%d", (family == AF_INET) ? '4' : '6', + ip_address_s, port); } diff --git a/lib/src/util/log.c b/lib/src/util/log.c new file mode 100644 index 000000000..c1fc999ad --- /dev/null +++ b/lib/src/util/log.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * 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. + */ + +#include + +#include +#include +#include + +#ifdef __ANDROID__ +#include +#endif + +log_conf_t log_conf = DEFAULT_LOG_CONF; + +#define FMT_DATETIME "%02d-%02d-%04d %02d:%02d:%02d" +#define FMT_DATETIME_LEN 20 +#define snprintf_nowarn(...) (snprintf(__VA_ARGS__) < 0 ? abort() : (void)0) + + +static char ts[FMT_DATETIME_LEN]; + +static char *timestamp(void) +{ + time_t tv; + struct tm *tm; + + time(&tv); + tm = localtime(&tv); + + snprintf_nowarn(ts, FMT_DATETIME_LEN, FMT_DATETIME, tm->tm_mday, + tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, + tm->tm_sec); + return ts; +} + +void _log_va(int level, const char *fmt, va_list ap) +{ + +#if 0 + if (!conf.log_system) + return; +#endif + + char *prefix; + +#ifdef __ANDROID__ + int prio = -1; + if (level > log_conf.log_level) + return; + + switch (level) { + case LOG_FATAL: + prio = ANDROID_LOG_FATAL; + prefix = "FATAL: "; + break; + case LOG_ERROR: + prio = ANDROID_LOG_ERROR; + prefix = "ERROR: "; + break; + case LOG_WARN: + prio = ANDROID_LOG_WARN; + prefix = "WARNING: "; + break; + case LOG_INFO: + prio = ANDROID_LOG_INFO; + prefix = ""; + break; + case LOG_DEBUG: + prio = ANDROID_LOG_DEBUG; + prefix = "DEBUG: "; + break; + case LOG_TRACE: + prio = ANDROID_LOG_DEBUG; + prefix = "TRACE: "; + break; + default: + prio = ANDROID_LOG_INFO; + prefix = ""; + break; + } + + if (log_conf.log_file) { + FILE *f = log_conf.log_file; + fprintf(f, "%s %s", timestamp(), prefix); + vfprintf(f, fmt, ap); + fprintf(f, "\n"); + } else { + __android_log_vprint(ANDROID_LOG_INFO, "HICN FACEMGR", fmt, ap); + } + +#else + + if (level > log_conf.log_level) + return; + + switch (level) { + case LOG_FATAL: + prefix = "FATAL: "; + break; + case LOG_ERROR: + prefix = "ERROR: "; + break; + case LOG_WARN: + prefix = "WARNING: "; + break; + case LOG_INFO: + prefix = ""; + break; + case LOG_DEBUG: + prefix = "DEBUG: "; + break; + case LOG_TRACE: + prefix = "TRACE: "; + break; + default: + prefix = ""; + break; + } + FILE *f = log_conf.log_file ? log_conf.log_file : stdout; + fprintf(f, "%s %s", timestamp(), prefix); + vfprintf(f, fmt, ap); + fprintf(f, "\n"); +#ifdef DEBUG + fflush(f); +#endif +#endif +} + +void _log(int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _log_va(level, fmt, ap); + va_end(ap); +} + +#ifdef HAVE_BACKTRACE +#include + +void print_trace(void) +{ + void *array[32]; + size_t size; + + size = backtrace(array, 32); + fflush(conf.log_file); + backtrace_symbols_fd(array, size, fileno(conf.log_file)); +} +#endif + +void fatal(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _log_va(LOG_FATAL, fmt, ap); + va_end(ap); + +#ifdef HAVE_BACKTRACE + print_trace(); +#endif + + exit(200); +} -- cgit 1.2.3-korg