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