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