text: /*
   * This file is part of RTRlib.
   *
   * This file is subject to the terms and conditions of the MIT license.
   * See the file LICENSE in the top level directory for more details.
   *
   * Website: http://rtrlib.realmv6.org/
   */
  
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
  #include <unistd.h>
  #include "rtrlib/rtrlib.h"
  
  #define RPKI_CACHE_HOST "rpki-validator.realmv6.org"
  #define RPKI_CACHE_POST "8282"
  
  struct test_validity_query {
  	char *pfx;
  	int len;
  	int asn;
  	int val;
  };
  
  /*
   * Verification is based on ROAs for RIPE RIS Routing Beacons, see:
   * (https://www.ripe.net/analyse/internet-measurements/
   *  routing-information-service-ris/current-ris-routing-beacons)
   */
  const struct test_validity_query queries[] = {
  	{"93.175.146.0",	24, 12654, BGP_PFXV_STATE_VALID},
  	{"2001:7fb:fd02::",	48, 12654, BGP_PFXV_STATE_VALID},
  	{"93.175.147.0",	24, 12654, BGP_PFXV_STATE_INVALID},
  	{"2001:7fb:fd03::",	48, 12654, BGP_PFXV_STATE_INVALID},
  	{"84.205.83.0",		24, 12654, BGP_PFXV_STATE_NOT_FOUND},
  	{"2001:7fb:ff03::",	48, 12654, BGP_PFXV_STATE_NOT_FOUND},
  	{NULL, 0, 0, 0}
  };
  
  const int connection_timeout = 20;
  enum rtr_mgr_status connection_status = -1;
  
  static void connection_status_callback(const struct rtr_mgr_group *group,
  				       enum rtr_mgr_status status,
  				       const struct rtr_socket *socket,
  				       void *data)
  {
  	if (status == RTR_MGR_ERROR)
  		connection_status = status;
  }
  
  /**
   * @brief live prefix validation test
   * This test requires an active network connection. It runs an on-line live
   * validation of specific IP prefixes, i.e., RIPE BGP beacons, that have known
   * RPKI validation states. This tests uses a TCP transport connection.
   */
  int main(void)
  {
  	/* create a TCP transport socket */
  	struct tr_socket tr_tcp;
  	struct tr_tcp_config tcp_config = { RPKI_CACHE_HOST,
  					    RPKI_CACHE_POST,
  					    NULL };
  	struct rtr_socket rtr_tcp;
  	struct rtr_mgr_group groups[1];
  
  	/* init a TCP transport and create rtr socket */
  	tr_tcp_init(&tcp_config, &tr_tcp);
  	rtr_tcp.tr_socket = &tr_tcp;
  
  	/* create a rtr_mgr_group array with 1 element */
  	groups[0].sockets = malloc(1 * sizeof(struct rtr_socket *));
  	groups[0].sockets_len = 1;
  	groups[0].sockets[0] = &rtr_tcp;
  	groups[0].preference = 1;
  
  	struct rtr_mgr_config *conf;
  
  	if  (rtr_mgr_init(&conf, groups, 1, 30, 600, 600, NULL, NULL,
  			  &connection_status_callback, NULL) < 0)
  		return EXIT_FAILURE;
  
  	rtr_mgr_start(conf);
  	int sleep_counter = 0;
  	/* wait for connection, or timeout and exit eventually */
  	while (!rtr_mgr_conf_in_sync(conf)) {
  		if (connection_status == RTR_MGR_ERROR)
  			return EXIT_FAILURE;
  
  		sleep(1);
  		sleep_counter++;
  		if (sleep_counter >= connection_timeout)
  			return EXIT_FAILURE;
  	}
  
  	int i = 0;
  	struct test_validity_query q = queries[i];
  	/* test validity of entries in queries[] */
  	while (q.pfx) {
  		struct lrtr_ip_addr pref;
  		enum pfxv_state result;
  		struct pfx_record *reason = NULL;
  		unsigned int reason_len = 0;
  
  		lrtr_ip_str_to_addr(q.pfx, &pref);
  		pfx_table_validate_r(groups[0].sockets[0]->pfx_table, &reason,
  				     &reason_len, q.asn, &pref, q.len, &result);
  		if (result != q.val) {
  			printf("ERROR: prefix validation mismatch.\n");
  			return EXIT_FAILURE;
  		}
  		printf("%s/%d	\tOK\n", q.pfx, q.len);
  		q = queries[++i];
  	}
  
  	rtr_mgr_stop(conf);
  	rtr_mgr_free(conf);
  
  	return EXIT_SUCCESS;
  }
  