Use the schema introduced in the previous set of commits when querying ROAs from the database.
WARNING: This is one of a series of commits to use the updated schema. It is not the last in the series, so the code is still broken. addresses [#6] and [#7] --- bin/rpki/query.c | 4 +- lib/rpki/err.c | 1 + lib/rpki/err.h | 3 +- lib/rpki/querySupport.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/rpki/querySupport.h | 4 +- 5 files changed, 249 insertions(+), 11 deletions(-) diff --git a/bin/rpki/query.c b/bin/rpki/query.c index 70e600d..4af5b60 100644 --- a/bin/rpki/query.c +++ b/bin/rpki/query.c @@ -91,7 +91,6 @@ static int handleResults( char resultStr[MAX_RESULT_SZ]; int i; - UNREFERENCED_PARAMETER(conp); UNREFERENCED_PARAMETER(numLine); if (validate) { @@ -108,7 +107,8 @@ static int handleResults( QueryField *field = globalFields[display]; if (field->displayer != NULL) { - result += field->displayer(s, result, resultStr); + result += field->displayer( + scmp, conp, s, result, resultStr); } else if (s->vec[result].avalsize != SQL_NULL_DATA) { diff --git a/lib/rpki/err.c b/lib/rpki/err.c index 9b078c1..f184546 100644 --- a/lib/rpki/err.c +++ b/lib/rpki/err.c @@ -180,6 +180,7 @@ static char *errs[-(ERR_SCM_MAXERR) + 1] = { "AIA in TA cert", /* ERR_SCM_AIATA */ "Invalid signed attribute", /* ERR_SCM_INVALSATTR */ "TA cert has inherit resources", /* ERR_SCM_TAINHERIT */ + "Truncated data", /* ERR_SCM_TRUNCATED */ }; char *err2string( diff --git a/lib/rpki/err.h b/lib/rpki/err.h index 7313904..835b624 100644 --- a/lib/rpki/err.h +++ b/lib/rpki/err.h @@ -169,7 +169,8 @@ #define ERR_SCM_AIATA -160 /* AIA found in TA cert */ #define ERR_SCM_INVALSATTR -161 /* Invalid signed attribute */ #define ERR_SCM_TAINHERIT -162 /* TA cert has inherit resources */ -#define ERR_SCM_MAXERR -162 +#define ERR_SCM_TRUNCATED -163 /* Truncated data */ +#define ERR_SCM_MAXERR -163 /* * macro that prints an error string and call return if a condition is true diff --git a/lib/rpki/querySupport.c b/lib/rpki/querySupport.c index 1e6c6c3..3385319 100644 --- a/lib/rpki/querySupport.c +++ b/lib/rpki/querySupport.c @@ -7,6 +7,7 @@ #include <unistd.h> #include <string.h> #include <mysql.h> +#include <arpa/inet.h> #include "config/config.h" @@ -42,6 +43,7 @@ void addQueryFlagTests( * all these static variables are used for efficiency, so that * there is no need to initialize them with each call to checkValidity */ +static scmtab *roaPrefixTable = NULL; static scmtab *validTable = NULL; static scmsrcha *validSrch = NULL, *anySrch = NULL; @@ -203,10 +205,14 @@ int checkValidity( * combines dirname and filename into a pathname */ static int pathnameDisplay( + scm * scmp, + scmcon * connection, scmsrcha * s, int idx1, char *returnStr) { + (void)scmp; + (void)connection; snprintf(returnStr, MAX_RESULT_SZ, "%s/%s", (char *)s->vec[idx1].valptr, (char *)s->vec[idx1 + 1].valptr); return 2; @@ -216,10 +222,15 @@ static int pathnameDisplay( * create space-separated string of serial numbers */ static int displaySNList( + scm * scmp, + scmcon * connection, scmsrcha * s, int idx1, char *returnStr) { + (void)scmp; + (void)connection; + uint8_t *snlist; unsigned int i, snlen; @@ -249,6 +260,217 @@ static int displaySNList( return 2; } +/** + * @brief callback state for the display_ip_addrs_valuefunc() + * callback function + */ +struct display_ip_addrs_context +{ + char const * separator; + + char * result; + size_t result_len; + size_t result_idx; +}; + +/** + * @brief searchscm() callback for display_ip_addrs(), called for each + * prefix in a ROA + */ +static int display_ip_addrs_valuefunc( + scmcon * conp, + scmsrcha * s, + ssize_t idx) +{ + (void)conp; + (void)idx; + + struct display_ip_addrs_context * context = s->context; + + unsigned char const * prefix = s->vec[0].valptr; + int_fast64_t const prefix_family_length = s->vec[0].avalsize; + unsigned long const prefix_length = + *(unsigned long const *)s->vec[1].valptr; + unsigned long const prefix_max_length = + *(unsigned long const *)s->vec[2].valptr; + + int af; + switch (prefix_family_length) + { + case 4: + af = AF_INET; + break; + + case 16: + af = AF_INET6; + break; + + default: + LOG(LOG_ERR, "invalid prefix_family_length %" PRIuFAST64, + prefix_family_length); + return ERR_SCM_INTERNAL; + } + + char prefix_str[INET6_ADDRSTRLEN]; + if (inet_ntop(af, prefix, prefix_str, sizeof(prefix_str)) == NULL) + { + LOG(LOG_ERR, "error converting prefix to a string"); + return ERR_SCM_INTERNAL; + } + + int snprintf_ret = snprintf( + context->result + context->result_idx, + context->result_len - context->result_idx, + "%s/%lu(%lu)%s", + prefix_str, + prefix_length, + prefix_max_length, + context->separator); + if (snprintf_ret < 0) + { + return ERR_SCM_INTERNAL; + } + else if ((size_t)snprintf_ret >= + context->result_len - context->result_idx) + { + return ERR_SCM_TRUNCATED; + } + else + { + context->result_idx += snprintf_ret; + } + + return 0; +} + +/** + * @brief displayfunc to convert the list of prefixes in a ROA into a + * string, @p returnStr + */ +static int display_ip_addrs( + scm * scmp, + scmcon * connection, + scmsrcha * s, + int idx1, + char *returnStr) +{ + static char const none_str[] = "(none)"; + static char const truncated_str[] = "..."; + static char const separator[] = ", "; + static size_t const separator_len = sizeof(separator) - 1; + + if (roaPrefixTable == NULL) + { + roaPrefixTable = findtablescm(scmp, "ROA_PREFIX"); + } + + int sta; + + unsigned long roa_local_id = + *((unsigned long *)(s->vec[idx1].valptr)); + char roa_local_id_str[24]; + snprintf(roa_local_id_str, sizeof(roa_local_id_str), "%lu", + roa_local_id); + + struct display_ip_addrs_context context; + context.separator = separator; + context.result = returnStr; + context.result[0] = '\0'; + context.result_len = MAX_RESULT_SZ - sizeof(truncated_str); + context.result_idx = 0; + + unsigned char prefix[16]; + unsigned long prefix_length; + unsigned long prefix_max_length; + + scmsrch select[3]; + scmkv where_cols[1]; + scmkva where; + char * order; + scmsrcha srch; + + select[0].colno = 1; + select[0].sqltype = SQL_C_BINARY; + select[0].colname = "prefix"; + select[0].valptr = prefix; + select[0].valsize = sizeof(prefix); + select[0].avalsize = 0; + select[1].colno = 2; + select[1].sqltype = SQL_C_ULONG; + select[1].colname = "prefix_length"; + select[1].valptr = &prefix_length; + select[1].valsize = sizeof(prefix_length); + select[1].avalsize = 0; + select[2].colno = 3; + select[2].sqltype = SQL_C_ULONG; + select[2].colname = "prefix_max_length"; + select[2].valptr = &prefix_max_length; + select[2].valsize = sizeof(prefix_max_length); + select[2].avalsize = 0; + + where_cols[0].column = "roa_local_id"; + where_cols[0].value = roa_local_id_str; + + where.vec = where_cols; + where.ntot = sizeof(where_cols)/sizeof(where_cols[0]); + where.nused = where.ntot; + where.vald = 0; + + order = + "length(prefix) asc, " + "prefix asc, " + "prefix_length asc, " + "prefix_max_length asc"; + + srch.vec = select; + srch.sname = NULL; + srch.ntot = sizeof(select)/sizeof(select[0]); + srch.nused = srch.ntot; + srch.vald = 0; + srch.where = &where; + srch.wherestr = NULL; + srch.context = &context; + + sta = searchscm( + connection, + roaPrefixTable, + &srch, + NULL, + display_ip_addrs_valuefunc, + SCM_SRCH_DOVALUE_ANN | SCM_SRCH_BREAK_VERR, + order); + if (sta == ERR_SCM_TRUNCATED) + { + snprintf( + context.result + context.result_idx, + MAX_RESULT_SZ - context.result_idx, + "%s", + truncated_str); + } + else if (sta < 0) + { + // XXX: there should be a better way to signal an error + snprintf( + context.result, + MAX_RESULT_SZ, + "error: %s (%d)", + err2string(sta), + sta); + } + else if (context.result_idx >= separator_len) + { + // Remove the final separator + context.result[context.result_idx - separator_len] = '\0'; + } + else if (context.result[0] == '\0') + { + // Indicate that there were no results + snprintf(context.result, MAX_RESULT_SZ, "%s", none_str); + } + + return 1; +} + /* * helper function for displayFlags */ @@ -292,10 +514,14 @@ void setIsManifest( * create list of all flags set to true */ static int displayFlags( + scm * scmp, + scmcon * connection, scmsrcha * s, int idx1, char *returnStr) { + (void)scmp; + (void)connection; unsigned int flags = *((unsigned int *)(s->vec[idx1].valptr)); returnStr[0] = 0; addFlagIfSet(returnStr, flags, SCM_FLAG_CA, "CA"); @@ -391,14 +617,22 @@ static QueryField fields[] = { "CRLDP", NULL, }, { - "ip_addrs", /* name of the field */ + "local_id", + NULL, + Q_JUST_DISPLAY | Q_FOR_ROA, + SQL_C_ULONG, sizeof(unsigned long), + NULL, NULL, + NULL, NULL, + }, + { + "ip_addrs", "the set of IP addresses assigned by the ROA", - Q_JUST_DISPLAY | Q_FOR_ROA, /* flags */ - SQL_C_CHAR, 32768, /* sql return type, size */ - NULL, /* use this for query, not name */ - NULL, /* second field for query */ - "IP Addresses", /* name of column for printout */ - NULL, /* function for display string */ + Q_JUST_DISPLAY | Q_FOR_ROA, + -1, 0, + "local_id", + NULL, + "IP Addresses", + display_ip_addrs, }, { "asn", diff --git a/lib/rpki/querySupport.h b/lib/rpki/querySupport.h index 2a27e2e..91a98cb 100644 --- a/lib/rpki/querySupport.h +++ b/lib/rpki/querySupport.h @@ -18,6 +18,8 @@ extern void addQueryFlagTests( /****** prototype for a function for displaying a field *****/ typedef int ( *displayfunc) ( + scm * scmp, + scmcon * connection, scmsrcha * s, int idx1, char *returnStr); @@ -78,4 +80,4 @@ void setIsManifest( #define Q_FOR_MAN 0x20 #define Q_FOR_GBR 0x40 -#define MAX_RESULT_SZ 8192 +#define MAX_RESULT_SZ (128 * 1024) -- 1.9.1 ------------------------------------------------------------------------------ _______________________________________________ rpstir-devel mailing list rpstir-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rpstir-devel