Home | History | Annotate | Line # | Download | only in npftest
npftest.c revision 1.4
      1  1.4  rmind /*	$NetBSD: npftest.c,v 1.4 2012/08/12 03:35:14 rmind Exp $	*/
      2  1.1  rmind 
      3  1.1  rmind /*
      4  1.1  rmind  * NPF testing framework.
      5  1.1  rmind  *
      6  1.1  rmind  * Public Domain.
      7  1.1  rmind  */
      8  1.1  rmind 
      9  1.1  rmind #include <stdio.h>
     10  1.1  rmind #include <stdlib.h>
     11  1.1  rmind #include <stdbool.h>
     12  1.2  rmind #include <string.h>
     13  1.1  rmind #include <unistd.h>
     14  1.1  rmind #include <assert.h>
     15  1.2  rmind #include <fcntl.h>
     16  1.2  rmind #include <err.h>
     17  1.2  rmind 
     18  1.2  rmind #include <sys/ioctl.h>
     19  1.2  rmind #include <net/if.h>
     20  1.2  rmind #include <arpa/inet.h>
     21  1.1  rmind 
     22  1.1  rmind #include <rump/rump.h>
     23  1.2  rmind #include <rump/rump_syscalls.h>
     24  1.1  rmind 
     25  1.1  rmind #include "npftest.h"
     26  1.1  rmind 
     27  1.2  rmind static bool verbose, quiet;
     28  1.1  rmind 
     29  1.1  rmind static void
     30  1.1  rmind usage(void)
     31  1.1  rmind {
     32  1.2  rmind 	printf("usage: %s: [ -q | -v ] [ -c <config> ] "
     33  1.4  rmind 	    "[ -i <interface> ] < -b | -t | -s file >\n"
     34  1.2  rmind 	    "\t-b: benchmark\n"
     35  1.2  rmind 	    "\t-t: regression test\n"
     36  1.4  rmind 	    "\t-s <file>: pcap stream\n"
     37  1.2  rmind 	    "\t-c <config>: NPF configuration file\n"
     38  1.4  rmind 	    "\t-i <interface>: primary interface\n"
     39  1.2  rmind 	    "\t-q: quiet mode\n"
     40  1.2  rmind 	    "\t-v: verbose mode\n",
     41  1.2  rmind 	    getprogname());
     42  1.2  rmind 	exit(EXIT_FAILURE);
     43  1.1  rmind }
     44  1.1  rmind 
     45  1.1  rmind static void
     46  1.2  rmind result(const char *testcase, bool ok)
     47  1.1  rmind {
     48  1.1  rmind 	if (!quiet) {
     49  1.2  rmind 		printf("NPF %-10s\t%s\n", testcase, ok ? "OK" : "fail");
     50  1.1  rmind 	}
     51  1.1  rmind 	if (verbose) {
     52  1.1  rmind 		puts("-----");
     53  1.1  rmind 	}
     54  1.1  rmind 	if (!ok) {
     55  1.1  rmind 		exit(EXIT_FAILURE);
     56  1.1  rmind 	}
     57  1.1  rmind }
     58  1.1  rmind 
     59  1.2  rmind static void
     60  1.4  rmind load_npf_config_ifs(prop_dictionary_t dbg_dict)
     61  1.2  rmind {
     62  1.4  rmind 	prop_dictionary_t ifdict;
     63  1.4  rmind 	prop_object_iterator_t it;
     64  1.4  rmind 	prop_array_t iflist;
     65  1.4  rmind 
     66  1.4  rmind 	iflist = prop_dictionary_get(dbg_dict, "interfaces");
     67  1.4  rmind 	it = prop_array_iterator(iflist);
     68  1.4  rmind 	while ((ifdict = prop_object_iterator_next(it)) != NULL) {
     69  1.4  rmind 		const char *ifname;
     70  1.4  rmind 		unsigned if_idx;
     71  1.4  rmind 
     72  1.4  rmind 		prop_dictionary_get_cstring_nocopy(ifdict, "name", &ifname);
     73  1.4  rmind 		prop_dictionary_get_uint32(ifdict, "idx", &if_idx);
     74  1.4  rmind 		(void)rumpns_npf_test_addif(ifname, if_idx, verbose);
     75  1.2  rmind 	}
     76  1.4  rmind 	prop_object_iterator_release(it);
     77  1.2  rmind }
     78  1.2  rmind 
     79  1.2  rmind static void
     80  1.2  rmind load_npf_config(const char *config)
     81  1.2  rmind {
     82  1.4  rmind 	prop_dictionary_t npf_dict, dbg_dict;
     83  1.2  rmind 	void *xml;
     84  1.2  rmind 	int error;
     85  1.2  rmind 
     86  1.4  rmind 	/* Read the configuration from the specified file. */
     87  1.2  rmind 	npf_dict = prop_dictionary_internalize_from_file(config);
     88  1.2  rmind 	if (!npf_dict) {
     89  1.2  rmind 		err(EXIT_FAILURE, "prop_dictionary_internalize_from_file");
     90  1.2  rmind 	}
     91  1.2  rmind 	xml = prop_dictionary_externalize(npf_dict);
     92  1.4  rmind 
     93  1.4  rmind 	/* Inspect the debug data.  Create the interfaces, if any. */
     94  1.4  rmind 	dbg_dict = prop_dictionary_get(npf_dict, "debug");
     95  1.4  rmind 	if (dbg_dict) {
     96  1.4  rmind 		load_npf_config_ifs(dbg_dict);
     97  1.4  rmind 	}
     98  1.2  rmind 	prop_object_release(npf_dict);
     99  1.2  rmind 
    100  1.4  rmind 	/* Pass the XML configuration for NPF kernel component to load. */
    101  1.2  rmind 	error = rumpns_npf_test_load(xml);
    102  1.2  rmind 	if (error) {
    103  1.2  rmind 		errx(EXIT_FAILURE, "npf_test_load: %s\n", strerror(error));
    104  1.2  rmind 	}
    105  1.2  rmind 	free(xml);
    106  1.2  rmind 
    107  1.2  rmind 	if (verbose) {
    108  1.2  rmind 		printf("Loaded NPF config at '%s'\n", config);
    109  1.2  rmind 	}
    110  1.2  rmind }
    111  1.2  rmind 
    112  1.4  rmind /*
    113  1.4  rmind  * Need to override for cprng_fast32(), since RUMP uses arc4random() for it.
    114  1.4  rmind  */
    115  1.4  rmind uint32_t
    116  1.4  rmind arc4random(void)
    117  1.4  rmind {
    118  1.4  rmind 	return random();
    119  1.4  rmind }
    120  1.4  rmind 
    121  1.1  rmind int
    122  1.1  rmind main(int argc, char **argv)
    123  1.1  rmind {
    124  1.2  rmind 	bool benchmark, test, ok;
    125  1.4  rmind 	char *config, *interface, *stream;
    126  1.4  rmind 	int idx = -1, ch;
    127  1.1  rmind 
    128  1.1  rmind 	benchmark = false;
    129  1.2  rmind 	test = false;
    130  1.2  rmind 
    131  1.2  rmind 	config = NULL;
    132  1.4  rmind 	interface = NULL;
    133  1.2  rmind 	stream = NULL;
    134  1.2  rmind 
    135  1.1  rmind 	verbose = false;
    136  1.1  rmind 	quiet = false;
    137  1.1  rmind 
    138  1.2  rmind 	while ((ch = getopt(argc, argv, "bqvc:i:s:t")) != -1) {
    139  1.1  rmind 		switch (ch) {
    140  1.1  rmind 		case 'b':
    141  1.1  rmind 			benchmark = true;
    142  1.1  rmind 			break;
    143  1.1  rmind 		case 'q':
    144  1.1  rmind 			quiet = true;
    145  1.1  rmind 			break;
    146  1.1  rmind 		case 'v':
    147  1.1  rmind 			verbose = true;
    148  1.1  rmind 			break;
    149  1.2  rmind 		case 'c':
    150  1.2  rmind 			config = optarg;
    151  1.2  rmind 			break;
    152  1.2  rmind 		case 'i':
    153  1.4  rmind 			interface = optarg;
    154  1.2  rmind 			break;
    155  1.2  rmind 		case 's':
    156  1.2  rmind 			stream = optarg;
    157  1.2  rmind 			break;
    158  1.2  rmind 		case 't':
    159  1.2  rmind 			test = true;
    160  1.2  rmind 			break;
    161  1.1  rmind 		default:
    162  1.1  rmind 			usage();
    163  1.1  rmind 		}
    164  1.1  rmind 	}
    165  1.1  rmind 
    166  1.4  rmind 	/*
    167  1.4  rmind 	 * Either benchmark or test.  If stream analysis, then the interface
    168  1.4  rmind 	 * is needed as well.
    169  1.4  rmind 	 */
    170  1.4  rmind 	if (benchmark == test && (stream && !interface)) {
    171  1.2  rmind 		usage();
    172  1.2  rmind 	}
    173  1.2  rmind 
    174  1.1  rmind 	/* XXX rn_init */
    175  1.1  rmind 	extern int rumpns_max_keylen;
    176  1.1  rmind 	rumpns_max_keylen = 1;
    177  1.1  rmind 
    178  1.1  rmind 	rump_init();
    179  1.1  rmind 	rump_schedule();
    180  1.1  rmind 
    181  1.2  rmind 	if (config) {
    182  1.2  rmind 		load_npf_config(config);
    183  1.2  rmind 	}
    184  1.4  rmind 	if (interface && (idx = rumpns_npf_test_getif(interface)) == 0) {
    185  1.4  rmind 		errx(EXIT_FAILURE, "failed to find the interface");
    186  1.4  rmind 	}
    187  1.4  rmind 
    188  1.4  rmind 	srandom(1);
    189  1.2  rmind 
    190  1.2  rmind 	if (test) {
    191  1.2  rmind 		ok = rumpns_npf_nbuf_test(verbose);
    192  1.2  rmind 		result("nbuf", ok);
    193  1.1  rmind 
    194  1.2  rmind 		ok = rumpns_npf_processor_test(verbose);
    195  1.2  rmind 		result("processor", ok);
    196  1.1  rmind 
    197  1.2  rmind 		ok = rumpns_npf_table_test(verbose);
    198  1.2  rmind 		result("table", ok);
    199  1.3  rmind 
    200  1.3  rmind 		ok = rumpns_npf_state_test(verbose);
    201  1.3  rmind 		result("state", ok);
    202  1.2  rmind 	}
    203  1.2  rmind 
    204  1.4  rmind 	if (test && config) {
    205  1.4  rmind 		ok = rumpns_npf_rule_test(verbose);
    206  1.4  rmind 		result("rule", ok);
    207  1.4  rmind 
    208  1.4  rmind 		ok = rumpns_npf_nat_test(verbose);
    209  1.4  rmind 		result("nat", ok);
    210  1.4  rmind 	}
    211  1.4  rmind 
    212  1.2  rmind 	if (stream) {
    213  1.2  rmind 		process_stream(stream, NULL, idx);
    214  1.2  rmind 	}
    215  1.1  rmind 
    216  1.1  rmind 	rump_unschedule();
    217  1.1  rmind 
    218  1.1  rmind 	return EXIT_SUCCESS;
    219  1.1  rmind }
    220