Home | History | Annotate | Line # | Download | only in npftest
npftest.c revision 1.6
      1  1.4  rmind /*	$NetBSD: npftest.c,v 1.6 2012/08/21 20:52:11 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.6  rmind static bool
     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.6  rmind 	return !ok;
     55  1.1  rmind }
     56  1.1  rmind 
     57  1.2  rmind static void
     58  1.4  rmind load_npf_config_ifs(prop_dictionary_t dbg_dict)
     59  1.2  rmind {
     60  1.4  rmind 	prop_dictionary_t ifdict;
     61  1.4  rmind 	prop_object_iterator_t it;
     62  1.4  rmind 	prop_array_t iflist;
     63  1.4  rmind 
     64  1.4  rmind 	iflist = prop_dictionary_get(dbg_dict, "interfaces");
     65  1.4  rmind 	it = prop_array_iterator(iflist);
     66  1.4  rmind 	while ((ifdict = prop_object_iterator_next(it)) != NULL) {
     67  1.4  rmind 		const char *ifname;
     68  1.4  rmind 		unsigned if_idx;
     69  1.4  rmind 
     70  1.4  rmind 		prop_dictionary_get_cstring_nocopy(ifdict, "name", &ifname);
     71  1.4  rmind 		prop_dictionary_get_uint32(ifdict, "idx", &if_idx);
     72  1.4  rmind 		(void)rumpns_npf_test_addif(ifname, if_idx, verbose);
     73  1.2  rmind 	}
     74  1.4  rmind 	prop_object_iterator_release(it);
     75  1.2  rmind }
     76  1.2  rmind 
     77  1.2  rmind static void
     78  1.2  rmind load_npf_config(const char *config)
     79  1.2  rmind {
     80  1.4  rmind 	prop_dictionary_t npf_dict, dbg_dict;
     81  1.2  rmind 	void *xml;
     82  1.2  rmind 	int error;
     83  1.2  rmind 
     84  1.4  rmind 	/* Read the configuration from the specified file. */
     85  1.2  rmind 	npf_dict = prop_dictionary_internalize_from_file(config);
     86  1.2  rmind 	if (!npf_dict) {
     87  1.2  rmind 		err(EXIT_FAILURE, "prop_dictionary_internalize_from_file");
     88  1.2  rmind 	}
     89  1.2  rmind 	xml = prop_dictionary_externalize(npf_dict);
     90  1.4  rmind 
     91  1.4  rmind 	/* Inspect the debug data.  Create the interfaces, if any. */
     92  1.4  rmind 	dbg_dict = prop_dictionary_get(npf_dict, "debug");
     93  1.4  rmind 	if (dbg_dict) {
     94  1.4  rmind 		load_npf_config_ifs(dbg_dict);
     95  1.4  rmind 	}
     96  1.2  rmind 	prop_object_release(npf_dict);
     97  1.2  rmind 
     98  1.4  rmind 	/* Pass the XML configuration for NPF kernel component to load. */
     99  1.2  rmind 	error = rumpns_npf_test_load(xml);
    100  1.2  rmind 	if (error) {
    101  1.2  rmind 		errx(EXIT_FAILURE, "npf_test_load: %s\n", strerror(error));
    102  1.2  rmind 	}
    103  1.2  rmind 	free(xml);
    104  1.2  rmind 
    105  1.2  rmind 	if (verbose) {
    106  1.2  rmind 		printf("Loaded NPF config at '%s'\n", config);
    107  1.2  rmind 	}
    108  1.2  rmind }
    109  1.2  rmind 
    110  1.4  rmind /*
    111  1.4  rmind  * Need to override for cprng_fast32(), since RUMP uses arc4random() for it.
    112  1.4  rmind  */
    113  1.4  rmind uint32_t
    114  1.4  rmind arc4random(void)
    115  1.4  rmind {
    116  1.4  rmind 	return random();
    117  1.4  rmind }
    118  1.4  rmind 
    119  1.1  rmind int
    120  1.1  rmind main(int argc, char **argv)
    121  1.1  rmind {
    122  1.6  rmind 	bool benchmark, test, ok, fail;
    123  1.4  rmind 	char *config, *interface, *stream;
    124  1.4  rmind 	int idx = -1, ch;
    125  1.1  rmind 
    126  1.1  rmind 	benchmark = false;
    127  1.2  rmind 	test = false;
    128  1.2  rmind 
    129  1.2  rmind 	config = NULL;
    130  1.4  rmind 	interface = NULL;
    131  1.2  rmind 	stream = NULL;
    132  1.2  rmind 
    133  1.1  rmind 	verbose = false;
    134  1.1  rmind 	quiet = false;
    135  1.1  rmind 
    136  1.2  rmind 	while ((ch = getopt(argc, argv, "bqvc:i:s:t")) != -1) {
    137  1.1  rmind 		switch (ch) {
    138  1.1  rmind 		case 'b':
    139  1.1  rmind 			benchmark = true;
    140  1.1  rmind 			break;
    141  1.1  rmind 		case 'q':
    142  1.1  rmind 			quiet = true;
    143  1.1  rmind 			break;
    144  1.1  rmind 		case 'v':
    145  1.1  rmind 			verbose = true;
    146  1.1  rmind 			break;
    147  1.2  rmind 		case 'c':
    148  1.2  rmind 			config = optarg;
    149  1.2  rmind 			break;
    150  1.2  rmind 		case 'i':
    151  1.4  rmind 			interface = optarg;
    152  1.2  rmind 			break;
    153  1.2  rmind 		case 's':
    154  1.2  rmind 			stream = optarg;
    155  1.2  rmind 			break;
    156  1.2  rmind 		case 't':
    157  1.2  rmind 			test = true;
    158  1.2  rmind 			break;
    159  1.1  rmind 		default:
    160  1.1  rmind 			usage();
    161  1.1  rmind 		}
    162  1.1  rmind 	}
    163  1.1  rmind 
    164  1.4  rmind 	/*
    165  1.4  rmind 	 * Either benchmark or test.  If stream analysis, then the interface
    166  1.4  rmind 	 * is needed as well.
    167  1.4  rmind 	 */
    168  1.4  rmind 	if (benchmark == test && (stream && !interface)) {
    169  1.2  rmind 		usage();
    170  1.2  rmind 	}
    171  1.2  rmind 
    172  1.1  rmind 	/* XXX rn_init */
    173  1.1  rmind 	extern int rumpns_max_keylen;
    174  1.1  rmind 	rumpns_max_keylen = 1;
    175  1.1  rmind 
    176  1.1  rmind 	rump_init();
    177  1.1  rmind 	rump_schedule();
    178  1.1  rmind 
    179  1.5  rmind 	rumpns_npf_test_init();
    180  1.5  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.6  rmind 	fail = false;
    190  1.2  rmind 
    191  1.2  rmind 	if (test) {
    192  1.2  rmind 		ok = rumpns_npf_nbuf_test(verbose);
    193  1.6  rmind 		fail |= result("nbuf", ok);
    194  1.1  rmind 
    195  1.2  rmind 		ok = rumpns_npf_processor_test(verbose);
    196  1.6  rmind 		fail |= result("processor", ok);
    197  1.1  rmind 
    198  1.2  rmind 		ok = rumpns_npf_table_test(verbose);
    199  1.6  rmind 		fail |= result("table", ok);
    200  1.3  rmind 
    201  1.3  rmind 		ok = rumpns_npf_state_test(verbose);
    202  1.6  rmind 		fail |= result("state", ok);
    203  1.2  rmind 	}
    204  1.2  rmind 
    205  1.4  rmind 	if (test && config) {
    206  1.4  rmind 		ok = rumpns_npf_rule_test(verbose);
    207  1.6  rmind 		fail |= result("rule", ok);
    208  1.4  rmind 
    209  1.4  rmind 		ok = rumpns_npf_nat_test(verbose);
    210  1.6  rmind 		fail |= result("nat", ok);
    211  1.4  rmind 	}
    212  1.4  rmind 
    213  1.2  rmind 	if (stream) {
    214  1.2  rmind 		process_stream(stream, NULL, idx);
    215  1.2  rmind 	}
    216  1.1  rmind 
    217  1.1  rmind 	rump_unschedule();
    218  1.1  rmind 
    219  1.6  rmind 	return fail ? EXIT_FAILURE : EXIT_SUCCESS;
    220  1.1  rmind }
    221