From: David Mandelberg <dmand...@bbn.com>

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 | 228 ++++++++++++++++++++++++++++++++++++++++++++++--
 lib/rpki/querySupport.h |   4 +-
 5 files changed, 229 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..bc4f4da 100644
--- a/lib/rpki/querySupport.c
+++ b/lib/rpki/querySupport.c
@@ -42,6 +42,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 +204,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 +221,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 +259,198 @@ static int displaySNList(
     return 2;
 }
 
+struct display_ip_addrs_context
+{
+    char const * separator;
+
+    char * result;
+    size_t result_len;
+    size_t result_idx;
+};
+
+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;
+
+    uint8_t const * prefix = s->vec[0].valptr;
+    int_fast64_t const prefix_family_length = s->vec[0].avalsize;
+    unsigned const prefix_length =
+        *(unsigned const *)s->vec[1].valptr;
+    unsigned const prefix_max_length =
+        *(unsigned 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/%u(%u)%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;
+}
+
+static int display_ip_addrs(
+    scm * scmp,
+    scmcon * connection,
+    scmsrcha * s,
+    int idx1,
+    char *returnStr)
+{
+    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 int roa_local_id =
+        *((unsigned int *)(s->vec[idx1].valptr));
+    char roa_local_id_str[24];
+    snprintf(roa_local_id_str, sizeof(roa_local_id_str), "%u",
+        roa_local_id);
+
+    struct display_ip_addrs_context context;
+    context.separator = separator;
+    context.result = returnStr;
+    context.result_len = MAX_RESULT_SZ - sizeof(truncated_str);
+    context.result_idx = 0;
+
+    uint8_t prefix[16];
+    unsigned prefix_length;
+    unsigned 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';
+    }
+
+    return 1;
+}
+
 /*
  * helper function for displayFlags 
  */
@@ -292,10 +494,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 +597,22 @@ static QueryField fields[] = {
      "CRLDP", NULL,
      },
     {
-     "ip_addrs",                /* name of the field */
+     "local_id",
+     NULL,
+     Q_JUST_DISPLAY | Q_FOR_ROA,
+     SQL_C_ULONG, 4,
+     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


------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
rpstir-devel mailing list
rpstir-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpstir-devel

Reply via email to