From: pcarana Date: Thu, 18 Feb 2021 02:08:30 +0000 (-0600) Subject: Add argument to set the desired output format X-Git-Tag: v1.5.1~31^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f6ba00f8470d35cd4808004f791209fa490d97a1;p=thirdparty%2FFORT-validator.git Add argument to set the desired output format --- diff --git a/src/Makefile.am b/src/Makefile.am index ccf10fc8..86a8a15a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ fort_SOURCES += config/filename_format.h config/filename_format.c fort_SOURCES += config/log_conf.h config/log_conf.c fort_SOURCES += config/mode.c config/mode.h fort_SOURCES += config/incidences.h config/incidences.c +fort_SOURCES += config/output_format.h config/output_format.c fort_SOURCES += config/rrdp_conf.h config/rrdp_conf.c fort_SOURCES += config/rsync_strategy.h config/rsync_strategy.c fort_SOURCES += config/str.c config/str.h diff --git a/src/config.c b/src/config.c index 43cc8ca3..de6ca67a 100644 --- a/src/config.c +++ b/src/config.c @@ -186,8 +186,8 @@ struct rpki_config { char *roa; /** File where the validated BGPsec certs will be stored */ char *bgpsec; - /** File where the validated ROAs will be stored in JSON format */ - char *roa_json; + /** Format for the output */ + enum output_format format; } output; /* ASN1 decoder max stack size allowed */ @@ -690,22 +690,21 @@ static const struct option_field options[] = { .name = "output.roa", .type = >_string, .offset = offsetof(struct rpki_config, output.roa), - .doc = "File where ROAs will be stored in CSV format, use '-' to print at console", + .doc = "File where ROAs will be stored, use '-' to print at console", .arg_doc = "", }, { .id = 6001, .name = "output.bgpsec", .type = >_string, .offset = offsetof(struct rpki_config, output.bgpsec), - .doc = "File where BGPsec Router Keys will be stored in CSV format, use '-' to print at console", + .doc = "File where BGPsec Router Keys will be stored, use '-' to print at console", .arg_doc = "", }, { - .id = 6002, - .name = "output.roa.json", - .type = >_string, - .offset = offsetof(struct rpki_config, output.roa_json), - .doc = "File where ROAs will be stored in JSON format, use '-' to print at console", - .arg_doc = "", + .id = 6002, + .name = "output.format", + .type = >_output_format, + .offset = offsetof(struct rpki_config, output.format), + .doc = "Format to print ROAs and BGPsec Router Keys", }, { @@ -985,8 +984,8 @@ set_default_values(void) } rpki_config.output.roa = NULL; - rpki_config.output.roa_json = NULL; rpki_config.output.bgpsec = NULL; + rpki_config.output.format = OFM_CSV; rpki_config.asn1_decode_max_stack = 4096; /* 4kB */ rpki_config.stale_repository_period = 43200; /* 12 hours */ @@ -1448,15 +1447,15 @@ config_get_output_roa(void) } char const * -config_get_output_roa_json(void) +config_get_output_bgpsec(void) { - return rpki_config.output.roa_json; + return rpki_config.output.bgpsec; } -char const * -config_get_output_bgpsec(void) +enum output_format +config_get_output_format(void) { - return rpki_config.output.bgpsec; + return rpki_config.output.format; } unsigned int diff --git a/src/config.h b/src/config.h index e7772167..680109c9 100644 --- a/src/config.h +++ b/src/config.h @@ -7,6 +7,7 @@ #include "config/filename_format.h" #include "config/log_conf.h" #include "config/mode.h" +#include "config/output_format.h" #include "config/rsync_strategy.h" #include "config/string_array.h" #include "config/types.h" @@ -48,8 +49,8 @@ unsigned int config_get_http_priority(void); unsigned int config_get_http_retry_count(void); unsigned int config_get_http_retry_interval(void); char const *config_get_output_roa(void); -char const *config_get_output_roa_json(void); char const *config_get_output_bgpsec(void); +enum output_format config_get_output_format(void); unsigned int config_get_asn1_decode_max_stack(void); unsigned int config_get_stale_repository_period(void); diff --git a/src/config/output_format.c b/src/config/output_format.c new file mode 100644 index 00000000..525d4b05 --- /dev/null +++ b/src/config/output_format.c @@ -0,0 +1,65 @@ +#include "config/output_format.h" + +#include +#include +#include + +#include "log.h" +#include "config/str.h" + +#define OFM_VALUE_CSV "csv" +#define OFM_VALUE_JSON "json" + +#define DEREFERENCE(void_value) (*((enum output_format *) void_value)) + +static void +print_output_format(struct option_field const *field, void *value) +{ + char const *str = ""; + + switch (DEREFERENCE(value)) { + case OFM_CSV: + str = OFM_VALUE_CSV; + break; + case OFM_JSON: + str = OFM_VALUE_JSON; + break; + } + + pr_op_info("%s: %s", field->name, str); +} + +static int +parse_argv_output_format(struct option_field const *field, char const *str, + void *result) +{ + if (strcmp(str, OFM_VALUE_CSV) == 0) + DEREFERENCE(result) = OFM_CSV; + else if (strcmp(str, OFM_VALUE_JSON) == 0) + DEREFERENCE(result) = OFM_JSON; + else + return pr_op_err("Unknown output format %s: '%s'", + field->name, str); + + return 0; +} + +static int +parse_json_output_format(struct option_field const *opt, json_t *json, + void *result) +{ + char const *string; + int error; + + error = parse_json_string(json, opt->name, &string); + return error ? error : parse_argv_output_format(opt, string, result); +} + +const struct global_type gt_output_format = { + .has_arg = required_argument, + .size = sizeof(enum output_format), + .print = print_output_format, + .parse.argv = parse_argv_output_format, + .parse.json = parse_json_output_format, + .arg_doc = OFM_VALUE_CSV "|" OFM_VALUE_JSON, +}; diff --git a/src/config/output_format.h b/src/config/output_format.h new file mode 100644 index 00000000..537e94c8 --- /dev/null +++ b/src/config/output_format.h @@ -0,0 +1,15 @@ +#ifndef SRC_CONFIG_OUTPUT_FORMAT_H_ +#define SRC_CONFIG_OUTPUT_FORMAT_H_ + +#include "config/types.h" + +enum output_format { + /* CSV format */ + OFM_CSV, + /* JSON format */ + OFM_JSON, +}; + +extern const struct global_type gt_output_format; + +#endif /* SRC_CONFIG_OUTPUT_FORMAT_H_ */ diff --git a/src/output_printer.c b/src/output_printer.c index 18c98b41..7c35de55 100644 --- a/src/output_printer.c +++ b/src/output_printer.c @@ -10,6 +10,11 @@ static char addr_buf[INET6_ADDRSTRLEN]; +typedef struct json_out { + FILE *file; + bool first; +} JSON_OUT; + static int load_output_file(char const *output, FILE **result, bool *fopen) { @@ -40,7 +45,7 @@ load_output_file(char const *output, FILE **result, bool *fopen) } static int -print_roa(struct vrp const *vrp, void *arg) +print_roa_csv(struct vrp const *vrp, void *arg) { FILE *out = arg; @@ -62,40 +67,44 @@ print_roa(struct vrp const *vrp, void *arg) return 0; } -typedef struct json_out { FILE *file; int first; } JSON_OUT; - static int print_roa_json(struct vrp const *vrp, void *arg) { JSON_OUT *json_out = arg; - FILE *out = json_out->file; + FILE *out; + out = json_out->file; if (!json_out->first) fprintf(out, ","); - switch (vrp->addr_fam) { case AF_INET: - fprintf(out, "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }", vrp->asn, - addr2str4(&vrp->prefix.v4, addr_buf), vrp->prefix_length, - vrp->max_prefix_length); + fprintf(out, + "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }", + vrp->asn, + addr2str4(&vrp->prefix.v4, addr_buf), + vrp->prefix_length, + vrp->max_prefix_length); break; case AF_INET6: - fprintf(out, "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }", vrp->asn, - addr2str6(&vrp->prefix.v6, addr_buf), vrp->prefix_length, - vrp->max_prefix_length); + fprintf(out, + "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }", + vrp->asn, + addr2str6(&vrp->prefix.v6, addr_buf), + vrp->prefix_length, + vrp->max_prefix_length); break; default: pr_crit("Unknown family type"); } - json_out->first = 0; + json_out->first = false; return 0; } /* Print as base64url strings without trailing pad */ static int -print_router_key(struct router_key const *key, void *arg) +print_router_key_csv(struct router_key const *key, void *arg) { FILE *out = arg; char *buf1, *buf2; @@ -117,6 +126,40 @@ free1: return error; } +/* Print as base64url strings without trailing pad */ +static int +print_router_key_json(struct router_key const *key, void *arg) +{ + JSON_OUT *json_out = arg; + FILE *out; + char *buf1, *buf2; + int error; + + error = base64url_encode(key->ski, RK_SKI_LEN, &buf1); + if (error) + return error; + + error = base64url_encode(key->spk, RK_SPKI_LEN, &buf2); + if (error) + goto free1; + + out = json_out->file; + if (!json_out->first) + fprintf(out, ","); + + fprintf(out, + "\n { \"asn\" : \"AS%u\", \"ski\" : \"%s\", \"spki\" : \"%s\" }", + key->as, + buf1, + buf2); + + free(buf2); +free1: + free(buf1); + json_out->first = false; + return error; +} + static int open_file(char const *loc, FILE **out, bool *fopen) { @@ -137,6 +180,7 @@ static void print_roas(struct db_table *db) { FILE *out; + JSON_OUT json_out; bool fopen; int error; @@ -145,33 +189,18 @@ print_roas(struct db_table *db) if (error) return; - fprintf(out, "ASN,Prefix,Max prefix length\n"); - error = db_table_foreach_roa(db, print_roa, out); - if (fopen) - file_close(out); - if (error) - pr_op_err("Error printing ROAs"); -} - -static void -print_roas_json(struct db_table *db) -{ - FILE *out; - bool fopen; - int error; - - out = NULL; - error = open_file(config_get_output_roa_json(), &out, &fopen); - if (error) - return; + if (config_get_output_format() == OFM_CSV) { + fprintf(out, "ASN,Prefix,Max prefix length\n"); + error = db_table_foreach_roa(db, print_roa_csv, out); + } else { + json_out.file = out; + json_out.first = true; - JSON_OUT json_out; - json_out.file = out; - json_out.first = 1; + fprintf(out, "{ \"roas\" : ["); + error = db_table_foreach_roa(db, print_roa_json, &json_out); + fprintf(out, "\n]}\n"); + } - fprintf(out, "{ \"roas\" : ["); - error = db_table_foreach_roa(db, print_roa_json, &json_out); - fprintf(out, "\n]}\n"); if (fopen) file_close(out); if (error) @@ -182,6 +211,7 @@ static void print_router_keys(struct db_table *db) { FILE *out; + JSON_OUT json_out; bool fopen; int error; @@ -190,8 +220,21 @@ print_router_keys(struct db_table *db) if (error) return; - fprintf(out, "ASN,Subject Key Identifier,Subject Public Key Info\n"); - error = db_table_foreach_router_key(db, print_router_key, out); + if (config_get_output_format() == OFM_CSV) { + fprintf(out, + "ASN,Subject Key Identifier,Subject Public Key Info\n"); + error = db_table_foreach_router_key(db, print_router_key_csv, + out); + } else { + json_out.file = out; + json_out.first = true; + + fprintf(out, "{ \"router_keys\" : ["); + error = db_table_foreach_router_key(db, print_router_key_json, + &json_out); + fprintf(out, "\n]}\n"); + } + if (fopen) file_close(out); if (error) @@ -202,6 +245,5 @@ void output_print_data(struct db_table *db) { print_roas(db); - print_roas_json(db); print_router_keys(db); }