diff --git a/.travis.yml b/.travis.yml index 902e78bc..be14c02b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,18 @@ +sudo: required +dist: trusty + language: c -install: - - sudo apt-get install cppcheck -y +before_install: + - sudo apt-get -qq update + - sudo apt-get -y install cppcheck doxygen libssh-dev + script: - scripts/cppcheck.sh - + - cmake -D CMAKE_BUILD_TYPE=NoSSH . + - make + - make test + - make clean - cmake -D CMAKE_BUILD_TYPE=Release . - make - + - make test diff --git a/CMakeLists.txt b/CMakeLists.txt index bcff06d5..f14b0ece 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,12 @@ project(rtrlib) cmake_minimum_required(VERSION 2.6) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) - +set(NOSSH false) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=gnu99 -fstack-protector-all") if(CMAKE_BUILD_TYPE STREQUAL Debug) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Wfree-nonheap-object -Wformat-security -Wmissing-prototypes -Wmissing-declarations -Wdeclaration-after-statement -Winit-self -Waggregate-return -Wmissing-format-attribute -Wundef -Wbad-function-cast -Wwrite-strings -Wformat=2") +elseif(CMAKE_BUILD_TYPE STREQUAL NoSSH) + set(NOSSH true) else() endif(CMAKE_BUILD_TYPE STREQUAL Debug) @@ -23,7 +25,7 @@ set(RTRLIB_SRC rtrlib/rtr_mgr.c rtrlib/lib/utils.c rtrlib/lib/ip.c rtrlib/lib/ip set(RTRLIB_LINK ${RT_LIB} ${CMAKE_THREAD_LIBS_INIT}) find_package(LibSSH 0.6.0) -if(LIBSSH_FOUND) +if(LIBSSH_FOUND AND NOT NOSSH) set(RTRLIB_HAVE_LIBSSH 1) message(STATUS "libssh found, building librtr with SSH support") @@ -37,8 +39,8 @@ endif(LIBSSH_FOUND) #doxygen target find_package(Doxygen) if(DOXYGEN_FOUND) - add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile - COMMENT "Generating doxygen API documentation" VERBATIM) + add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile + COMMENT "Generating doxygen API documentation" VERBATIM) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/docs DESTINATION share/doc/rtrlib) endif(DOXYGEN_FOUND) @@ -53,11 +55,12 @@ ADD_SUBDIRECTORY(tests) ENABLE_TESTING() ADD_TEST(test_pfx tests/test_pfx) ADD_TEST(test_lpfst tests/test_lpfst) -ADD_TEST(test_pfx_locks tests/test_pfx_locks) +#ADD_TEST(test_pfx_locks tests/test_pfx_locks) ADD_TEST(test_ht_spkitable tests/test_ht_spkitable) ADD_TEST(test_ht_spkitable_locks tests/test_ht_spkitable_locks) +ADD_TEST(test_live_validation tests/test_live_validation) #install lib set (RTRLIB_VERSION_MAJOR 0) diff --git a/rtrlib/lib/ip.c b/rtrlib/lib/ip.c index e75671a2..79430558 100644 --- a/rtrlib/lib/ip.c +++ b/rtrlib/lib/ip.c @@ -63,6 +63,7 @@ int lrtr_ip_str_to_addr(const char *str, struct lrtr_ip_addr *ip) return lrtr_ipv6_str_to_addr(str, &(ip->u.addr6)); } +// cppcheck-suppress unusedFunction bool lrtr_ip_str_cmp(const struct lrtr_ip_addr *addr1, const char *addr2) { struct lrtr_ip_addr tmp; diff --git a/rtrlib/lib/ipv4.c b/rtrlib/lib/ipv4.c index c28d0e7f..b970efbf 100644 --- a/rtrlib/lib/ipv4.c +++ b/rtrlib/lib/ipv4.c @@ -32,7 +32,7 @@ int lrtr_ipv4_addr_to_str(const struct lrtr_ipv4_addr *ip, char *str, unsigned i int lrtr_ipv4_str_to_addr(const char *str, struct lrtr_ipv4_addr *ip) { unsigned char *t = (unsigned char *) &(ip->addr); - if(sscanf(str, "%hhu.%hhu.%hhu.%hhu", &(t[3]), &(t[2]), &(t[1]), &(t[0])) != 4) + if(sscanf(str, "%3hhu.%3hhu.%3hhu.%3hhu", &(t[3]), &(t[2]), &(t[1]), &(t[0])) != 4) return -1; return 0; } diff --git a/rtrlib/lib/ipv6.c b/rtrlib/lib/ipv6.c index 8ddec789..5ed63f7b 100644 --- a/rtrlib/lib/ipv6.c +++ b/rtrlib/lib/ipv6.c @@ -61,7 +61,6 @@ struct lrtr_ipv6_addr lrtr_ipv6_get_bits(const struct lrtr_ipv6_addr *val, const const uint8_t fr = first_bit < 96 ? 0 : first_bit - 127; const uint8_t q = bits_left > 32 ? 32 : bits_left; assert(bits_left >= q); - bits_left -= q; result.addr[3] = lrtr_get_bits(val->addr[3], fr, q); } return result; diff --git a/rtrlib/pfx/lpfst/lpfst-pfx.c b/rtrlib/pfx/lpfst/lpfst-pfx.c index 9c0a4ea2..6b61aa34 100644 --- a/rtrlib/pfx/lpfst/lpfst-pfx.c +++ b/rtrlib/pfx/lpfst/lpfst-pfx.c @@ -54,8 +54,9 @@ void pfx_table_free(struct pfx_table *pfx_table) { for(int i = 0; i < 2; i++) { struct lpfst_node *root = (i == 0 ? pfx_table->ipv4 : pfx_table->ipv6); - struct lpfst_node *rm_node; if(root != NULL) { + struct lpfst_node *rm_node; + pthread_rwlock_wrlock(&(pfx_table->lock)); do { struct node_data *data = (struct node_data *) (root->data); diff --git a/rtrlib/pfx/lpfst/lpfst.c b/rtrlib/pfx/lpfst/lpfst.c index 63020357..90f1ef81 100644 --- a/rtrlib/pfx/lpfst/lpfst.c +++ b/rtrlib/pfx/lpfst/lpfst.c @@ -110,7 +110,6 @@ struct lpfst_node *lpfst_remove(struct lpfst_node *root_node, const struct lrtr_ root_node->prefix = root_node->rchild->prefix; root_node->len = root_node->rchild->len; void *tmp = root_node->data; - tmp = root_node->data; root_node->data = root_node->rchild->data; root_node->rchild->data = tmp; return lpfst_remove(root_node->rchild, &(root_node->rchild->prefix), root_node->rchild->len, level+1); diff --git a/rtrlib/rtr/packets.c b/rtrlib/rtr/packets.c index 9aa706d3..14113912 100644 --- a/rtrlib/rtr/packets.c +++ b/rtrlib/rtr/packets.c @@ -733,16 +733,21 @@ static int rtr_store_prefix_pdu(struct rtr_socket *rtr_socket, const void *pdu, } *ary = tmp; } - if (type == IPV4_PREFIX) - memcpy((struct pdu_ipv4 *) *ary + *ind, pdu, pdu_size); - else if (type == IPV6_PREFIX) - memcpy((struct pdu_ipv6 *) *ary + *ind, pdu, pdu_size); + if (type == IPV4_PREFIX) { + struct pdu_ipv4 *ary_ipv4 = *ary; + + memcpy(ary_ipv4 + *ind, pdu, pdu_size); + } else if (type == IPV6_PREFIX) { + struct pdu_ipv6 *ary_ipv6 = *ary; + + memcpy(ary_ipv6 + *ind, pdu, pdu_size); + } (*ind)++; return RTR_SUCCESS; } -static int rtr_store_router_key_pdu(struct rtr_socket *rtr_socket, const void *pdu, const unsigned int pdu_size, void **ary, - unsigned int *ind, unsigned int *size) +static int rtr_store_router_key_pdu(struct rtr_socket *rtr_socket, const void *pdu, const unsigned int pdu_size, + struct pdu_router_key **ary, unsigned int *ind, unsigned int *size) { assert(rtr_get_pdu_type(pdu) == ROUTER_KEY); @@ -899,7 +904,7 @@ int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){ goto cleanup; } } else if (type == ROUTER_KEY) { - if (rtr_store_router_key_pdu(rtr_socket, pdu, sizeof(*router_key_pdus), (void **) &router_key_pdus, &router_key_pdus_nindex, &router_key_pdus_size) == RTR_ERROR){ + if (rtr_store_router_key_pdu(rtr_socket, pdu, sizeof(*router_key_pdus), &router_key_pdus, &router_key_pdus_nindex, &router_key_pdus_size) == RTR_ERROR){ rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL); retval = RTR_ERROR; goto cleanup; @@ -971,8 +976,10 @@ int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){ retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv4_pdus[j])); for (unsigned int j = 0; j < ipv6_pdus_nindex && retval == PFX_SUCCESS; j++) retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv6_pdus[j])); + // cppcheck-suppress duplicateExpression for (unsigned int j = 0; j < i && (retval == PFX_SUCCESS || retval == SPKI_SUCCESS); j++) retval = rtr_undo_update_spki_table(rtr_socket, &(router_key_pdus[j])); + // cppcheck-suppress duplicateExpression if (retval == RTR_ERROR || retval == SPKI_ERROR) { RTR_DBG1("Couldn't undo all update operations from failed data synchronisation: Purging all key entries"); spki_table_src_remove(rtr_socket->spki_table, rtr_socket); diff --git a/rtrlib/rtr_mgr.c b/rtrlib/rtr_mgr.c index 9ad3beb3..024f9cec 100644 --- a/rtrlib/rtr_mgr.c +++ b/rtrlib/rtr_mgr.c @@ -324,11 +324,13 @@ void rtr_mgr_free(struct rtr_mgr_config *config) free(config); } +// cppcheck-suppress unusedFunction inline int rtr_mgr_validate(struct rtr_mgr_config *config, const uint32_t asn, const struct lrtr_ip_addr *prefix, const uint8_t mask_len, enum pfxv_state *result) { return pfx_table_validate(config->groups[0].sockets[0]->pfx_table, asn, prefix, mask_len, result); } +// cppcheck-suppress unusedFunction inline int rtr_mgr_get_spki(struct rtr_mgr_config *config, const uint32_t asn, uint8_t *ski, struct spki_record *result, unsigned int *result_count) { return spki_table_get_all(config->groups[0].sockets[0]->spki_table, asn, ski, &result, result_count); @@ -349,11 +351,13 @@ const char *rtr_mgr_status_to_str(enum rtr_mgr_status status) return mgr_str_status[status]; } +// cppcheck-suppress unusedFunction inline void rtr_mgr_for_each_ipv4_record(struct rtr_mgr_config *config, void (fp)(const struct pfx_record *, void *data), void *data) { pfx_table_for_each_ipv4_record(config->groups[0].sockets[0]->pfx_table, fp, data); } +// cppcheck-suppress unusedFunction inline void rtr_mgr_for_each_ipv6_record(struct rtr_mgr_config *config, void (fp)(const struct pfx_record *, void *data), void *data) { pfx_table_for_each_ipv6_record(config->groups[0].sockets[0]->pfx_table, fp, data); diff --git a/rtrlib/spki/hashtable/ht-spkitable.c b/rtrlib/spki/hashtable/ht-spkitable.c index 233b657c..3a1fa02d 100644 --- a/rtrlib/spki/hashtable/ht-spkitable.c +++ b/rtrlib/spki/hashtable/ht-spkitable.c @@ -140,7 +140,6 @@ int spki_table_get_all(struct spki_table *spki_table, uint32_t asn, { uint32_t hash = tommy_inthash_u32(asn); tommy_node *result_bucket; - struct key_entry *element; void *tmp; *result = NULL; @@ -163,6 +162,8 @@ int spki_table_get_all(struct spki_table *spki_table, uint32_t asn, /* Build the result array */ while (result_bucket) { + struct key_entry *element; + element = result_bucket->data; if (element->asn == asn && memcmp(element->ski, ski, sizeof(element->ski)) == 0) { @@ -184,11 +185,11 @@ int spki_table_get_all(struct spki_table *spki_table, uint32_t asn, return SPKI_SUCCESS; } +// cppcheck-suppress unusedFunction int spki_table_search_by_ski(struct spki_table *spki_table, uint8_t *ski, struct spki_record **result, unsigned int *result_size) { - struct key_entry *current_entry; tommy_node *current_node; void *tmp; *result = NULL; @@ -198,7 +199,9 @@ int spki_table_search_by_ski(struct spki_table *spki_table, uint8_t *ski, current_node = tommy_list_head(&spki_table->list); while (current_node) { - current_entry = (struct key_entry *)current_node->data; + struct key_entry *current_entry; + + current_entry = (struct key_entry *)current_node->data; if (memcmp(current_entry->ski, ski, sizeof(current_entry->ski)) == 0) { (*result_size)++; diff --git a/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayblkof.h b/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayblkof.h index 3d020943..ed3a8b52 100644 --- a/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayblkof.h +++ b/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayblkof.h @@ -92,6 +92,7 @@ tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, unsigned pos) base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); +// cppcheck-suppress CastIntegerToAddressAtReturn return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; } diff --git a/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayof.h b/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayof.h index 20db9d1a..e4ee6509 100644 --- a/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayof.h +++ b/rtrlib/spki/hashtable/tommyds-1.8/tommyarrayof.h @@ -111,6 +111,7 @@ tommy_inline void* tommy_arrayof_ref(tommy_arrayof* array, unsigned pos) base = tommy_cast(unsigned char*, array->bucket[bsr - TOMMY_ARRAYOF_BIT + 1]); } +// cppcheck-suppress CastIntegerToAddressAtReturn return base + pos * array->element_size; } diff --git a/rtrlib/transport/transport.c b/rtrlib/transport/transport.c index 834eca24..18d7d361 100644 --- a/rtrlib/transport/transport.c +++ b/rtrlib/transport/transport.c @@ -20,6 +20,7 @@ inline void tr_close(struct tr_socket *socket) socket->close_fp(socket->socket); } +// cppcheck-suppress unusedFunction inline void tr_free(struct tr_socket *socket) { socket->free_fp(socket); @@ -43,13 +44,14 @@ inline const char *tr_ident(struct tr_socket *sock) int tr_send_all(const struct tr_socket *socket, const void *pdu, const size_t len, const time_t timeout) { unsigned int total_send = 0; - int rtval = 0; time_t end_time; lrtr_get_monotonic_time(&end_time); end_time = end_time + timeout; while(total_send < len) { time_t cur_time; + int rtval; + lrtr_get_monotonic_time(&cur_time); rtval = tr_send(socket, ((char *) pdu) + total_send, (len - total_send), (end_time - cur_time)); @@ -63,13 +65,14 @@ int tr_send_all(const struct tr_socket *socket, const void *pdu, const size_t le int tr_recv_all(const struct tr_socket *socket, const void *pdu, const size_t len, const time_t timeout) { size_t total_recv = 0; - int rtval = 0; time_t end_time; lrtr_get_monotonic_time(&end_time); end_time += timeout; while(total_recv < len) { time_t cur_time; + int rtval; + lrtr_get_monotonic_time(&cur_time); rtval = tr_recv(socket, ((char *) pdu)+total_recv, (len - total_recv), end_time - cur_time); diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh index d3ec56e6..5a21f8fa 100755 --- a/scripts/cppcheck.sh +++ b/scripts/cppcheck.sh @@ -1,3 +1,5 @@ #!/bin/bash -cppcheck --error-exitcode=1--enable=all -i rtrlib/spki/hashtable/tommyds-1.8/ tools/ rtrlib/ +cppcheck --error-exitcode=1 --enable=all --inline-suppr \ + --template='{id}:{file}({line}):({severity}) {message}' \ + -i rtrlib/spki/hashtable/tommyds-1.8/ tools/ rtrlib/ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 328907cd..f117dda6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,3 +10,5 @@ add_executable(test_ht_spkitable test_ht_spkitable.c) target_link_libraries(test_ht_spkitable rtrlib) add_executable(test_ht_spkitable_locks test_ht_spkitable_locks.c) target_link_libraries(test_ht_spkitable_locks rtrlib) +add_executable(test_live_validation test_live_validation.c) +target_link_libraries(test_live_validation rtrlib) diff --git a/tests/test_ht_spkitable.c b/tests/test_ht_spkitable.c index 1c462b3f..e88e5571 100644 --- a/tests/test_ht_spkitable.c +++ b/tests/test_ht_spkitable.c @@ -20,13 +20,8 @@ #include #include - static struct spki_record *create_record(int ASN, int ski_offset, int spki_offset, struct rtr_socket *socket); - - - - static bool compare_spki_records(struct spki_record *r1, struct spki_record *r2) { if(r1->asn != r2->asn) { diff --git a/tests/test_ht_spkitable_locks.c b/tests/test_ht_spkitable_locks.c index df7a40f9..7b309896 100644 --- a/tests/test_ht_spkitable_locks.c +++ b/tests/test_ht_spkitable_locks.c @@ -162,6 +162,5 @@ static void lock_test1() int main() { lock_test1(); - - + return EXIT_SUCCESS; } diff --git a/tests/test_live_validation.c b/tests/test_live_validation.c new file mode 100644 index 00000000..a4799de5 --- /dev/null +++ b/tests/test_live_validation.c @@ -0,0 +1,114 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ +*/ + +#include +#include +#include +#include +#include "rtrlib/rtrlib.h" + +#define RPKI_CACHE_HOST "rpki-validator.realmv6.org" +#define RPKI_CACHE_POST "8282" + +typedef struct { + char *pfx; + int len; + int asn; + int val; +} test_validity_t; + +/* + * Verification is based on ROAs for RIPE RIS Routing Beacons, see: + * https://www.ripe.net/analyse/internet-measurements/routing-information-service-ris/current-ris-routing-beacons + */ +const test_validity_t queries[] = { + {"93.175.146.0", 24, 12654, BGP_PFXV_STATE_VALID}, + {"2001:7fb:fd02::", 48, 12654, BGP_PFXV_STATE_VALID}, + {"93.175.147.0", 24, 12654, BGP_PFXV_STATE_INVALID}, + {"2001:7fb:fd03::", 48, 12654, BGP_PFXV_STATE_INVALID}, + {"84.205.83.0", 24, 12654, BGP_PFXV_STATE_NOT_FOUND}, + {"2001:7fb:ff03::", 48, 12654, BGP_PFXV_STATE_NOT_FOUND}, + {NULL, 0, 0, 0} +}; + +const int connection_timeout = 20; +enum rtr_mgr_status connectionStatus = -1; + +static void connectionStatusCallback(const struct rtr_mgr_group *group, + enum rtr_mgr_status status, + const struct rtr_socket *socket, + void *data) +{ + if(status == RTR_MGR_ERROR) + connectionStatus = status; +} + +int main() +{ + // create a TCP transport socket + struct tr_socket tr_tcp; + struct tr_tcp_config tcp_config = { RPKI_CACHE_HOST, RPKI_CACHE_POST, NULL }; + tr_tcp_init(&tcp_config, &tr_tcp); + + // create an rtr_socket and associate it with the transport socket + struct rtr_socket rtr_tcp; + rtr_tcp.tr_socket = &tr_tcp; + struct rtr_mgr_config *conf; + + // create a rtr_mgr_group array with 1 element + struct rtr_mgr_group groups[1]; + groups[0].sockets = malloc(1 * sizeof(struct rtr_socket*)); + groups[0].sockets_len = 1; + groups[0].sockets[0] = &rtr_tcp; + groups[0].preference = 1; + + if (rtr_mgr_init(&conf, groups, 1, 30, 600, 600, NULL, NULL, + &connectionStatusCallback, NULL) < 0) + return(EXIT_FAILURE); + + rtr_mgr_start(conf); + + int sleepCounter = 0; + while (!rtr_mgr_conf_in_sync(conf)) { + if(connectionStatus == RTR_MGR_ERROR) + return(EXIT_FAILURE); + + sleep(1); + sleepCounter++; + if (sleepCounter >= connection_timeout) + return(EXIT_FAILURE); + } + + int i = 0; + test_validity_t q = queries[i]; + while (q.pfx) { + struct lrtr_ip_addr pref; + lrtr_ip_str_to_addr(q.pfx, &pref); + enum pfxv_state result; + struct pfx_record* reason = NULL; + unsigned int reason_len = 0; + + // do validation + pfx_table_validate_r(groups[0].sockets[0]->pfx_table, &reason, + &reason_len, q.asn, &pref, q.len, &result); + if (result != q.val) { + printf("ERROR: prefix validation mismatch.\n"); + return(EXIT_FAILURE); + } else { + printf("%s/%d \tOK\n", q.pfx, q.len); + } + q = queries[++i]; + } + + rtr_mgr_stop(conf); + rtr_mgr_free(conf); + free(groups[0].sockets); + + return EXIT_SUCCESS; +} diff --git a/tests/test_lpfst.c b/tests/test_lpfst.c index a906b774..f93c0989 100644 --- a/tests/test_lpfst.c +++ b/tests/test_lpfst.c @@ -318,4 +318,5 @@ int main() get_bits_testv6(); lpfst_test(); printf("Test successfull\n"); + return EXIT_SUCCESS; } diff --git a/tests/test_pfx.c b/tests/test_pfx.c index 57d1da64..623d1742 100644 --- a/tests/test_pfx.c +++ b/tests/test_pfx.c @@ -348,5 +348,6 @@ int main() pfx_table_free(&pfxt); remove_src_test(); mass_test(); -} + return EXIT_SUCCESS; +} diff --git a/tests/test_pfx_locks.c b/tests/test_pfx_locks.c index 513a4143..66710a0f 100644 --- a/tests/test_pfx_locks.c +++ b/tests/test_pfx_locks.c @@ -165,4 +165,6 @@ int main() pthread_join(threads[i], NULL); printf("Thread %i returned\n", i); } + + return EXIT_SUCCESS; } diff --git a/tools/cli-validator.c b/tools/cli-validator.c index aedb9aac..62f00702 100644 --- a/tools/cli-validator.c +++ b/tools/cli-validator.c @@ -64,7 +64,6 @@ int main(int argc, char *argv[]) rtr_mgr_start(conf); char input[256]; - int inputLength; int sleepCounter = 0; // wait till at least one rtr_mgr_group is fully synchronized with server @@ -89,9 +88,11 @@ int main(int argc, char *argv[]) int mask; int asn; int counter; - int spaces; // loop for input while (1) { + int inputLength; + int spaces; + // recheck connection, exit on failure if(connectionError(connectionStatus)) return(EXIT_FAILURE);