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