From bc33a1e08d2f7913b61f22e31777c514b1e9f6aa Mon Sep 17 00:00:00 2001 From: Alberto Leiva Popper Date: Tue, 11 Dec 2018 11:18:31 -0600 Subject: [PATCH] Refactor: Send the validation state to thread local Unclutters lots of argument lists. Also delete the prefix*_contains functions. Weren't being used. --- src/Makefile.am | 2 +- src/address.c | 48 ----- src/address.h | 3 - src/asn1/signed_data.c | 22 +-- src/asn1/signed_data.h | 4 +- src/common.c | 1 + src/filename_stack.h | 11 -- src/log.c | 53 +++-- src/log.h | 4 +- src/main.c | 6 +- src/object/certificate.c | 59 +++--- src/object/certificate.h | 9 +- src/object/crl.c | 12 +- src/object/crl.h | 3 +- src/object/manifest.c | 47 +++-- src/object/manifest.h | 4 +- src/object/roa.c | 9 +- src/object/roa.h | 4 +- src/object/signed_object.c | 5 +- src/object/signed_object.h | 6 +- src/resource.c | 94 ++++++--- src/resource.h | 6 +- src/sorted_array.c | 1 + src/state.c | 79 ++++---- src/state.h | 5 +- src/{filename_stack.c => thread_var.c} | 45 ++++- src/thread_var.h | 16 ++ test/Makefile.am | 5 +- test/address_test.c | 264 ------------------------- 29 files changed, 292 insertions(+), 535 deletions(-) delete mode 100644 src/filename_stack.h rename src/{filename_stack.c => thread_var.c} (70%) create mode 100644 src/thread_var.h delete mode 100644 test/address_test.c diff --git a/src/Makefile.am b/src/Makefile.am index d2f52578..23378d80 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,12 +10,12 @@ rpki_validator_SOURCES += address.h address.c rpki_validator_SOURCES += common.h common.c rpki_validator_SOURCES += debug.h debug.c rpki_validator_SOURCES += file.h file.c -rpki_validator_SOURCES += filename_stack.h filename_stack.c rpki_validator_SOURCES += line_file.h line_file.c rpki_validator_SOURCES += log.h log.c rpki_validator_SOURCES += resource.h resource.c rpki_validator_SOURCES += sorted_array.h sorted_array.c rpki_validator_SOURCES += state.h state.c +rpki_validator_SOURCES += thread_var.h thread_var.c rpki_validator_SOURCES += asn1/content_info.h asn1/content_info.c rpki_validator_SOURCES += asn1/decode.h asn1/decode.c diff --git a/src/address.c b/src/address.c index e4987499..3c276eb9 100644 --- a/src/address.c +++ b/src/address.c @@ -149,51 +149,3 @@ range6_decode(IPAddressRange_t *input, struct ipv6_range *result) return 0; } - -bool -prefix4_contains(const struct ipv4_prefix *a, const struct ipv4_prefix *b) -{ - uint32_t maskbits; - uint32_t a_bits; - uint32_t b_bits; - - if (a->len > b->len) - return false; - - maskbits = ((uint64_t) 0xffffffffU) << (32 - a->len); - a_bits = ntohl(a->addr.s_addr) & maskbits; - b_bits = ntohl(b->addr.s_addr) & maskbits; - - return a_bits == b_bits; -} - -bool -prefix6_contains(const struct ipv6_prefix *a, const struct ipv6_prefix *b) -{ - struct in6_addr a2; - struct in6_addr b2; - unsigned int quadrant; - uint32_t mask; - unsigned int i; - - if (a->len > b->len) - return false; - - memcpy(&a2, &a->addr, sizeof(a2)); - memcpy(&b2, &b->addr, sizeof(b2)); - - /* Zeroize the suffixes of a2 and b2 */ - quadrant = a->len >> 5; /* ">> 5" is the same as "/ 32" */ - if (quadrant > 3) - quadrant = 3; - mask = ((uint64_t) 0xffffffffU) << (32 - (a->len & 0x1f)); - a2.s6_addr32[quadrant] = htonl(ntohl(a2.s6_addr32[quadrant]) & mask); - b2.s6_addr32[quadrant] = htonl(ntohl(b2.s6_addr32[quadrant]) & mask); - for (i = quadrant + 1; i < 4; i++) { - a2.s6_addr32[i] = 0; - b2.s6_addr32[i] = 0; - } - - /* Finally compare */ - return memcmp(&a2, &b2, sizeof(a2)) == 0; -} diff --git a/src/address.h b/src/address.h index 32357bad..b117daaf 100644 --- a/src/address.h +++ b/src/address.h @@ -34,7 +34,4 @@ int prefix6_decode(IPAddress2_t *, struct ipv6_prefix *); int range4_decode(IPAddressRange_t *, struct ipv4_range *); int range6_decode(IPAddressRange_t *, struct ipv6_range *); -bool prefix4_contains(const struct ipv4_prefix *, const struct ipv4_prefix *); -bool prefix6_contains(const struct ipv6_prefix *, const struct ipv6_prefix *); - #endif /* SRC_ADDRESS_H_ */ diff --git a/src/asn1/signed_data.c b/src/asn1/signed_data.c index 8ae8d683..ab549759 100644 --- a/src/asn1/signed_data.c +++ b/src/asn1/signed_data.c @@ -42,8 +42,7 @@ is_digest_algorithm(AlgorithmIdentifier_t *aid, bool *result) } static int -handle_sdata_certificate(struct validation *state, ANY_t *any, - struct resources *res) +handle_sdata_certificate(ANY_t *any, struct resources *res) { const unsigned char *tmp; X509 *cert; @@ -62,16 +61,16 @@ handle_sdata_certificate(struct validation *state, ANY_t *any, cert = d2i_X509(NULL, &tmp, any->size); if (cert == NULL) { - error = crypto_err(state, "Signed object's 'certificate' element does not decode into a Certificate"); + error = crypto_err("Signed object's 'certificate' element does not decode into a Certificate"); goto end1; } - error = certificate_validate(state, cert, NULL); /* TODO crls */ + error = certificate_validate(cert, NULL); /* TODO crls */ if (error) goto end2; if (res != NULL) { - error = certificate_get_resources(state, cert, res); + error = certificate_get_resources(cert, res); if (error) goto end2; } @@ -227,8 +226,7 @@ illegal_attrType: } static int -validate(struct validation *state, struct SignedData *sdata, - struct resources *res) +validate(struct SignedData *sdata, struct resources *res) { struct SignerInfo *sinfo; bool is_digest; @@ -289,8 +287,8 @@ validate(struct validation *state, struct SignedData *sdata, return -EINVAL; } - error = handle_sdata_certificate(state, - sdata->certificates->list.array[0], res); + error = handle_sdata_certificate(sdata->certificates->list.array[0], + res); if (error) return error; @@ -372,8 +370,8 @@ validate(struct validation *state, struct SignedData *sdata, } int -signed_data_decode(struct validation *state, ANY_t *coded, - struct SignedData **result, struct resources *res) +signed_data_decode(ANY_t *coded, struct SignedData **result, + struct resources *res) { struct SignedData *sdata; int error; @@ -383,7 +381,7 @@ signed_data_decode(struct validation *state, ANY_t *coded, if (error) return error; - error = validate(state, sdata, res); + error = validate(sdata, res); if (error) { signed_data_free(sdata); return error; diff --git a/src/asn1/signed_data.h b/src/asn1/signed_data.h index 3d722cb0..49d10b67 100644 --- a/src/asn1/signed_data.h +++ b/src/asn1/signed_data.h @@ -5,10 +5,8 @@ #include #include "resource.h" -#include "state.h" -int signed_data_decode(struct validation *, ANY_t *, struct SignedData **, - struct resources *); +int signed_data_decode(ANY_t *, struct SignedData **, struct resources *); void signed_data_free(struct SignedData *); int get_content_type_attr(struct SignedData *, OBJECT_IDENTIFIER_t **); diff --git a/src/common.c b/src/common.c index 4aaf4b45..1a87f54d 100644 --- a/src/common.c +++ b/src/common.c @@ -1,6 +1,7 @@ #include "common.h" #include +#include #include "log.h" char const *repository; diff --git a/src/filename_stack.h b/src/filename_stack.h deleted file mode 100644 index 8c93ab84..00000000 --- a/src/filename_stack.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SRC_FILENAME_STACK_H_ -#define SRC_FILENAME_STACK_H_ - -void fnstack_init(void); -void fnstack_store(void); - -void fnstack_push(char const *); -char const *fnstack_peek(void); -void fnstack_pop(void); - -#endif /* SRC_FILENAME_STACK_H_ */ diff --git a/src/log.c b/src/log.c index 1aa2d9bf..99976270 100644 --- a/src/log.c +++ b/src/log.c @@ -3,7 +3,7 @@ #include #include -#include "filename_stack.h" +#include "thread_var.h" #define STDOUT stdout #define STDERR stderr @@ -113,6 +113,16 @@ pr_err_prefix(void) pr_indent(STDERR); } +#define PR_ERR(args) do { \ + pr_err_prefix(); \ + pr_file_name(STDERR); \ + \ + va_start(args, format); \ + vfprintf(STDERR, format, args); \ + va_end(args); \ + fprintf(STDERR, "\n"); \ +} while (0) + /** * Always appends a newline at the end. */ @@ -120,14 +130,7 @@ void pr_err(const char *format, ...) { va_list args; - - pr_err_prefix(); - pr_file_name(STDERR); - - va_start(args, format); - vfprintf(STDERR, format, args); - va_end(args); - fprintf(STDERR, "\n"); + PR_ERR(args); } /** @@ -182,20 +185,32 @@ pr_errno(int error, const char *format, ...) * Always appends a newline at the end. */ int -crypto_err(struct validation *state, const char *format, ...) +crypto_err(const char *format, ...) { + struct validation *state; BIO *bio; + bool bio_needs_free; char const *file; va_list args; int error; - bio = validation_stderr(state); + error = ERR_GET_REASON(ERR_peek_last_error()); + bio = NULL; + bio_needs_free = false; + + state = state_retrieve(); + if (state != NULL) + bio = validation_stderr(state); + if (bio == NULL) { + bio = BIO_new_fp(stderr, BIO_NOCLOSE); + if (bio == NULL) + goto trainwreck; + bio_needs_free = true; + } file = fnstack_peek(); BIO_printf(bio, "%s: ", (file != NULL) ? file : "(Unknown file)"); - error = ERR_GET_REASON(ERR_peek_last_error()); - va_start(args, format); BIO_vprintf(bio, format, args); va_end(args); @@ -214,5 +229,17 @@ crypto_err(struct validation *state, const char *format, ...) } BIO_printf(bio, "\n"); + if (bio_needs_free) + BIO_free_all(bio); return error; + +trainwreck: + /* Fall back to behave just like pr_err(). */ + PR_ERR(args); + + pr_err_prefix(); + pr_file_name(STDERR); + fprintf(STDERR, "(Cannot print libcrypto error: Failed to initialise standard error's BIO.)\n"); + + return error ? error : -EINVAL; } diff --git a/src/log.h b/src/log.h index 7d6af24b..2be6ad87 100644 --- a/src/log.h +++ b/src/log.h @@ -1,15 +1,13 @@ #ifndef SRC_LOG_H_ #define SRC_LOG_H_ -#include "state.h" - void pr_debug(const char *, ...); void pr_debug_add(const char *, ...); void pr_debug_rm(const char *, ...); void pr_err(const char *, ...); int pr_errno(int, const char *, ...); -int crypto_err(struct validation *, const char *, ...); +int crypto_err(const char *, ...); #define PR_DEBUG printf("%s:%d (%s())\n", __FILE__, __LINE__, __func__) #define PR_DEBUG_MSG(msg, ...) printf("%s:%d (%s()): " msg "\n", \ diff --git a/src/main.c b/src/main.c index 57025329..f3442b56 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ #include "common.h" #include "debug.h" #include "log.h" -#include "filename_stack.h" +#include "thread_var.h" #include "object/certificate.h" #include "object/tal.h" @@ -56,7 +56,7 @@ handle_tal_uri(char const *uri) } fnstack_push(uri); - error = certificate_traverse(state, validation_peek_cert(state)); + error = certificate_traverse(validation_peek_cert(state)); fnstack_pop(); end2: @@ -81,7 +81,7 @@ main(int argc, char **argv) } add_rpki_oids(); - fnstack_init(); + thvar_init(); fnstack_store(); fnstack_push(argv[2]); diff --git a/src/object/certificate.c b/src/object/certificate.c index a10de9f1..ed997f8a 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -7,6 +7,7 @@ #include "common.h" #include "log.h" #include "manifest.h" +#include "thread_var.h" #include "asn1/decode.h" /* @@ -54,7 +55,7 @@ validate_name(X509_NAME *name, char *what) } static int -validate_public_key(struct validation *state, X509 *cert) +validate_public_key(X509 *cert) { X509_PUBKEY *pubkey; ASN1_OBJECT *algorithm; @@ -63,13 +64,13 @@ validate_public_key(struct validation *state, X509 *cert) pubkey = X509_get_X509_PUBKEY(cert); if (pubkey == NULL) { - crypto_err(state, "X509_get_X509_PUBKEY() returned NULL."); + crypto_err("X509_get_X509_PUBKEY() returned NULL."); return -EINVAL; } ok = X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, pubkey); if (!ok) { - crypto_err(state, "X509_PUBKEY_get0_param() returned %d.", ok); + crypto_err("X509_PUBKEY_get0_param() returned %d.", ok); return -EINVAL; } @@ -107,7 +108,7 @@ validate_extensions(X509 *cert) } static int -rfc6487_validate(struct validation *state, X509 *cert) +rfc6487_validate(X509 *cert) { int error; @@ -158,7 +159,7 @@ rfc6487_validate(struct validation *state, X509 *cert) /* libcrypto already does this. */ /* rfc6487#section-4.7 */ - error = validate_public_key(state, cert); + error = validate_public_key(cert); if (error) return error; @@ -166,7 +167,7 @@ rfc6487_validate(struct validation *state, X509 *cert) } int -certificate_load(struct validation *state, const char *file, X509 **result) +certificate_load(const char *file, X509 **result) { X509 *cert = NULL; BIO *bio; @@ -174,19 +175,19 @@ certificate_load(struct validation *state, const char *file, X509 **result) bio = BIO_new(BIO_s_file()); if (bio == NULL) - return crypto_err(state, "BIO_new(BIO_s_file()) returned NULL"); + return crypto_err("BIO_new(BIO_s_file()) returned NULL"); if (BIO_read_filename(bio, file) <= 0) { - error = crypto_err(state, "Error reading certificate"); + error = crypto_err("Error reading certificate"); goto abort1; } cert = d2i_X509_bio(bio, NULL); if (cert == NULL) { - error = crypto_err(state, "Error parsing certificate"); + error = crypto_err("Error parsing certificate"); goto abort1; } - error = rfc6487_validate(state, cert); + error = rfc6487_validate(cert); if (error) goto abort2; @@ -202,8 +203,7 @@ abort1: } int -certificate_validate(struct validation *state, X509 *cert, - STACK_OF(X509_CRL) *crls) +certificate_validate(X509 *cert, STACK_OF(X509_CRL) *crls) { /* * TODO @@ -214,20 +214,25 @@ certificate_validate(struct validation *state, X509 *cert, * So, just in case, enable -no-CAfile and -no-CApath. */ + struct validation *state; X509_STORE_CTX *ctx; int ok; int error; + state = state_retrieve(); + if (state == NULL) + return -EINVAL; + ctx = X509_STORE_CTX_new(); if (ctx == NULL) { - crypto_err(state, "X509_STORE_CTX_new() returned NULL"); + crypto_err("X509_STORE_CTX_new() returned NULL"); return -EINVAL; } /* Returns 0 or 1 , all callers test ! only. */ ok = X509_STORE_CTX_init(ctx, validation_store(state), cert, NULL); if (!ok) { - crypto_err(state, "X509_STORE_CTX_init() returned %d", ok); + crypto_err("X509_STORE_CTX_init() returned %d", ok); goto abort; } @@ -259,8 +264,7 @@ certificate_validate(struct validation *state, X509 *cert, * That said, there's not much to do about !error, * so hope for the best. */ - crypto_err(state, "Certificate validation failed: %d", - ok); + crypto_err("Certificate validation failed: %d", ok); } goto abort; @@ -292,8 +296,7 @@ gn_g2l(GENERAL_NAME *name, char **luri) } static int -handle_ip_extension(struct validation *state, X509_EXTENSION *ext, - struct resources *resources) +handle_ip_extension(X509_EXTENSION *ext, struct resources *resources) { ASN1_OCTET_STRING *string; struct IPAddrBlocks *blocks; @@ -311,8 +314,7 @@ handle_ip_extension(struct validation *state, X509_EXTENSION *ext, * Each SEQUENCE MUST be ordered by ascending addressFamily values. */ for (i = 0; i < blocks->list.count; i++) { - error = resources_add_ip(resources, blocks->list.array[i], - validation_peek_resource(state)); + error = resources_add_ip(resources, blocks->list.array[i]); if (error) break; } @@ -322,8 +324,7 @@ handle_ip_extension(struct validation *state, X509_EXTENSION *ext, } static int -handle_asn_extension(struct validation *state, X509_EXTENSION *ext, - struct resources *resources) +handle_asn_extension(X509_EXTENSION *ext, struct resources *resources) { ASN1_OCTET_STRING *string; struct ASIdentifiers *ids; @@ -335,16 +336,14 @@ handle_asn_extension(struct validation *state, X509_EXTENSION *ext, if (error) return error; - error = resources_add_asn(resources, ids, - validation_peek_resource(state)); + error = resources_add_asn(resources, ids); ASN_STRUCT_FREE(asn_DEF_ASIdentifiers, ids); return error; } int -certificate_get_resources(struct validation *state, X509 *cert, - struct resources *resources) +certificate_get_resources(X509 *cert, struct resources *resources) { X509_EXTENSION *ext; int i; @@ -365,12 +364,12 @@ certificate_get_resources(struct validation *state, X509 *cert, switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext))) { case NID_sbgp_ipAddrBlock: pr_debug_add("IP {"); - error = handle_ip_extension(state, ext, resources); + error = handle_ip_extension(ext, resources); pr_debug_rm("}"); break; case NID_sbgp_autonomousSysNum: pr_debug_add("ASN {"); - error = handle_asn_extension(state, ext, resources); + error = handle_asn_extension(ext, resources); pr_debug_rm("}"); break; } @@ -382,7 +381,7 @@ certificate_get_resources(struct validation *state, X509 *cert, return error; } -int certificate_traverse(struct validation *state, X509 *cert) +int certificate_traverse(X509 *cert) { SIGNATURE_INFO_ACCESS *sia; ACCESS_DESCRIPTION *ad; @@ -404,7 +403,7 @@ int certificate_traverse(struct validation *state, X509 *cert) error = gn_g2l(ad->location, &uri); if (error) goto end; - error = handle_manifest(state, uri); + error = handle_manifest(uri); free(uri); if (error) goto end; diff --git a/src/object/certificate.h b/src/object/certificate.h index f8bc3fbc..28e822fe 100644 --- a/src/object/certificate.h +++ b/src/object/certificate.h @@ -4,10 +4,9 @@ #include #include #include "resource.h" -#include "state.h" bool is_certificate(char const *); -int certificate_load(struct validation *, const char *, X509 **); +int certificate_load(const char *, X509 **); /* * Note: You actually need all three of these functions for a full validation; @@ -16,8 +15,8 @@ int certificate_load(struct validation *, const char *, X509 **); * you will need certificate_traverse() to walk through the children. */ -int certificate_validate(struct validation *, X509 *, STACK_OF(X509_CRL) *); -int certificate_get_resources(struct validation *, X509 *, struct resources *); -int certificate_traverse(struct validation *, X509 *); +int certificate_validate(X509 *, STACK_OF(X509_CRL) *); +int certificate_get_resources(X509 *, struct resources *); +int certificate_traverse(X509 *); #endif /* SRC_OBJECT_CERTIFICATE_H_ */ diff --git a/src/object/crl.c b/src/object/crl.c index cb9fd464..88968aa6 100644 --- a/src/object/crl.c +++ b/src/object/crl.c @@ -3,7 +3,7 @@ #include "log.h" static int -__crl_load(struct validation *state, const char *file, X509_CRL **result) +__crl_load(const char *file, X509_CRL **result) { X509_CRL *crl = NULL; BIO *bio; @@ -11,15 +11,15 @@ __crl_load(struct validation *state, const char *file, X509_CRL **result) bio = BIO_new(BIO_s_file()); if (bio == NULL) - return crypto_err(state, "BIO_new(BIO_s_file()) returned NULL"); + return crypto_err("BIO_new(BIO_s_file()) returned NULL"); if (BIO_read_filename(bio, file) <= 0) { - error = crypto_err(state, "Error reading CRL '%s'", file); + error = crypto_err("Error reading CRL '%s'", file); goto end; } crl = d2i_X509_CRL_bio(bio, NULL); if (crl == NULL) { - error = crypto_err(state, "Error parsing CRL '%s'", file); + error = crypto_err("Error parsing CRL '%s'", file); goto end; } @@ -32,12 +32,12 @@ end: } int -crl_load(struct validation *state, char const *file, X509_CRL **result) +crl_load(char const *file, X509_CRL **result) { int error; pr_debug_add("CRL {"); - error = __crl_load(state, file, result); + error = __crl_load(file, result); pr_debug_rm("}"); return error; diff --git a/src/object/crl.h b/src/object/crl.h index b288dd9e..aecffed4 100644 --- a/src/object/crl.h +++ b/src/object/crl.h @@ -2,8 +2,7 @@ #define SRC_OBJECT_CRL_H_ #include -#include "state.h" -int crl_load(struct validation *, char const *, X509_CRL **); +int crl_load(char const *, X509_CRL **); #endif /* SRC_OBJECT_CRL_H_ */ diff --git a/src/object/manifest.c b/src/object/manifest.c index 8f7e5040..0f103974 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -4,9 +4,9 @@ #include #include -#include "filename_stack.h" #include "log.h" #include "asn1/oid.h" +#include "thread_var.h" #include "object/certificate.h" #include "object/crl.h" #include "object/roa.h" @@ -154,7 +154,7 @@ succeed: return 0; } -typedef int (*foreach_cb)(struct validation *, char *, void *); +typedef int (*foreach_cb)(char *, void *); struct foreach_args { STACK_OF(X509_CRL) *crls; @@ -162,8 +162,7 @@ struct foreach_args { }; static int -foreach_file(struct validation *state, struct manifest *mft, char *extension, - foreach_cb cb, void *arg) +foreach_file(struct manifest *mft, char *extension, foreach_cb cb, void *arg) { char *uri; char *luri; /* "Local URI". As in "URI that we can easily reference." */ @@ -178,7 +177,7 @@ foreach_file(struct validation *state, struct manifest *mft, char *extension, error = get_relative_file(mft->file_path, uri, &luri); if (error) return error; - error = cb(state, luri, arg); + error = cb(luri, arg); free(luri); if (error) return error; @@ -189,7 +188,7 @@ foreach_file(struct validation *state, struct manifest *mft, char *extension, } static int -pile_crls(struct validation *state, char *file, void *crls) +pile_crls(char *file, void *crls) { X509_CRL *crl; int error; @@ -197,13 +196,13 @@ pile_crls(struct validation *state, char *file, void *crls) fnstack_push(file); - error = crl_load(state, file, &crl); + error = crl_load(file, &crl); if (error) goto end; idx = sk_X509_CRL_push(crls, crl); if (idx <= 0) { - error = crypto_err(state, "Could not add CRL to a CRL stack"); + error = crypto_err("Could not add CRL to a CRL stack"); X509_CRL_free(crl); goto end; } @@ -214,7 +213,7 @@ end: } static int -pile_addr_ranges(struct validation *state, char *file, void *__args) +pile_addr_ranges(char *file, void *__args) { struct foreach_args *args = __args; struct resources *resources; @@ -230,10 +229,10 @@ pile_addr_ranges(struct validation *state, char *file, void *__args) * (Error messages should have been printed in stderr.) */ - if (certificate_load(state, file, &cert)) + if (certificate_load(file, &cert)) goto end; /* Fine */ - if (certificate_validate(state, cert, args->crls)) + if (certificate_validate(cert, args->crls)) goto revert; /* Fine */ resources = resources_create(); @@ -242,10 +241,10 @@ pile_addr_ranges(struct validation *state, char *file, void *__args) goto revert; } - if (certificate_get_resources(state, cert, resources)) + if (certificate_get_resources(cert, resources)) goto revert2; /* Fine */ - if (validation_push_cert(state, cert, resources)) { + if (validation_push_cert(cert, resources)) { /* * Validation_push_cert() only fails on OPENSSL_sk_push(). * The latter really only fails on memory allocation fault. @@ -254,8 +253,8 @@ pile_addr_ranges(struct validation *state, char *file, void *__args) error = -EINVAL; /* Not fine */ goto revert2; } - certificate_traverse(state, cert); /* Error code is useless. */ - validation_pop_cert(state); /* Error code is useless. */ + certificate_traverse(cert); /* Error code is useless. */ + validation_pop_cert(); /* Error code is useless. */ error = resources_join(args->resources, resources); /* Not fine */ @@ -270,18 +269,18 @@ end: } static int -print_roa(struct validation *state, char *file, void *arg) +print_roa(char *file, void *arg) { /* * TODO to validate the ROA's cert, the parent cert must not have been * popped at this point. */ - handle_roa(state, file); + handle_roa(file); return 0; } static int -__handle_manifest(struct validation *state, struct manifest *mft) +__handle_manifest(struct manifest *mft) { struct foreach_args args; int error; @@ -300,7 +299,7 @@ __handle_manifest(struct validation *state, struct manifest *mft) } /* Get CRLs as a stack. There will usually only be one. */ - error = foreach_file(state, mft, "crl", pile_crls, args.crls); + error = foreach_file(mft, "crl", pile_crls, args.crls); if (error) goto end; @@ -308,12 +307,12 @@ __handle_manifest(struct validation *state, struct manifest *mft) * Use CRL stack to validate certificates. * Pile up valid address ranges from the valid certificates. */ - error = foreach_file(state, mft, "cer", pile_addr_ranges, &args); + error = foreach_file(mft, "cer", pile_addr_ranges, &args); if (error) goto end; /* Use valid address ranges to print ROAs that match them. */ - error = foreach_file(state, mft, "roa", print_roa, &args); + error = foreach_file(mft, "roa", print_roa, &args); end: resources_destroy(args.resources); @@ -322,7 +321,7 @@ end: } int -handle_manifest(struct validation *state, char const *file_path) +handle_manifest(char const *file_path) { static OID oid = OID_MANIFEST; struct oid_arcs arcs = OID2ARCS(oid); @@ -338,14 +337,14 @@ handle_manifest(struct validation *state, char const *file_path) * TODO about those NULL resources: Maybe print a warning if the * certificate contains some. */ - error = signed_object_decode(state, file_path, &asn_DEF_Manifest, &arcs, + error = signed_object_decode(file_path, &asn_DEF_Manifest, &arcs, (void **) &mft.obj, NULL); if (error) goto end; error = validate_manifest(mft.obj); if (!error) - error = __handle_manifest(state, &mft); + error = __handle_manifest(&mft); ASN_STRUCT_FREE(asn_DEF_Manifest, mft.obj); end: diff --git a/src/object/manifest.h b/src/object/manifest.h index 573bcb6f..ab2bd7f1 100644 --- a/src/object/manifest.h +++ b/src/object/manifest.h @@ -1,8 +1,6 @@ #ifndef SRC_OBJECT_MANIFEST_H_ #define SRC_OBJECT_MANIFEST_H_ -#include "state.h" - -int handle_manifest(struct validation *, char const *); +int handle_manifest(char const *); #endif /* SRC_OBJECT_MANIFEST_H_ */ diff --git a/src/object/roa.c b/src/object/roa.c index 6018ac7e..01193970 100644 --- a/src/object/roa.c +++ b/src/object/roa.c @@ -4,8 +4,8 @@ #include #include -#include "filename_stack.h" #include "log.h" +#include "thread_var.h" #include "asn1/oid.h" #include "object/signed_object.h" @@ -151,7 +151,7 @@ family_error: return -EINVAL; } -int handle_roa(struct validation *state, char const *file) +int handle_roa(char const *file) { static OID oid = OID_ROA; struct oid_arcs arcs = OID2ARCS(oid); @@ -170,9 +170,8 @@ int handle_roa(struct validation *state, char const *file) goto end1; } - error = signed_object_decode(state, file, - &asn_DEF_RouteOriginAttestation, &arcs, (void **) &roa, - cert_resources); + error = signed_object_decode(file, &asn_DEF_RouteOriginAttestation, + &arcs, (void **) &roa, cert_resources); if (error) goto end2; error = __handle_roa(roa, cert_resources); diff --git a/src/object/roa.h b/src/object/roa.h index 2d86e657..ff134268 100644 --- a/src/object/roa.h +++ b/src/object/roa.h @@ -1,8 +1,6 @@ #ifndef SRC_OBJECT_ROA_H_ #define SRC_OBJECT_ROA_H_ -#include "state.h" - -int handle_roa(struct validation *, char const *); +int handle_roa(char const *); #endif /* SRC_OBJECT_ROA_H_ */ diff --git a/src/object/signed_object.c b/src/object/signed_object.c index 31af6281..0cc7acee 100644 --- a/src/object/signed_object.c +++ b/src/object/signed_object.c @@ -58,8 +58,7 @@ validate_content_type(struct SignedData *sdata, } int -signed_object_decode(struct validation *state, - char const *file, +signed_object_decode(char const *file, asn_TYPE_descriptor_t const *descriptor, struct oid_arcs const *oid, void **result, @@ -73,7 +72,7 @@ signed_object_decode(struct validation *state, if (error) goto end1; - error = signed_data_decode(state, &cinfo->content, &sdata, res); + error = signed_data_decode(&cinfo->content, &sdata, res); if (error) goto end2; diff --git a/src/object/signed_object.h b/src/object/signed_object.h index a5009577..9565d513 100644 --- a/src/object/signed_object.h +++ b/src/object/signed_object.h @@ -3,10 +3,8 @@ #include "asn1/oid.h" #include "resource.h" -#include "state.h" -int signed_object_decode(struct validation *, char const *, - asn_TYPE_descriptor_t const *, struct oid_arcs const *, void **, - struct resources *); +int signed_object_decode(char const *, asn_TYPE_descriptor_t const *, + struct oid_arcs const *, void **, struct resources *); #endif /* SRC_OBJECT_SIGNED_OBJECT_H_ */ diff --git a/src/resource.c b/src/resource.c index 59a94f4f..29885faa 100644 --- a/src/resource.c +++ b/src/resource.c @@ -7,6 +7,7 @@ #include "address.h" #include "log.h" #include "sorted_array.h" +#include "thread_var.h" #include "resource/ip4.h" #include "resource/ip6.h" #include "resource/asn.h" @@ -83,6 +84,13 @@ unknown: return -1; } +static struct resources * +get_parent_resources(void) +{ + struct validation *state = state_retrieve(); + return (state != NULL) ? validation_peek_resource(state) : NULL; +} + static void pr_debug_prefix(int family, void *addr, unsigned int length) { @@ -126,8 +134,16 @@ fail: } static int -inherit_aors(struct resources *resources, int family, struct resources *parent) +inherit_aors(struct resources *resources, int family) { + struct resources *parent; + + parent = get_parent_resources(); + if (!parent) { + pr_err("Certificate inherits IP resources, but parent does not define any resources."); + return -EINVAL; + } + switch (family) { case AF_INET: if (resources->ip4s != NULL) { @@ -161,12 +177,14 @@ inherit_aors(struct resources *resources, int family, struct resources *parent) } static int -add_prefix4(struct resources *resources, IPAddress2_t *addr, - struct resources *parent) +add_prefix4(struct resources *resources, IPAddress2_t *addr) { + struct resources *parent; struct ipv4_prefix prefix; int error; + parent = get_parent_resources(); + if ((parent != NULL) && (resources->ip4s == parent->ip4s)) { pr_err("Certificate defines IPv4 prefixes while also inheriting his parent's."); return -EINVAL; @@ -201,12 +219,14 @@ add_prefix4(struct resources *resources, IPAddress2_t *addr, } static int -add_prefix6(struct resources *resources, IPAddress2_t *addr, - struct resources *parent) +add_prefix6(struct resources *resources, IPAddress2_t *addr) { + struct resources *parent; struct ipv6_prefix prefix; int error; + parent = get_parent_resources(); + if ((parent != NULL) && (resources->ip6s == parent->ip6s)) { pr_err("Certificate defines IPv6 prefixes while also inheriting his parent's."); return -EINVAL; @@ -241,14 +261,13 @@ add_prefix6(struct resources *resources, IPAddress2_t *addr, } static int -add_prefix(struct resources *resources, int family, IPAddress2_t *addr, - struct resources *parent) +add_prefix(struct resources *resources, int family, IPAddress2_t *addr) { switch (family) { case AF_INET: - return add_prefix4(resources, addr, parent); + return add_prefix4(resources, addr); case AF_INET6: - return add_prefix6(resources, addr, parent); + return add_prefix6(resources, addr); } pr_err("Programming error: Unknown address family '%d'", family); @@ -256,12 +275,14 @@ add_prefix(struct resources *resources, int family, IPAddress2_t *addr, } static int -add_range4(struct resources *resources, IPAddressRange_t *input, - struct resources *parent) +add_range4(struct resources *resources, IPAddressRange_t *input) { + struct resources *parent; struct ipv4_range range; int error; + parent = get_parent_resources(); + if ((parent != NULL) && (resources->ip4s == parent->ip4s)) { pr_err("Certificate defines IPv4 ranges while also inheriting his parent's."); return -EINVAL; @@ -296,12 +317,14 @@ add_range4(struct resources *resources, IPAddressRange_t *input, } static int -add_range6(struct resources *resources, IPAddressRange_t *input, - struct resources *parent) +add_range6(struct resources *resources, IPAddressRange_t *input) { + struct resources *parent; struct ipv6_range range; int error; + parent = get_parent_resources(); + if ((parent != NULL) && (resources->ip6s == parent->ip6s)) { pr_err("Certificate defines IPv6 ranges while also inheriting his parent's."); return -EINVAL; @@ -336,14 +359,13 @@ add_range6(struct resources *resources, IPAddressRange_t *input, } static int -add_range(struct resources *resources, int family, IPAddressRange_t *range, - struct resources *parent) +add_range(struct resources *resources, int family, IPAddressRange_t *range) { switch (family) { case AF_INET: - return add_range4(resources, range, parent); + return add_range4(resources, range); case AF_INET6: - return add_range6(resources, range, parent); + return add_range6(resources, range); } pr_err("Programming error: Unknown address family '%d'", family); @@ -352,7 +374,7 @@ add_range(struct resources *resources, int family, IPAddressRange_t *range, static int add_aors(struct resources *resources, int family, - struct IPAddressChoice__addressesOrRanges *aors, struct resources *parent) + struct IPAddressChoice__addressesOrRanges *aors) { struct IPAddressOrRange *aor; int i; @@ -363,13 +385,13 @@ add_aors(struct resources *resources, int family, switch (aor->present) { case IPAddressOrRange_PR_addressPrefix: error = add_prefix(resources, family, - &aor->choice.addressPrefix, parent); + &aor->choice.addressPrefix); if (error) return error; break; case IPAddressOrRange_PR_addressRange: error = add_range(resources, family, - &aor->choice.addressRange, parent); + &aor->choice.addressRange); if (error) return error; break; @@ -385,8 +407,7 @@ add_aors(struct resources *resources, int family, } int -resources_add_ip(struct resources *resources, struct IPAddressFamily *obj, - struct resources *parent) +resources_add_ip(struct resources *resources, struct IPAddressFamily *obj) { int family; @@ -398,10 +419,10 @@ resources_add_ip(struct resources *resources, struct IPAddressFamily *obj, case IPAddressChoice_PR_NOTHING: break; case IPAddressChoice_PR_inherit: - return inherit_aors(resources, family, parent); + return inherit_aors(resources, family); case IPAddressChoice_PR_addressesOrRanges: return add_aors(resources, family, - &obj->ipAddressChoice.choice.addressesOrRanges, parent); + &obj->ipAddressChoice.choice.addressesOrRanges); } /* rfc3779#section-2.2.3.4 */ @@ -411,8 +432,16 @@ resources_add_ip(struct resources *resources, struct IPAddressFamily *obj, } static int -inherit_asiors(struct resources *resources, struct resources *parent) +inherit_asiors(struct resources *resources) { + struct resources *parent; + + parent = get_parent_resources(); + if (!parent) { + pr_err("Certificate inherits ASN resources, but parent does not define any resources."); + return -EINVAL; + } + if (resources->asns != NULL) { pr_err("Certificate inherits ASN resources while also defining others of its own."); return -EINVAL; @@ -460,9 +489,12 @@ add_asn(struct resources *resources, ASId_t min, ASId_t max, } static int -add_asior(struct resources *resources, struct ASIdOrRange *obj, - struct resources *parent) +add_asior(struct resources *resources, struct ASIdOrRange *obj) { + struct resources *parent; + + parent = get_parent_resources(); + if ((parent != NULL) && (resources->asns == parent->asns)) { pr_err("Certificate defines ASN resources while also inheriting his parent's."); return -EINVAL; @@ -484,8 +516,7 @@ add_asior(struct resources *resources, struct ASIdOrRange *obj, } int -resources_add_asn(struct resources *resources, struct ASIdentifiers *ids, - struct resources *parent) +resources_add_asn(struct resources *resources, struct ASIdentifiers *ids) { struct ASIdentifierChoice__asIdsOrRanges *iors; int i; @@ -502,12 +533,11 @@ resources_add_asn(struct resources *resources, struct ASIdentifiers *ids, switch (ids->asnum->present) { case ASIdentifierChoice_PR_inherit: - return inherit_asiors(resources, parent); + return inherit_asiors(resources); case ASIdentifierChoice_PR_asIdsOrRanges: iors = &ids->asnum->choice.asIdsOrRanges; for (i = 0; i < iors->list.count; i++) { - error = add_asior(resources, iors->list.array[i], - parent); + error = add_asior(resources, iors->list.array[i]); if (error) return error; } diff --git a/src/resource.h b/src/resource.h index bde82eaf..678c3b43 100644 --- a/src/resource.h +++ b/src/resource.h @@ -11,10 +11,8 @@ struct resources; struct resources *resources_create(void); void resources_destroy(struct resources *); -int resources_add_ip(struct resources *, struct IPAddressFamily *, - struct resources *); -int resources_add_asn(struct resources *, struct ASIdentifiers *, - struct resources *); +int resources_add_ip(struct resources *, struct IPAddressFamily *); +int resources_add_asn(struct resources *, struct ASIdentifiers *); bool resources_contains_asn(struct resources *, ASId_t); bool resources_contains_ipv4(struct resources *, struct ipv4_prefix *); diff --git a/src/sorted_array.c b/src/sorted_array.c index 4d509821..cd378c29 100644 --- a/src/sorted_array.c +++ b/src/sorted_array.c @@ -2,6 +2,7 @@ #include #include +#include #include "log.h" struct sorted_array { diff --git a/src/state.c b/src/state.c index 19f6cb8f..5eab07b8 100644 --- a/src/state.c +++ b/src/state.c @@ -2,7 +2,7 @@ #include #include "log.h" -#include "filename_stack.h" +#include "thread_var.h" #include "object/certificate.h" /** @@ -13,11 +13,6 @@ * uses it to traverse the tree and keep track of validated data. */ struct validation { - /** - * Encapsulated standard output. - * Needed because the crypto library won't write to stdout directly. - */ - BIO *out; /** * Encapsulated standard error. * Needed because the crypto library won't write to stderr directly. @@ -90,7 +85,7 @@ init_trusted(struct validation *result, char *root) fnstack_push(root); - error = certificate_load(result, root, &cert); + error = certificate_load(root, &cert); if (error) goto abort1; @@ -102,7 +97,7 @@ init_trusted(struct validation *result, char *root) ok = sk_X509_push(result->trusted, cert); if (ok <= 0) { - error = crypto_err(result, + error = crypto_err( "Could not add certificate to trusted stack: %d", ok); goto abort3; } @@ -124,66 +119,64 @@ validation_create(struct validation **out, char *root) { struct validation *result; struct resources *resources; - int error = -ENOMEM; + int error; result = malloc(sizeof(struct validation)); if (!result) return -ENOMEM; - result->out = BIO_new_fp(stdout, BIO_NOCLOSE); - if (result->out == NULL) { - fprintf(stderr, "Failed to initialise standard output's BIO.\n"); + error = state_store(result); + if (error) goto abort1; - } + result->err = BIO_new_fp(stderr, BIO_NOCLOSE); - if (result->out == NULL) { + if (result->err == NULL) { fprintf(stderr, "Failed to initialise standard error's BIO.\n"); - goto abort2; + error = -ENOMEM; + goto abort1; } result->store = X509_STORE_new(); if (!result->store) { - error = crypto_err(result, "X509_STORE_new() returned NULL"); - goto abort3; + error = crypto_err("X509_STORE_new() returned NULL"); + goto abort2; } X509_STORE_set_verify_cb(result->store, cb); error = init_trusted(result, root); if (error) - goto abort4; + goto abort3; result->rsrcs = restack_create(); if (!result->rsrcs) - goto abort5; + goto abort4; resources = resources_create(); if (resources == NULL) - goto abort6; + goto abort5; fnstack_push(root); - error = certificate_get_resources(result, validation_peek_cert(result), + error = certificate_get_resources(validation_peek_cert(result), resources); fnstack_pop(); if (error) - goto abort7; + goto abort6; restack_push(result->rsrcs, resources); *out = result; return 0; -abort7: - resources_destroy(resources); abort6: - restack_destroy(result->rsrcs); + resources_destroy(resources); abort5: - sk_X509_pop_free(result->trusted, X509_free); + restack_destroy(result->rsrcs); abort4: - X509_STORE_free(result->store); + sk_X509_pop_free(result->trusted, X509_free); abort3: - BIO_free_all(result->err); + X509_STORE_free(result->store); abort2: - BIO_free_all(result->out); + BIO_free_all(result->err); abort1: free(result); return error; @@ -208,16 +201,9 @@ validation_destroy(struct validation *state) sk_X509_pop_free(state->trusted, X509_free); X509_STORE_free(state->store); BIO_free_all(state->err); - BIO_free_all(state->out); free(state); } -BIO * -validation_stdout(struct validation *state) -{ - return state->out; -} - BIO * validation_stderr(struct validation *state) { @@ -243,15 +229,18 @@ validation_resources(struct validation *state) } int -validation_push_cert(struct validation *state, X509 *cert, - struct resources *resources) +validation_push_cert(X509 *cert, struct resources *resources) { + struct validation *state; int ok; + state = state_retrieve(); + if (state == NULL) + return -EINVAL; + ok = sk_X509_push(state->trusted, cert); if (ok <= 0) { - crypto_err(state, - "Could not add certificate to trusted stack: %d", ok); + crypto_err("Couldn't add certificate to trusted stack: %d", ok); return -ENOMEM; /* Presumably */ } @@ -261,10 +250,16 @@ validation_push_cert(struct validation *state, X509 *cert, } int -validation_pop_cert(struct validation *state) +validation_pop_cert(void) { + struct validation *state; + + state = state_retrieve(); + if (state == NULL) + return -EINVAL; + if (sk_X509_pop(state->trusted) == NULL) { - return crypto_err(state, + return crypto_err( "Programming error: Attempted to pop empty cert stack"); } if (restack_pop(state->rsrcs) == NULL) { diff --git a/src/state.h b/src/state.h index 52a4c3d9..2c4f18fe 100644 --- a/src/state.h +++ b/src/state.h @@ -10,14 +10,13 @@ struct validation; int validation_create(struct validation **, char *); void validation_destroy(struct validation *); -BIO *validation_stdout(struct validation *); BIO *validation_stderr(struct validation *); X509_STORE *validation_store(struct validation *); STACK_OF(X509) *validation_certs(struct validation *); struct restack *validation_resources(struct validation *); -int validation_push_cert(struct validation *, X509 *, struct resources *); -int validation_pop_cert(struct validation *); +int validation_push_cert(X509 *, struct resources *); +int validation_pop_cert(void); X509 *validation_peek_cert(struct validation *); struct resources *validation_peek_resource(struct validation *); diff --git a/src/filename_stack.c b/src/thread_var.c similarity index 70% rename from src/filename_stack.c rename to src/thread_var.c index 74308f5a..068dcacf 100644 --- a/src/filename_stack.c +++ b/src/thread_var.c @@ -1,4 +1,4 @@ -#include "filename_stack.h" +#include "thread_var.h" #include #include @@ -6,6 +6,7 @@ #include #include +static pthread_key_t state_key; static pthread_key_t filenames_key; struct filename_stack { @@ -23,21 +24,55 @@ fnstack_discard(void *arg) free(files); } -/** Initializes this module. Call once per runtime lifetime. */ +/** Initializes this entire module. Call once per runtime lifetime. */ void -fnstack_init(void) +thvar_init(void) { int error; + error = pthread_key_create(&state_key, NULL); + if (error) { + fprintf(stderr, + "Fatal: Errcode %d while initializing the validation state thread variable.\n", + error); + exit(error); + } + error = pthread_key_create(&filenames_key, fnstack_discard); if (error) { fprintf(stderr, - "Fatal: Errcode %d while attempting to initialize thread variable.\n", + "Fatal: Errcode %d while initializing the file name stack thread variable.\n", error); exit(error); } } +/* Puts @state in the current thread's variable pool. Call once per thread. */ +int +state_store(struct validation *state) +{ + int error; + + error = pthread_setspecific(state_key, state); + if (error) + fprintf(stderr, "pthread_setspecific() returned %d.", error); + + return error; +} + +/* Returns the current thread's validation state. */ +struct validation * +state_retrieve(void) +{ + struct validation *state; + + state = pthread_getspecific(state_key); + if (state == NULL) + fprintf(stderr, "This thread lacks a validation state.\n"); + + return state; +} + /** Initializes the current thread's fnstack. Call once per thread. */ void fnstack_store(void) @@ -113,6 +148,7 @@ fnstack_push(char const *file_path) files->filenames[files->len++] = get_filename(file_path); } +/* Returns the file name on the top of the file name stack. */ char const * fnstack_peek(void) { @@ -125,6 +161,7 @@ fnstack_peek(void) return files->filenames[files->len - 1]; } +/* Reverts the last fnstack_push(). */ void fnstack_pop(void) { diff --git a/src/thread_var.h b/src/thread_var.h new file mode 100644 index 00000000..c0cea0be --- /dev/null +++ b/src/thread_var.h @@ -0,0 +1,16 @@ +#ifndef SRC_THREAD_VAR_H_ +#define SRC_THREAD_VAR_H_ + +#include "state.h" + +void thvar_init(void); + +int state_store(struct validation *); +struct validation *state_retrieve(void); + +void fnstack_store(void); +void fnstack_push(char const *); +char const *fnstack_peek(void); +void fnstack_pop(void); + +#endif /* SRC_THREAD_VAR_H_ */ diff --git a/test/Makefile.am b/test/Makefile.am index 5134cfbc..adbd3c72 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,12 +1,9 @@ AM_CFLAGS = -pedantic -Wall -std=gnu11 -I../src ${CHECK_CFLAGS} MY_LDADD = ${CHECK_LIBS} -check_PROGRAMS = address.test line_file.test tal.test +check_PROGRAMS = line_file.test tal.test TESTS = ${check_PROGRAMS} -address_test_SOURCES = address_test.c ../src/address.c ../src/address.h -address_test_LDADD = ${MY_LDADD} - line_file_test_SOURCES = line_file_test.c ../src/line_file.c ../src/line_file.h line_file_test_LDADD = ${MY_LDADD} diff --git a/test/address_test.c b/test/address_test.c deleted file mode 100644 index 459c6e93..00000000 --- a/test/address_test.c +++ /dev/null @@ -1,264 +0,0 @@ -#include "address.h" - -#include -#include -#include -#include - -static bool -p4test(uint32_t a1, unsigned int l1, uint32_t a2, unsigned int l2) -{ - struct ipv4_prefix a, b; - - a.addr.s_addr = htonl(a1); - a.len = l1; - b.addr.s_addr = htonl(a2); - b.len = l2; - - return prefix4_contains(&a, &b); -} - -START_TEST(test_prefix4_contains) -{ - unsigned int i; - - /* Prefix-only tests */ - - ck_assert_int_eq(false, p4test(0x12345678u, 32, 0x12345677u, 32)); - ck_assert_int_eq(true, p4test(0x12345678u, 32, 0x12345678u, 32)); - ck_assert_int_eq(false, p4test(0x12345678u, 32, 0x12345679u, 32)); - - ck_assert_int_eq(false, p4test(0x01020304u, 30, 0x01020303u, 32)); - ck_assert_int_eq(true, p4test(0x01020304u, 30, 0x01020304u, 32)); - ck_assert_int_eq(true, p4test(0x01020304u, 30, 0x01020305u, 32)); - ck_assert_int_eq(true, p4test(0x01020304u, 30, 0x01020306u, 32)); - ck_assert_int_eq(true, p4test(0x01020304u, 30, 0x01020307u, 32)); - ck_assert_int_eq(false, p4test(0x01020304u, 30, 0x01020308u, 32)); - - ck_assert_int_eq(true, p4test(0x00000000u, 0, 0x00000000u, 32)); - ck_assert_int_eq(true, p4test(0x00000000u, 0, 0x12345678u, 32)); - ck_assert_int_eq(true, p4test(0x00000000u, 0, 0xFFFFFFFFu, 32)); - - /* Length-only tests */ - - for (i = 0; i < 33; i++) - ck_assert_int_eq(true, p4test(0, i, 0, 32)); - for (i = 0; i < 32; i++) - ck_assert_int_eq(false, p4test(0, 32, 0, i)); - for (i = 0; i < 33; i++) - ck_assert_int_eq(true, p4test(0, 0, 0, i)); - for (i = 1; i < 33; i++) - ck_assert_int_eq(false, p4test(0, i, 0, 0)); -} -END_TEST - -static void -p6init(struct ipv6_prefix *p, uint32_t q1, uint32_t q2, uint32_t q3, - uint32_t q4, unsigned int len) -{ - p->addr.s6_addr32[0] = htonl(q1); - p->addr.s6_addr32[1] = htonl(q2); - p->addr.s6_addr32[2] = htonl(q3); - p->addr.s6_addr32[3] = htonl(q4); - p->len = len; -} - -START_TEST(test_prefix6_contains) -{ - struct ipv6_prefix a, b; - - p6init(&a, 0, 0, 0, 0, 128); - p6init(&b, 0, 0, 0, 0, 128); - - /* Length-only tests */ - - for (a.len = 0; a.len < 129; a.len++) - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - a.len = 128; - for (b.len = 0; b.len < 128; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - a.len = 0; - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - b.len = 0; - for (a.len = 1; a.len < 129; a.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* Full quadrants */ - - /* pl = 0 */ - p6init(&a, 0, 0, 0, 0, 0); - p6init(&b, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - /* Others were already tested above. */ - - /* pl = 32 */ - p6init(&a, 0x13131313u, 0, 0, 0, 32); - p6init(&b, 0x13131313u, 0, 0, 0, 32); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x13131313u, 0xffffffffu, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x13151313u, 0xffffffffu, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* pl = 64 */ - p6init(&a, 0x13131313u, 0x13131313u, 0, 0, 64); - p6init(&b, 0x13131313u, 0x13131313u, 0, 0, 64); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x13131313u, 0x13131313u, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x13151313u, 0x13131313u, 0, 0, 128); - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - p6init(&b, 0x13131313u, 0x13151313u, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* pl = 96 */ - p6init(&a, 0x13131313u, 0x13131313u, 0x13131313u, 0, 96); - p6init(&b, 0x13131313u, 0x13131313u, 0x13131313u, 0, 96); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x13131313u, 0x13131313u, 0x13131313u, 0xffffffffu, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x13151313u, 0x13131313u, 0x13131313u, 0, 128); - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - p6init(&b, 0x13131313u, 0x13151313u, 0x13131313u, 0x12345678u, 128); - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - p6init(&b, 0x13131313u, 0x13131313u, 0x13151313u, 0xffffffffu, 128); - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* Try different prefixes in the same quadrant*/ - - p6init(&a, 0x20010000u, 0, 0, 0, 16); - p6init(&b, 0x20000000u, 0, 0, 0, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - p6init(&a, 0, 0x20010000u, 0, 0, 48); - p6init(&b, 0, 0x20000000u, 0, 0, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - p6init(&a, 0, 0, 0x20010000u, 0, 80); - p6init(&b, 0, 0, 0x20000000u, 0, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - p6init(&a, 0, 0, 0, 0x20010000u, 112); - p6init(&b, 0, 0, 0, 0x20000000u, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* Try different prefixes in different quadrants */ - - /* q2 */ - p6init(&a, 1, 0x20010000u, 0, 0, 48); - p6init(&b, 0, 0x20010000u, 0, 0, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* q3 */ - p6init(&a, 1, 0, 0x20010000u, 0, 80); - p6init(&b, 0, 0, 0x20000000u, 0, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - p6init(&a, 0, 1, 0x20010000u, 0, 80); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* q4 */ - p6init(&a, 1, 0, 0, 0x20010000u, 112); - p6init(&b, 0, 0, 0, 0x20000000u, 0); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - p6init(&a, 0, 1, 0, 0x20010000u, 112); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - p6init(&a, 0, 0, 1, 0x20010000u, 112); - for (b.len = 0; b.len < 129; b.len++) - ck_assert_int_eq(false, prefix6_contains(&a, &b)); - - /* Try actually containing prefixes */ - - /* q1 */ - p6init(&a, 0x20010000u, 0, 0, 0, 16); - p6init(&b, 0x20010000u, 0, 0, 0, 16); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x2001ffffu, 0, 0, 0, 32); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x2001ffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - /* q2 */ - p6init(&a, 0x20010000u, 0x20010000u, 0, 0, 48); - p6init(&b, 0x20010000u, 0x20010000u, 0, 0, 48); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x20010000u, 0x2001ffffu, 0, 0, 64); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x20010000u, 0x2001ffffu, 0xffffffffu, 0xffffffffu, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - /* q3 */ - p6init(&a, 0x20010000u, 0x20010000u, 0x20010000u, 0, 80); - p6init(&b, 0x20010000u, 0x20010000u, 0x20010000u, 0, 80); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x20010000u, 0x20010000u, 0x2001ffffu, 0, 96); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x20010000u, 0x20010000u, 0x2001ffffu, 0xffffffff, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - /* q4 */ - p6init(&a, 0x20010000u, 0x20010000u, 0x20010000u, 0x20010000, 112); - p6init(&b, 0x20010000u, 0x20010000u, 0x20010000u, 0x20010000, 112); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); - - p6init(&b, 0x20010000u, 0x20010000u, 0x20010000u, 0x2001ffff, 128); - ck_assert_int_eq(true, prefix6_contains(&a, &b)); -} -END_TEST - -Suite *lfile_read_suite(void) -{ - Suite *suite; - TCase *core; - - core = tcase_create("Core"); - tcase_add_test(core, test_prefix6_contains); - tcase_add_test(core, test_prefix4_contains); - - suite = suite_create("address"); - suite_add_tcase(suite, core); - return suite; -} - -int main(void) -{ - Suite *suite; - SRunner *runner; - int tests_failed; - - suite = lfile_read_suite(); - - runner = srunner_create(suite); - srunner_run_all(runner, CK_NORMAL); - tests_failed = srunner_ntests_failed(runner); - srunner_free(runner); - - return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} -- 2.47.3