Home | History | Annotate | Line # | Download | only in npftest
npftest.c revision 1.2
      1 /*	$NetBSD: npftest.c,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
      2 
      3 /*
      4  * NPF testing framework.
      5  *
      6  * Public Domain.
      7  */
      8 
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <stdbool.h>
     12 #include <string.h>
     13 #include <unistd.h>
     14 #include <assert.h>
     15 #include <fcntl.h>
     16 #include <err.h>
     17 
     18 #include <sys/ioctl.h>
     19 #include <net/if.h>
     20 #include <arpa/inet.h>
     21 
     22 #include <rump/rump.h>
     23 #include <rump/rump_syscalls.h>
     24 
     25 #include "npftest.h"
     26 
     27 static bool verbose, quiet;
     28 
     29 static void
     30 usage(void)
     31 {
     32 	printf("usage: %s: [ -q | -v ] [ -c <config> ] "
     33 	    "[ -i 'interfaces' ] < -b | -t | -s file >\n"
     34 	    "\t-b: benchmark\n"
     35 	    "\t-t: regression test\n"
     36 	    "\t-c <config>: NPF configuration file\n"
     37 	    "\t-i 'interfaces': interfaces to create\n"
     38 	    "\t-q: quiet mode\n"
     39 	    "\t-s <file>: pcap stream\n"
     40 	    "\t-v: verbose mode\n",
     41 	    getprogname());
     42 	exit(EXIT_FAILURE);
     43 }
     44 
     45 static void
     46 result(const char *testcase, bool ok)
     47 {
     48 	if (!quiet) {
     49 		printf("NPF %-10s\t%s\n", testcase, ok ? "OK" : "fail");
     50 	}
     51 	if (verbose) {
     52 		puts("-----");
     53 	}
     54 	if (!ok) {
     55 		exit(EXIT_FAILURE);
     56 	}
     57 }
     58 
     59 #if 0
     60 static void
     61 construct_interfaces(char *ifs)
     62 {
     63 	char *ifname, *addr, *mask, *sptr;
     64 
     65 	/*
     66 	 * Format: ifname0[,ip0,mask1];ifname1,...
     67 	 */
     68 	ifname = strtok_r(ifs, ";", &sptr);
     69 	while (ifname) {
     70 		/* Address and netmask. */
     71 		addr = strchr(ifname, ',');
     72 		if (addr) {
     73 			*addr++ = '\0';
     74 		}
     75 		mask = strchr(addr, ',');
     76 		if (mask) {
     77 			*mask++ = '\0';
     78 		}
     79 
     80 		/* Construct; next.. */
     81 		setup_rump_if(ifname, addr, mask);
     82 		ifname = strtok_r(NULL, ";", &sptr);
     83 	}
     84 }
     85 #endif
     86 
     87 static void
     88 load_npf_config(const char *config)
     89 {
     90 	prop_dictionary_t npf_dict;
     91 	void *xml;
     92 	int error;
     93 
     94 	npf_dict = prop_dictionary_internalize_from_file(config);
     95 	if (!npf_dict) {
     96 		err(EXIT_FAILURE, "prop_dictionary_internalize_from_file");
     97 	}
     98 	xml = prop_dictionary_externalize(npf_dict);
     99 	prop_object_release(npf_dict);
    100 
    101 	error = rumpns_npf_test_load(xml);
    102 	if (error) {
    103 		errx(EXIT_FAILURE, "npf_test_load: %s\n", strerror(error));
    104 	}
    105 	free(xml);
    106 
    107 	if (verbose) {
    108 		printf("Loaded NPF config at '%s'\n", config);
    109 	}
    110 }
    111 
    112 int
    113 main(int argc, char **argv)
    114 {
    115 	bool benchmark, test, ok;
    116 	char *config, *interfaces, *stream;
    117 	int ch;
    118 
    119 	benchmark = false;
    120 	test = false;
    121 
    122 	config = NULL;
    123 	interfaces = NULL;
    124 	stream = NULL;
    125 
    126 	verbose = false;
    127 	quiet = false;
    128 
    129 	while ((ch = getopt(argc, argv, "bqvc:i:s:t")) != -1) {
    130 		switch (ch) {
    131 		case 'b':
    132 			benchmark = true;
    133 			break;
    134 		case 'q':
    135 			quiet = true;
    136 			break;
    137 		case 'v':
    138 			verbose = true;
    139 			break;
    140 		case 'c':
    141 			config = optarg;
    142 			break;
    143 		case 'i':
    144 			interfaces = optarg;
    145 			break;
    146 		case 's':
    147 			stream = optarg;
    148 			break;
    149 		case 't':
    150 			test = true;
    151 			break;
    152 		default:
    153 			usage();
    154 		}
    155 	}
    156 
    157 	/* Either benchmark or test. */
    158 	if (benchmark == test && (!stream || !interfaces)) {
    159 		usage();
    160 	}
    161 
    162 	/* XXX rn_init */
    163 	extern int rumpns_max_keylen;
    164 	rumpns_max_keylen = 1;
    165 
    166 	rump_init();
    167 	rump_schedule();
    168 
    169 	if (config) {
    170 		load_npf_config(config);
    171 	}
    172 
    173 	if (test) {
    174 		ok = rumpns_npf_nbuf_test(verbose);
    175 		result("nbuf", ok);
    176 
    177 		ok = rumpns_npf_processor_test(verbose);
    178 		result("processor", ok);
    179 
    180 		ok = rumpns_npf_table_test(verbose);
    181 		result("table", ok);
    182 	}
    183 
    184 	if (stream) {
    185 		unsigned idx = if_nametoindex(interfaces);
    186 		if (idx == 0) {
    187 			err(EXIT_FAILURE, "if_nametoindex");
    188 		} else if (verbose) {
    189 			printf("Interface %s index %u\n", interfaces, idx);
    190 		}
    191 		process_stream(stream, NULL, idx);
    192 	}
    193 
    194 	rump_unschedule();
    195 
    196 	return EXIT_SUCCESS;
    197 }
    198