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