diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-05-30 09:05:34 +0300 | 
|---|---|---|
| committer | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-05-30 11:04:12 +0300 | 
| commit | dff41cc8a96c7712db26b4711e5d668a7111b471 (patch) | |
| tree | f654cc891c906a7d39011dcf08b126386b40dcaf /bgpd | |
| parent | 859cca2f70636c978626c723e302921038b8beb4 (diff) | |
bgpd: Add JSON output for `show rpki prefix` and other show commands
```
spine1-debian-11# sh rpki prefix 192.168.100.1/32
Prefix                                   Prefix Length  Origin-AS
192.168.100.1                               32 -  32        47583
spine1-debian-11# sh rpki prefix 192.168.100.1/32 json
{
  "prefixes":[
    {
      "prefix":"192.168.100.1",
      "prefixLenMin":32,
      "prefixLenMax":32,
      "asn":47583
    }
  ]
}
```
```
spine1-debian-11# sh rpki as-number 47583 json
{
  "prefixes":[
    {
      "prefix":"192.168.100.1",
      "prefixLenMin":32,
      "prefixLenMax":32,
      "asn":47583
    },
    {
      "prefix":"2606:4700:7000::",
      "prefixLenMin":48,
      "prefixLenMax":48,
      "asn":47583
    }
  ],
  "ipv4PrefixCount":1,
  "ipv6PrefixCount":1
}
spine1-debian-11# sh rpki as-number 47583
RPKI/RTR prefix table
Prefix                                   Prefix Length  Origin-AS
192.168.100.1                               32 -  32        47583
2606:4700:7000::                            48 -  48        47583
Number of IPv4 Prefixes: 1
Number of IPv6 Prefixes: 1
```
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Diffstat (limited to 'bgpd')
| -rw-r--r-- | bgpd/bgp_rpki.c | 179 | 
1 files changed, 139 insertions, 40 deletions
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index c28b81a413..1c7dc7cb0a 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -98,13 +98,14 @@ struct rpki_for_each_record_arg {  	struct vty *vty;  	unsigned int *prefix_amount;  	as_t as; +	json_object *json;  };  static int start(void);  static void stop(void);  static int reset(bool force);  static struct rtr_mgr_group *get_connected_group(void); -static void print_prefix_table(struct vty *vty); +static void print_prefix_table(struct vty *vty, json_object *json);  static void install_cli_commands(void);  static int config_write(struct vty *vty);  static int config_on_exit(struct vty *vty); @@ -121,7 +122,8 @@ static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);  static struct cache *find_cache(const uint8_t preference);  static int add_tcp_cache(const char *host, const char *port,  			 const uint8_t preference, const char *bindaddr); -static void print_record(const struct pfx_record *record, struct vty *vty); +static void print_record(const struct pfx_record *record, struct vty *vty, +			 json_object *json);  static bool is_synchronized(void);  static bool is_running(void);  static bool is_stopping(void); @@ -274,13 +276,27 @@ static struct cache *find_cache(const uint8_t preference)  	return NULL;  } -static void print_record(const struct pfx_record *record, struct vty *vty) +static void print_record(const struct pfx_record *record, struct vty *vty, +			 json_object *json)  {  	char ip[INET6_ADDRSTRLEN]; +	json_object *json_record = NULL;  	lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip)); -	vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len, -		record->max_len, record->asn); + +	if (!json) { +		vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len, +			record->max_len, record->asn); +	} else { +		json_record = json_object_new_object(); +		json_object_string_add(json_record, "prefix", ip); +		json_object_int_add(json_record, "prefixLenMin", +				    record->min_len); +		json_object_int_add(json_record, "prefixLenMax", +				    record->max_len); +		json_object_int_add(json_record, "asn", record->asn); +		json_object_array_add(json, json_record); +	}  }  static void print_record_by_asn(const struct pfx_record *record, void *data) @@ -290,7 +306,7 @@ static void print_record_by_asn(const struct pfx_record *record, void *data)  	if (record->asn == arg->as) {  		(*arg->prefix_amount)++; -		print_record(record, vty); +		print_record(record, vty, arg->json);  	}  } @@ -301,7 +317,7 @@ static void print_record_cb(const struct pfx_record *record, void *data)  	(*arg->prefix_amount)++; -	print_record(record, vty); +	print_record(record, vty, arg->json);  }  static struct rtr_mgr_group *get_groups(void) @@ -653,25 +669,36 @@ static struct rtr_mgr_group *get_connected_group(void)  	return rtr_mgr_get_first_group(rtr_config);  } -static void print_prefix_table_by_asn(struct vty *vty, as_t as) +static void print_prefix_table_by_asn(struct vty *vty, as_t as, +				      json_object *json)  {  	unsigned int number_of_ipv4_prefixes = 0;  	unsigned int number_of_ipv6_prefixes = 0;  	struct rtr_mgr_group *group = get_connected_group();  	struct rpki_for_each_record_arg arg; +	json_object *json_records = NULL;  	arg.vty = vty;  	arg.as = as; +	arg.json = NULL;  	if (!group) { -		vty_out(vty, "Cannot find a connected group.\n"); +		if (!json) +			vty_out(vty, "Cannot find a connected group.\n");  		return;  	}  	struct pfx_table *pfx_table = group->sockets[0]->pfx_table; -	vty_out(vty, "RPKI/RTR prefix table\n"); -	vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS"); +	if (!json) { +		vty_out(vty, "RPKI/RTR prefix table\n"); +		vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", +			"Origin-AS"); +	} else { +		json_records = json_object_new_array(); +		json_object_object_add(json, "prefixes", json_records); +		arg.json = json_records; +	}  	arg.prefix_amount = &number_of_ipv4_prefixes;  	pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg); @@ -679,27 +706,51 @@ static void print_prefix_table_by_asn(struct vty *vty, as_t as)  	arg.prefix_amount = &number_of_ipv6_prefixes;  	pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg); -	vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes); -	vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes); +	if (!json) { +		vty_out(vty, "Number of IPv4 Prefixes: %u\n", +			number_of_ipv4_prefixes); +		vty_out(vty, "Number of IPv6 Prefixes: %u\n", +			number_of_ipv6_prefixes); +	} else { +		json_object_int_add(json, "ipv4PrefixCount", +				    number_of_ipv4_prefixes); +		json_object_int_add(json, "ipv6PrefixCount", +				    number_of_ipv6_prefixes); +	} + +	if (json) +		vty_json(vty, json);  } -static void print_prefix_table(struct vty *vty) +static void print_prefix_table(struct vty *vty, json_object *json)  {  	struct rpki_for_each_record_arg arg;  	unsigned int number_of_ipv4_prefixes = 0;  	unsigned int number_of_ipv6_prefixes = 0;  	struct rtr_mgr_group *group = get_connected_group(); +	json_object *json_records = NULL;  	arg.vty = vty; +	arg.json = NULL; -	if (!group) +	if (!group) { +		if (!json) +			vty_out(vty, "Cannot find a connected group.\n");  		return; +	}  	struct pfx_table *pfx_table = group->sockets[0]->pfx_table; -	vty_out(vty, "RPKI/RTR prefix table\n"); -	vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS"); +	if (!json) { +		vty_out(vty, "RPKI/RTR prefix table\n"); +		vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", +			"Origin-AS"); +	} else { +		json_records = json_object_new_array(); +		json_object_object_add(json, "prefixes", json_records); +		arg.json = json_records; +	}  	arg.prefix_amount = &number_of_ipv4_prefixes;  	pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg); @@ -707,8 +758,20 @@ static void print_prefix_table(struct vty *vty)  	arg.prefix_amount = &number_of_ipv6_prefixes;  	pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg); -	vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes); -	vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes); +	if (!json) { +		vty_out(vty, "Number of IPv4 Prefixes: %u\n", +			number_of_ipv4_prefixes); +		vty_out(vty, "Number of IPv6 Prefixes: %u\n", +			number_of_ipv6_prefixes); +	} else { +		json_object_int_add(json, "ipv4PrefixCount", +				    number_of_ipv4_prefixes); +		json_object_int_add(json, "ipv6PrefixCount", +				    number_of_ipv6_prefixes); +	} + +	if (json) +		vty_json(vty, json);  }  static int rpki_validate_prefix(struct peer *peer, struct attr *attr, @@ -1187,49 +1250,70 @@ DEFPY (no_rpki_cache,  	return CMD_SUCCESS;  } -DEFUN (show_rpki_prefix_table, +DEFPY (show_rpki_prefix_table,         show_rpki_prefix_table_cmd, -       "show rpki prefix-table", +       "show rpki prefix-table [json$uj]",         SHOW_STR         RPKI_OUTPUT_STRING -       "Show validated prefixes which were received from RPKI Cache\n") +       "Show validated prefixes which were received from RPKI Cache\n" +       JSON_STR)  { -	if (is_synchronized()) -		print_prefix_table(vty); -	else -		vty_out(vty, "No connection to RPKI cache server.\n"); +	struct json_object *json = NULL; + +	if (!is_synchronized()) { +		if (!uj) +			vty_out(vty, "No connection to RPKI cache server.\n"); +		return CMD_WARNING; +	} +	if (uj) +		json = json_object_new_object(); + +	print_prefix_table(vty, json);  	return CMD_SUCCESS;  } -DEFPY (show_rpki_as_number, show_rpki_as_number_cmd, -      "show rpki as-number (1-4294967295)$by_asn", -      SHOW_STR RPKI_OUTPUT_STRING -      "Lookup by ASN in prefix table\n" -      "AS Number\n") +DEFPY (show_rpki_as_number, +       show_rpki_as_number_cmd, +       "show rpki as-number (1-4294967295)$by_asn [json$uj]", +       SHOW_STR +       RPKI_OUTPUT_STRING +       "Lookup by ASN in prefix table\n" +       "AS Number\n" +       JSON_STR)  { +	struct json_object *json = NULL; +  	if (!is_synchronized()) { -		vty_out(vty, "No Connection to RPKI cache server.\n"); +		if (!uj) +			vty_out(vty, "No Connection to RPKI cache server.\n");  		return CMD_WARNING;  	} -	print_prefix_table_by_asn(vty, by_asn); +	if (uj) +		json = json_object_new_object(); + +	print_prefix_table_by_asn(vty, by_asn, json);  	return CMD_SUCCESS;  }  DEFPY (show_rpki_prefix,         show_rpki_prefix_cmd, -       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]", +       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]",         SHOW_STR         RPKI_OUTPUT_STRING         "Lookup IP prefix and optionally ASN in prefix table\n"         "IPv4 prefix\n"         "IPv6 prefix\n" -       "AS Number\n") +       "AS Number\n" +       JSON_STR)  { +	json_object *json = NULL; +	json_object *json_records = NULL;  	if (!is_synchronized()) { -		vty_out(vty, "No Connection to RPKI cache server.\n"); +		if (!uj) +			vty_out(vty, "No Connection to RPKI cache server.\n");  		return CMD_WARNING;  	} @@ -1241,7 +1325,8 @@ DEFPY (show_rpki_prefix,  	memcpy(addr_str, prefix_str, addr_len);  	if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) { -		vty_out(vty, "Invalid IP prefix\n"); +		if (!json) +			vty_out(vty, "Invalid IP prefix\n");  		return CMD_WARNING;  	} @@ -1252,21 +1337,35 @@ DEFPY (show_rpki_prefix,  	if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,  				 asn, &addr, prefix->prefixlen, &result)  	    != PFX_SUCCESS) { -		vty_out(vty, "Prefix lookup failed\n"); +		if (!json) +			vty_out(vty, "Prefix lookup failed\n");  		return CMD_WARNING;  	} -	vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS"); +	if (uj) +		json = json_object_new_object(); + +	if (!json) { +		vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", +			"Origin-AS"); +	} else { +		json_records = json_object_new_array(); +		json_object_object_add(json, "prefixes", json_records); +	} +  	for (size_t i = 0; i < match_count; ++i) {  		const struct pfx_record *record = &matches[i];  		if (record->max_len >= prefix->prefixlen  		    && ((asn != 0 && (uint32_t)asn == record->asn)  			|| asn == 0)) { -			print_record(&matches[i], vty); +			print_record(&matches[i], vty, json_records);  		}  	} +	if (json) +		vty_json(vty, json); +  	return CMD_SUCCESS;  }  | 
