corrected copyright notices
[gnutls.git] / tests / dtls / dtls-stress.c
blob7bad75181c3ddef3cdbbd1e126af4ca0a8a4682a
1 /*
2 * Copyright (C) 2012 Sean Buckheister
4 * This file is part of GnuTLS.
6 * GnuTLS is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuTLS is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GnuTLS; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 * DTLS stress test utility
24 * **** Available parameters ****
26 * -nb enable nonblocking operations on sessions
27 * -batch read test identifiers from stdin and run them
28 * -d increase debug level by one
29 * -d <n> set debug level to <n>
30 * -die don't start new tests after the first detected failure
31 * -timeout <n> set handshake timeout to <n> seconds. Tests that don't make progress
32 * within twice this time will be forcibly killed. (default: 120)
33 * -retransmit <n> set retransmit timeout to <n> milliseconds (default: 100)
34 * -j <n> run up to <n> tests in parallel
35 * -full use full handshake with mutual certificate authentication
36 * -shello <perm> run only one test, with the server hello flight permuted as <perm>
37 * -sfinished <perm> run only one test, with the server finished flight permuted as <perm>
38 * -cfinished <perm> run only one test, with the client finished flight permuted as <perm>
39 * <packet name> run only one test, drop <packet name> three times
40 * valid values for <packet name> are:
41 * SHello, SCertificate, SKeyExchange, SCertificateRequest, SHelloDone,
42 * CCertificate, CKeyExchange, CCertificateVerify, CChangeCipherSpec,
43 * CFinished, SChangeCipherSpec, SFinished
44 * using *Certificate* without -full will yield unexpected results
47 * **** Permutation handling ****
49 * Flight length for -sfinished is 2, for -shello and -cfinished they are 5 with -full, 3 otherwise.
50 * Permutations are given with base 0 and specify the order in which reordered packets are transmitted.
51 * For example, -full -shello 42130 will transmit server hello flight packets in the order
52 * SHelloDone, SKeyExchange, SCertificate, SCertificateRequest, SHello
55 * **** Output format ****
57 * Every line printed for any given test is prefixed by a unique id for that test. See run_test_by_id for
58 * exact composition. Errors encountered during execution are printed, with one status line after test
59 * completen. The format for this line is as follows:
61 * <id> <status> SHello(<shperm>), SFinished(<sfinperm>), CFinished(<cfinperm>) :- <drops>
63 * The format for error lines is <id> <role>| <text>, with <role> being the role of the child process
64 * that encountered the error, and <text> being obvious.
66 * <id> is the unique id for the test, it can be used as input to -batch.
67 * <status> can be ++ for a successful test, -- for a failure, TT for a deadlock timeout killed test,
68 * or !! for a test has died due to some unforeseen circumstances like syscall failures.
69 * <shperm>, <sfinperm>, <cfinperm> show the permutation for the respective flights used.
70 * They can be used as input to -shello, -sfinished, and -cfinished, respectively.
71 * <drops> is a comma separated list of <packet name>, one for every packet dropped thrice
74 * **** Exit status ****
76 * 0 all tests have passed
77 * 1 some tests have failed
78 * 4 the master processed has encountered unexpected errors
79 * 8 error parsing command line
82 #include <config.h>
83 #include <gnutls/gnutls.h>
84 #include <gnutls/openpgp.h>
85 #include <gnutls/dtls.h>
86 #include <unistd.h>
87 #include <sys/socket.h>
88 #include <sys/types.h>
89 #include <netinet/in.h>
90 #include <fcntl.h>
91 #include <stdio.h>
92 #include <stdlib.h>
93 #include <string.h>
94 #include <errno.h>
95 #include <poll.h>
96 #include <time.h>
97 #include <sys/wait.h>
99 #if _POSIX_TIMERS && (_POSIX_TIMERS - 200112L) >= 0
101 // {{{ types
103 typedef struct {
104 int count;
105 } filter_packet_state_t;
107 typedef struct {
108 gnutls_datum_t packets[5];
109 int* order;
110 int count;
111 } filter_permute_state_t;
113 typedef void (*filter_fn)(gnutls_transport_ptr_t, const unsigned char*, size_t);
115 typedef int (*match_fn)(const unsigned char*, size_t);
117 enum role { SERVER, CLIENT };
119 // }}}
121 // {{{ static data
123 static int permutations2[2][2]
124 = { { 0, 1 }, { 1, 0 } };
126 static const char* permutation_names2[]
127 = { "01", "10", 0 };
129 static int permutations3[6][3]
130 = { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 } };
132 static const char* permutation_names3[]
133 = { "012", "021", "102", "120", "201", "210", 0 };
135 static int permutations5[120][5]
136 = { { 0, 1, 2, 3, 4 }, { 0, 2, 1, 3, 4 }, { 1, 0, 2, 3, 4 }, { 1, 2, 0, 3, 4 }, { 2, 0, 1, 3, 4 }, { 2, 1, 0, 3, 4 },
137 { 0, 1, 3, 2, 4 }, { 0, 2, 3, 1, 4 }, { 1, 0, 3, 2, 4 }, { 1, 2, 3, 0, 4 }, { 2, 0, 3, 1, 4 }, { 2, 1, 3, 0, 4 },
138 { 0, 3, 1, 2, 4 }, { 0, 3, 2, 1, 4 }, { 1, 3, 0, 2, 4 }, { 1, 3, 2, 0, 4 }, { 2, 3, 0, 1, 4 }, { 2, 3, 1, 0, 4 },
139 { 3, 0, 1, 2, 4 }, { 3, 0, 2, 1, 4 }, { 3, 1, 0, 2, 4 }, { 3, 1, 2, 0, 4 }, { 3, 2, 0, 1, 4 }, { 3, 2, 1, 0, 4 },
140 { 0, 1, 2, 4, 3 }, { 0, 2, 1, 4, 3 }, { 1, 0, 2, 4, 3 }, { 1, 2, 0, 4, 3 }, { 2, 0, 1, 4, 3 }, { 2, 1, 0, 4, 3 },
141 { 0, 1, 3, 4, 2 }, { 0, 2, 3, 4, 1 }, { 1, 0, 3, 4, 2 }, { 1, 2, 3, 4, 0 }, { 2, 0, 3, 4, 1 }, { 2, 1, 3, 4, 0 },
142 { 0, 3, 1, 4, 2 }, { 0, 3, 2, 4, 1 }, { 1, 3, 0, 4, 2 }, { 1, 3, 2, 4, 0 }, { 2, 3, 0, 4, 1 }, { 2, 3, 1, 4, 0 },
143 { 3, 0, 1, 4, 2 }, { 3, 0, 2, 4, 1 }, { 3, 1, 0, 4, 2 }, { 3, 1, 2, 4, 0 }, { 3, 2, 0, 4, 1 }, { 3, 2, 1, 4, 0 },
144 { 0, 1, 4, 2, 3 }, { 0, 2, 4, 1, 3 }, { 1, 0, 4, 2, 3 }, { 1, 2, 4, 0, 3 }, { 2, 0, 4, 1, 3 }, { 2, 1, 4, 0, 3 },
145 { 0, 1, 4, 3, 2 }, { 0, 2, 4, 3, 1 }, { 1, 0, 4, 3, 2 }, { 1, 2, 4, 3, 0 }, { 2, 0, 4, 3, 1 }, { 2, 1, 4, 3, 0 },
146 { 0, 3, 4, 1, 2 }, { 0, 3, 4, 2, 1 }, { 1, 3, 4, 0, 2 }, { 1, 3, 4, 2, 0 }, { 2, 3, 4, 0, 1 }, { 2, 3, 4, 1, 0 },
147 { 3, 0, 4, 1, 2 }, { 3, 0, 4, 2, 1 }, { 3, 1, 4, 0, 2 }, { 3, 1, 4, 2, 0 }, { 3, 2, 4, 0, 1 }, { 3, 2, 4, 1, 0 },
148 { 0, 4, 1, 2, 3 }, { 0, 4, 2, 1, 3 }, { 1, 4, 0, 2, 3 }, { 1, 4, 2, 0, 3 }, { 2, 4, 0, 1, 3 }, { 2, 4, 1, 0, 3 },
149 { 0, 4, 1, 3, 2 }, { 0, 4, 2, 3, 1 }, { 1, 4, 0, 3, 2 }, { 1, 4, 2, 3, 0 }, { 2, 4, 0, 3, 1 }, { 2, 4, 1, 3, 0 },
150 { 0, 4, 3, 1, 2 }, { 0, 4, 3, 2, 1 }, { 1, 4, 3, 0, 2 }, { 1, 4, 3, 2, 0 }, { 2, 4, 3, 0, 1 }, { 2, 4, 3, 1, 0 },
151 { 3, 4, 0, 1, 2 }, { 3, 4, 0, 2, 1 }, { 3, 4, 1, 0, 2 }, { 3, 4, 1, 2, 0 }, { 3, 4, 2, 0, 1 }, { 3, 4, 2, 1, 0 },
152 { 4, 0, 1, 2, 3 }, { 4, 0, 2, 1, 3 }, { 4, 1, 0, 2, 3 }, { 4, 1, 2, 0, 3 }, { 4, 2, 0, 1, 3 }, { 4, 2, 1, 0, 3 },
153 { 4, 0, 1, 3, 2 }, { 4, 0, 2, 3, 1 }, { 4, 1, 0, 3, 2 }, { 4, 1, 2, 3, 0 }, { 4, 2, 0, 3, 1 }, { 4, 2, 1, 3, 0 },
154 { 4, 0, 3, 1, 2 }, { 4, 0, 3, 2, 1 }, { 4, 1, 3, 0, 2 }, { 4, 1, 3, 2, 0 }, { 4, 2, 3, 0, 1 }, { 4, 2, 3, 1, 0 },
155 { 4, 3, 0, 1, 2 }, { 4, 3, 0, 2, 1 }, { 4, 3, 1, 0, 2 }, { 4, 3, 1, 2, 0 }, { 4, 3, 2, 0, 1 }, { 4, 3, 2, 1, 0 } };
157 static const char* permutation_names5[]
158 = { "01234", "02134", "10234", "12034", "20134", "21034", "01324", "02314", "10324", "12304", "20314", "21304",
159 "03124", "03214", "13024", "13204", "23014", "23104", "30124", "30214", "31024", "31204", "32014", "32104",
160 "01243", "02143", "10243", "12043", "20143", "21043", "01342", "02341", "10342", "12340", "20341", "21340",
161 "03142", "03241", "13042", "13240", "23041", "23140", "30142", "30241", "31042", "31240", "32041", "32140",
162 "01423", "02413", "10423", "12403", "20413", "21403", "01432", "02431", "10432", "12430", "20431", "21430",
163 "03412", "03421", "13402", "13420", "23401", "23410", "30412", "30421", "31402", "31420", "32401", "32410",
164 "04123", "04213", "14023", "14203", "24013", "24103", "04132", "04231", "14032", "14230", "24031", "24130",
165 "04312", "04321", "14302", "14320", "24301", "24310", "34012", "34021", "34102", "34120", "34201", "34210",
166 "40123", "40213", "41023", "41203", "42013", "42103", "40132", "40231", "41032", "41230", "42031", "42130",
167 "40312", "40321", "41302", "41320", "42301", "42310", "43012", "43021", "43102", "43120", "43201", "43210", 0 };
169 static const char* filter_names[8]
170 = { "SHello",
171 "SKeyExchange",
172 "SHelloDone",
173 "CKeyExchange",
174 "CChangeCipherSpec",
175 "CFinished",
176 "SChangeCipherSpec",
177 "SFinished" };
179 static const char* filter_names_full[12]
180 = { "SHello",
181 "SCertificate",
182 "SKeyExchange",
183 "SCertificateRequest",
184 "SHelloDone",
185 "CCertificate",
186 "CKeyExchange",
187 "CCertificateVerify",
188 "CChangeCipherSpec",
189 "CFinished",
190 "SChangeCipherSpec",
191 "SFinished" };
193 static const unsigned char PUBKEY[] =
194 "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
195 "\n"
196 "mI0ETz0XRAEEAKXSU/tg2yGvoKf/r1pdzj7dnfPHeS+BRiT34763uUhibAbTgMkp\n"
197 "v44OlBPiAaZ54uuXVkz8e4pgvrBgQwIRtNp3xPaWF1CfC4F+V4LdZV8l8IG+AfES\n"
198 "K0GbfUS4q8vjnPJ0TyxnXE2KtbcRdzZzWBshJ8KChKwbH2vvrMrlmEeZABEBAAG0\n"
199 "CHRlc3Qga2V5iLgEEwECACIFAk89F0QCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B\n"
200 "AheAAAoJEMNjhmkfkLY9J/YD+wYZ2BD/0/c5gkkDP2NlVvrLGyFmEwQcR7DcaQYB\n"
201 "P3/Teq2gnscZ5Xm/z1qgGEpwmaVfVHY8mfEj8bYI8jAu0v1C1jCtJPUTmxf9tmkZ\n"
202 "QYFNR8T+F5Xae2XseOH70lSN/AEiW02BEBFlGBx0a3T30muFfqi/KawaE7KKn2e4\n"
203 "uNWvuI0ETz0XRAEEAKgZExsb7Lf9P3DmwJSvNVdkGVny7wr4/M1s0CDX20NkO7Y1\n"
204 "Ao9g+qFo5MlCOEuzjVaEYmM+rro7qyxmDKsaNIzZF1VN5UeYgPFyLcBK7C+QwUqw\n"
205 "1PUl/w4dFq8neQyqIPUVGRwQPlwpkkabRPNT3t/7KgDJvYzV9uu+cXCyfqErABEB\n"
206 "AAGInwQYAQIACQUCTz0XRAIbDAAKCRDDY4ZpH5C2PTBtBACVsR6l4HtuzQb5WFQt\n"
207 "sD/lQEk6BEY9aVfK957Oj+A4alGEGObToqVJFo/nq+P7aWExIXucJQRL8lYnC7u+\n"
208 "GjPVCun5TYzKMiryxHPkQr9NBx4hh8JjkDCc8nAgI3il49uPYkmsv70CgqJFFtT8\n"
209 "NfM+8fS537I+XA+hfjt20NUFIA==\n"
210 "=oD3a\n"
211 "-----END PGP PUBLIC KEY BLOCK-----\n";
213 static const unsigned char PRIVKEY[] =
214 "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
215 "\n"
216 "lQHYBE89F0QBBACl0lP7YNshr6Cn/69aXc4+3Z3zx3kvgUYk9+O+t7lIYmwG04DJ\n"
217 "Kb+ODpQT4gGmeeLrl1ZM/HuKYL6wYEMCEbTad8T2lhdQnwuBfleC3WVfJfCBvgHx\n"
218 "EitBm31EuKvL45zydE8sZ1xNirW3EXc2c1gbISfCgoSsGx9r76zK5ZhHmQARAQAB\n"
219 "AAP6A6VhRVi22MHE1YzQrTr8yvMSgwayynGcOjndHxdpEodferLx1Pp/BL+bT+ib\n"
220 "Qq7RZ363Xg/7I2rHJpenQYdkI5SI4KrXIV57p8G+isyTtsxU38SY84WoB5os8sfT\n"
221 "YhxG+edoTfDzXkRSWFB8EUjRaLa2b//nvLpxNRyqDSzzUxECAMtEnL5H/8gHbpZf\n"
222 "D98TSJVxdAl9rBAQaVMgrFgcU/IlmxCyVEh9eh/P261tefgOnyVcGFYHxdZvJ3td\n"
223 "miM+DNUCANDW1S9t7IiqflDpQIS2wGTZ/rLKPoE1F3285EaYAd0FQUq0O4/Nu31D\n"
224 "5pz/S7D+PfXn9oEZH3Dvl3EVIDyq4bUB+QEzFc3BsH2uueD3g42RoBfMGl6m3LI9\n"
225 "yWOnrUmIW+h9Fu8W9mcU6y82Q1G7OPIxA1me/Qtzo20lGQa8jAyzLhuit7QIdGVz\n"
226 "dCBrZXmIuAQTAQIAIgUCTz0XRAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA\n"
227 "CgkQw2OGaR+Qtj0n9gP7BhnYEP/T9zmCSQM/Y2VW+ssbIWYTBBxHsNxpBgE/f9N6\n"
228 "raCexxnleb/PWqAYSnCZpV9UdjyZ8SPxtgjyMC7S/ULWMK0k9RObF/22aRlBgU1H\n"
229 "xP4Xldp7Zex44fvSVI38ASJbTYEQEWUYHHRrdPfSa4V+qL8prBoTsoqfZ7i41a+d\n"
230 "AdgETz0XRAEEAKgZExsb7Lf9P3DmwJSvNVdkGVny7wr4/M1s0CDX20NkO7Y1Ao9g\n"
231 "+qFo5MlCOEuzjVaEYmM+rro7qyxmDKsaNIzZF1VN5UeYgPFyLcBK7C+QwUqw1PUl\n"
232 "/w4dFq8neQyqIPUVGRwQPlwpkkabRPNT3t/7KgDJvYzV9uu+cXCyfqErABEBAAEA\n"
233 "A/4wX+brqkGZQTv8lateHn3PRHM3O34nPjgiNeo/SV9EKZg1e1PdRx9ZTAJrGK9y\n"
234 "uZ03BKn7vZIy7fD4ufVzV/s/BaypVmvwjZud8fdMgsMQAJYtoMhozbOtUelCFpja\n"
235 "I1xAbDBx1PAAbS8Sh022/0jvOGnZhvkgZMG90z7AEANUYQIAwzywU087TcJk8Bzd\n"
236 "37JGWyE4f3iYFGA+r8BoIOrxvvgfUHKxdhG0gaT8SDeRAwNY6D43dCBZkG7Uel1F\n"
237 "x9MlLQIA3Goaz58hEN0fdm4TM7A8crtMB+f8/h87EneBgMl+Yj/3sklhyahR6Itm\n"
238 "lGuAAGTAOmD7i8OmS/a1ac5MtHAGtwH6A0B5GjaL8VnLQo4vFnuR7JuCQaLqGadV\n"
239 "mBmKxVHElduLf/VauBQPD5KZA+egpg+laJ4JLVXMmKIZGqRzopcIWZnKiJ8EGAEC\n"
240 "AAkFAk89F0QCGwwACgkQw2OGaR+Qtj0wbQQAlbEepeB7bs0G+VhULbA/5UBJOgRG\n"
241 "PWlXyveezo/gOGpRhBjm06KlSRaP56vj+2lhMSF7nCUES/JWJwu7vhoz1Qrp+U2M\n"
242 "yjIq8sRz5EK/TQceIYfCY5AwnPJwICN4pePbj2JJrL+9AoKiRRbU/DXzPvH0ud+y\n"
243 "PlwPoX47dtDVBSA=\n"
244 "=EVlv\n"
245 "-----END PGP PRIVATE KEY BLOCK-----\n";
247 // }}}
249 // {{{ other global state
251 enum role role;
253 #define role_name (role == SERVER ? "server" : "client")
255 int debug;
256 int nonblock;
257 int full;
258 int timeout_seconds;
259 int retransmit_milliseconds;
260 int run_to_end;
262 int run_id;
264 // }}}
266 // {{{ logging and error handling
268 static void logfn(int level, const char* s)
270 if (debug) {
271 fprintf(stdout, "%i %s|<%i> %s", run_id, role_name, level, s);
275 static void auditfn(gnutls_session_t session, const char* s)
277 if (debug) {
278 fprintf(stdout, "%i %s| %s", run_id, role_name, s);
282 static void drop(const char* packet)
284 if (debug) {
285 fprintf(stdout, "%i %s| dropping %s\n", run_id, role_name, packet);
289 static int _process_error(int loc, int code, int die)
291 if (code < 0 && (die || code != GNUTLS_E_AGAIN)) {
292 fprintf(stdout, "%i <%s tls> line %i: %s", run_id, role_name, loc, gnutls_strerror(code));
293 if (gnutls_error_is_fatal(code) || die) {
294 fprintf(stdout, " (fatal)\n");
295 exit(1);
296 } else {
297 fprintf(stdout, "\n");
300 return code;
303 #define die_on_error(code) _process_error(__LINE__, code, 1)
304 #define process_error(code) _process_error(__LINE__, code, 0)
306 static void _process_error_or_timeout(int loc, int err, time_t tdiff)
308 if (err < 0) {
309 if (err != GNUTLS_E_TIMEDOUT || tdiff >= 60) {
310 _process_error(loc, err, 0);
311 } else {
312 fprintf(stdout, "%i %s| line %i: {spurious timeout} (fatal)", run_id, role_name, loc);
313 exit(1);
318 #define process_error_or_timeout(code, tdiff) _process_error_or_timeout(__LINE__, code, tdiff)
320 static void rperror(const char* name)
322 fprintf(stdout, "%i %s| %s: %s\n", run_id, role_name, name, strerror(errno));
325 // }}}
327 // {{{ init, shared, and teardown code and data for packet stream filters
329 filter_packet_state_t state_packet_ServerHello = { 0 };
330 filter_packet_state_t state_packet_ServerCertificate = { 0 };
331 filter_packet_state_t state_packet_ServerKeyExchange = { 0 };
332 filter_packet_state_t state_packet_ServerCertificateRequest = { 0 };
333 filter_packet_state_t state_packet_ServerHelloDone = { 0 };
334 filter_packet_state_t state_packet_ClientCertificate = { 0 };
335 filter_packet_state_t state_packet_ClientKeyExchange = { 0 };
336 filter_packet_state_t state_packet_ClientCertificateVerify = { 0 };
337 filter_packet_state_t state_packet_ClientChangeCipherSpec = { 0 };
338 filter_packet_state_t state_packet_ClientFinished = { 0 };
339 filter_packet_state_t state_packet_ServerChangeCipherSpec = { 0 };
340 filter_packet_state_t state_packet_ServerFinished = { 0 };
342 filter_permute_state_t state_permute_ServerHello = { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 0, 0 };
343 filter_permute_state_t state_permute_ServerHelloFull = { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 0, 0 };
344 filter_permute_state_t state_permute_ServerFinished = { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 0, 0 };
345 filter_permute_state_t state_permute_ClientFinished = { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 0, 0 };
346 filter_permute_state_t state_permute_ClientFinishedFull = { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 0, 0 };
348 filter_fn filter_chain[32];
349 int filter_current_idx;
351 static void filter_permute_state_free_buffer(filter_permute_state_t* state)
353 unsigned int i;
355 for (i = 0; i < sizeof(state->packets) / sizeof(state->packets[0]); i++) {
356 free(state->packets[i].data);
357 state->packets[i].data = NULL;
361 static void filter_clear_state(void)
363 filter_current_idx = 0;
365 filter_permute_state_free_buffer(&state_permute_ServerHello);
366 filter_permute_state_free_buffer(&state_permute_ServerHelloFull);
367 filter_permute_state_free_buffer(&state_permute_ServerFinished);
368 filter_permute_state_free_buffer(&state_permute_ClientFinished);
369 filter_permute_state_free_buffer(&state_permute_ClientFinishedFull);
371 memset(&state_packet_ServerHello, 0, sizeof(state_packet_ServerHello));
372 memset(&state_packet_ServerCertificate, 0, sizeof(state_packet_ServerCertificate));
373 memset(&state_packet_ServerKeyExchange, 0, sizeof(state_packet_ServerKeyExchange));
374 memset(&state_packet_ServerCertificateRequest, 0, sizeof(state_packet_ServerCertificateRequest));
375 memset(&state_packet_ServerHelloDone, 0, sizeof(state_packet_ServerHelloDone));
376 memset(&state_packet_ClientCertificate, 0, sizeof(state_packet_ClientCertificate));
377 memset(&state_packet_ClientKeyExchange, 0, sizeof(state_packet_ClientKeyExchange));
378 memset(&state_packet_ClientCertificateVerify, 0, sizeof(state_packet_ClientCertificateVerify));
379 memset(&state_packet_ClientChangeCipherSpec, 0, sizeof(state_packet_ClientChangeCipherSpec));
380 memset(&state_packet_ClientFinished, 0, sizeof(state_packet_ClientFinished));
381 memset(&state_packet_ServerChangeCipherSpec, 0, sizeof(state_packet_ServerChangeCipherSpec));
382 memset(&state_packet_ServerFinished, 0, sizeof(state_packet_ServerFinished));
383 memset(&state_permute_ServerHello, 0, sizeof(state_permute_ServerHello));
384 memset(&state_permute_ServerHelloFull, 0, sizeof(state_permute_ServerHelloFull));
385 memset(&state_permute_ServerFinished, 0, sizeof(state_permute_ServerFinished));
386 memset(&state_permute_ClientFinished, 0, sizeof(state_permute_ClientFinished));
387 memset(&state_permute_ClientFinishedFull, 0, sizeof(state_permute_ClientFinishedFull));
390 static void filter_run_next(gnutls_transport_ptr_t fd,
391 const unsigned char* buffer, size_t len)
393 filter_fn fn = filter_chain[filter_current_idx];
394 filter_current_idx++;
395 if (fn) {
396 fn(fd, buffer, len);
397 } else {
398 send((intptr_t) fd, buffer, len, 0);
400 filter_current_idx--;
403 // }}}
405 // {{{ packet match functions
407 static int match_ServerHello(const unsigned char* buffer, size_t len)
409 return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 2;
412 static int match_ServerCertificate(const unsigned char* buffer, size_t len)
414 return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 11;
417 static int match_ServerKeyExchange(const unsigned char* buffer, size_t len)
419 return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 12;
422 static int match_ServerCertificateRequest(const unsigned char* buffer, size_t len)
424 return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 13;
427 static int match_ServerHelloDone(const unsigned char* buffer, size_t len)
429 return role == SERVER && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 14;
432 static int match_ClientCertificate(const unsigned char* buffer, size_t len)
434 return role == CLIENT && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 11;
437 static int match_ClientKeyExchange(const unsigned char* buffer, size_t len)
439 return role == CLIENT && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 16;
442 static int match_ClientCertificateVerify(const unsigned char* buffer, size_t len)
444 return role == CLIENT && len >= 13 + 1 && buffer[0] == 22 && buffer[13] == 15;
447 static int match_ClientChangeCipherSpec(const unsigned char* buffer, size_t len)
449 return role == CLIENT && len >= 13 && buffer[0] == 20;
452 static int match_ClientFinished(const unsigned char* buffer, size_t len)
454 return role == CLIENT && len >= 13 && buffer[0] == 22 && buffer[4] == 1;
457 static int match_ServerChangeCipherSpec(const unsigned char* buffer, size_t len)
459 return role == SERVER && len >= 13 && buffer[0] == 20;
462 static int match_ServerFinished(const unsigned char* buffer, size_t len)
464 return role == SERVER && len >= 13 && buffer[0] == 22 && buffer[4] == 1;
467 // }}}
469 // {{{ packet drop filters
471 #define FILTER_DROP_COUNT 3
472 #define DECLARE_FILTER(packet) \
473 static void filter_packet_##packet(gnutls_transport_ptr_t fd, \
474 const unsigned char* buffer, size_t len) \
476 if (match_##packet(buffer, len) && (state_packet_##packet).count++ < FILTER_DROP_COUNT) { \
477 drop(#packet); \
478 } else { \
479 filter_run_next(fd, buffer, len); \
483 DECLARE_FILTER(ServerHello)
484 DECLARE_FILTER(ServerCertificate)
485 DECLARE_FILTER(ServerKeyExchange)
486 DECLARE_FILTER(ServerCertificateRequest)
487 DECLARE_FILTER(ServerHelloDone)
488 DECLARE_FILTER(ClientCertificate)
489 DECLARE_FILTER(ClientKeyExchange)
490 DECLARE_FILTER(ClientCertificateVerify)
491 DECLARE_FILTER(ClientChangeCipherSpec)
492 DECLARE_FILTER(ClientFinished)
493 DECLARE_FILTER(ServerChangeCipherSpec)
494 DECLARE_FILTER(ServerFinished)
496 // }}}
498 // {{{ flight permutation filters
500 static void filter_permute_state_run(filter_permute_state_t* state, int packetCount,
501 gnutls_transport_ptr_t fd, const unsigned char* buffer, size_t len)
503 unsigned char* data = malloc(len);
504 int packet = state->order[state->count];
506 memcpy(data, buffer, len);
507 state->packets[packet].data = data;
508 state->packets[packet].size = len;
509 state->count++;
511 if (state->count == packetCount) {
512 for (packet = 0; packet < packetCount; packet++) {
513 filter_run_next(fd, state->packets[packet].data,
514 state->packets[packet].size);
516 filter_permute_state_free_buffer(state);
517 state->count = 0;
521 #define DECLARE_PERMUTE(flight) \
522 static void filter_permute_##flight(gnutls_transport_ptr_t fd, \
523 const unsigned char* buffer, size_t len) \
525 int count = sizeof(permute_match_##flight) / sizeof(permute_match_##flight[0]); \
526 int i; \
527 for (i = 0; i < count; i++) { \
528 if (permute_match_##flight[i](buffer, len)) { \
529 filter_permute_state_run(&state_permute_##flight, count, fd, buffer, len); \
530 return; \
533 filter_run_next(fd, buffer, len); \
536 static match_fn permute_match_ServerHello[] = { match_ServerHello, match_ServerKeyExchange, match_ServerHelloDone };
537 static match_fn permute_match_ServerHelloFull[] = { match_ServerHello, match_ServerCertificate, match_ServerKeyExchange,
538 match_ServerCertificateRequest, match_ServerHelloDone };
539 static match_fn permute_match_ServerFinished[] = { match_ServerChangeCipherSpec, match_ServerFinished };
540 static match_fn permute_match_ClientFinished[] = { match_ClientKeyExchange, match_ClientChangeCipherSpec, match_ClientFinished };
541 static match_fn permute_match_ClientFinishedFull[] = { match_ClientCertificate, match_ClientKeyExchange,
542 match_ClientCertificateVerify, match_ClientChangeCipherSpec, match_ClientFinished };
544 DECLARE_PERMUTE(ServerHello)
545 DECLARE_PERMUTE(ServerHelloFull)
546 DECLARE_PERMUTE(ServerFinished)
547 DECLARE_PERMUTE(ClientFinished)
548 DECLARE_PERMUTE(ClientFinishedFull)
550 // }}}
552 // {{{ emergency deadlock resolution time bomb
554 timer_t killtimer_tid = 0;
556 static void killtimer_set(void)
558 struct sigevent sig;
559 struct itimerspec tout = { { 0, 0 }, { 2 * timeout_seconds, 0 } };
561 if (killtimer_tid != 0) {
562 timer_delete(killtimer_tid);
565 memset(&sig, 0, sizeof(sig));
566 sig.sigev_notify = SIGEV_SIGNAL;
567 sig.sigev_signo = 15;
568 if (timer_create(CLOCK_MONOTONIC, &sig, &killtimer_tid) < 0) {
569 rperror("timer_create");
570 exit(3);
573 timer_settime(killtimer_tid, 0, &tout, 0);
576 // }}}
578 // {{{ actual gnutls operations
580 gnutls_certificate_credentials_t cred;
581 gnutls_session_t session;
583 static ssize_t writefn(gnutls_transport_ptr_t fd, const void* buffer, size_t len)
585 filter_run_next(fd, (const unsigned char*) buffer, len);
586 return len;
589 static void await(int fd, int timeout)
591 if (nonblock) {
592 struct pollfd p = { fd, POLLIN, 0 };
593 if (poll(&p, 1, timeout) < 0 && errno != EAGAIN && errno != EINTR) {
594 rperror("poll");
595 exit(3);
600 static void cred_init(void)
602 gnutls_datum_t key = { (unsigned char*) PUBKEY, sizeof(PUBKEY) };
603 gnutls_datum_t sec = { (unsigned char*) PRIVKEY, sizeof(PRIVKEY) };
605 gnutls_certificate_allocate_credentials(&cred);
607 gnutls_certificate_set_openpgp_key_mem(cred, &key, &sec, GNUTLS_OPENPGP_FMT_BASE64);
610 static void session_init(int sock, int server)
612 gnutls_init(&session, GNUTLS_DATAGRAM | (server ? GNUTLS_SERVER : GNUTLS_CLIENT)
613 | GNUTLS_NONBLOCK * nonblock);
614 gnutls_priority_set_direct(session, "+CTYPE-OPENPGP:+CIPHER-ALL:+MAC-ALL:+ECDHE-RSA:+ANON-ECDH", 0);
615 gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) (intptr_t) sock);
617 if (full) {
618 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
619 if (server) {
620 gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE);
622 } else if (server) {
623 gnutls_anon_server_credentials_t cred;
624 gnutls_anon_allocate_server_credentials(&cred);
625 gnutls_credentials_set(session, GNUTLS_CRD_ANON, cred);
626 } else {
627 gnutls_anon_client_credentials_t cred;
628 gnutls_anon_allocate_client_credentials(&cred);
629 gnutls_credentials_set(session, GNUTLS_CRD_ANON, cred);
632 gnutls_transport_set_push_function(session, writefn);
634 gnutls_dtls_set_mtu(session, 1400);
635 gnutls_dtls_set_timeouts(session, retransmit_milliseconds, timeout_seconds * 1000);
638 static void client(int sock)
640 int err = 0;
641 time_t started = time(0);
642 const char* line = "foobar!";
643 char buffer[8192];
644 int len;
646 session_init(sock, 0);
648 killtimer_set();
649 do {
650 err = process_error(gnutls_handshake(session));
651 if (err != 0) {
652 int t = gnutls_dtls_get_timeout(session);
653 await(sock, t ? t : 100);
655 } while (err != 0);
656 process_error_or_timeout(err, time(0) - started);
658 killtimer_set();
659 die_on_error(gnutls_record_send(session, line, strlen(line)));
661 do {
662 await(sock, -1);
663 len = process_error(gnutls_record_recv(session, buffer, sizeof(buffer)));
664 } while (len < 0);
666 if (len > 0 && strncmp(line, buffer, len) == 0) {
667 exit(0);
668 } else {
669 exit(1);
673 static void server(int sock)
675 int err;
676 time_t started = time(0);
677 char buffer[8192];
678 int len;
680 session_init(sock, 1);
682 await(sock, -1);
684 killtimer_set();
685 do {
686 err = process_error(gnutls_handshake(session));
687 if (err != 0) {
688 int t = gnutls_dtls_get_timeout(session);
689 await(sock, t ? t : 100);
691 } while (err != 0);
692 process_error_or_timeout(err, time(0) - started);
694 killtimer_set();
695 do {
696 await(sock, -1);
697 len = process_error(gnutls_record_recv(session, buffer, sizeof(buffer)));
698 } while (len < 0);
700 die_on_error(gnutls_record_send(session, buffer, len));
701 exit(0);
704 // }}}
706 // {{{ test running/handling itself
708 #if 0
709 static void udp_sockpair(int* socks)
711 struct sockaddr_in6 sa = { AF_INET6, htons(30000), 0, in6addr_loopback, 0 };
712 struct sockaddr_in6 sb = { AF_INET6, htons(20000), 0, in6addr_loopback, 0 };
714 socks[0] = socket(AF_INET6, SOCK_DGRAM, 0);
715 socks[1] = socket(AF_INET6, SOCK_DGRAM, 0);
717 bind(socks[0], (struct sockaddr*) &sa, sizeof(sa));
718 bind(socks[1], (struct sockaddr*) &sb, sizeof(sb));
720 connect(socks[1], (struct sockaddr*) &sa, sizeof(sa));
721 connect(socks[0], (struct sockaddr*) &sb, sizeof(sb));
723 #endif
725 static int run_test(void)
727 int fds[2];
728 int pid1, pid2;
729 int status2;
731 if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds) < 0) {
732 rperror("socketpair");
733 exit(2);
736 if (nonblock) {
737 fcntl(fds[0], F_SETFL, (long) O_NONBLOCK);
738 fcntl(fds[1], F_SETFL, (long) O_NONBLOCK);
741 if (!(pid1 = fork())) {
742 role = SERVER;
743 server(fds[1]); // noreturn
744 } else if (pid1 < 0) {
745 rperror("fork server");
746 exit(2);
748 if (!(pid2 = fork())) {
749 role = CLIENT;
750 client(fds[0]); // noreturn
751 } else if (pid2 < 0) {
752 rperror("fork client");
753 exit(2);
755 while (waitpid(pid2, &status2, 0) < 0 && errno == EINTR);
756 kill(pid1, 15);
757 while (waitpid(pid1, 0, 0) < 0 && errno == EINTR);
759 close(fds[0]);
760 close(fds[1]);
762 if (!WIFSIGNALED(status2) && WEXITSTATUS(status2) != 3) {
763 return !!WEXITSTATUS(status2);
764 } else {
765 return 3;
769 static filter_fn filters[8]
770 = { filter_packet_ServerHello,
771 filter_packet_ServerKeyExchange,
772 filter_packet_ServerHelloDone,
773 filter_packet_ClientKeyExchange,
774 filter_packet_ClientChangeCipherSpec,
775 filter_packet_ClientFinished,
776 filter_packet_ServerChangeCipherSpec,
777 filter_packet_ServerFinished };
779 static filter_fn filters_full[12]
780 = { filter_packet_ServerHello,
781 filter_packet_ServerCertificate,
782 filter_packet_ServerKeyExchange,
783 filter_packet_ServerCertificateRequest,
784 filter_packet_ServerHelloDone,
785 filter_packet_ClientCertificate,
786 filter_packet_ClientKeyExchange,
787 filter_packet_ClientCertificateVerify,
788 filter_packet_ClientChangeCipherSpec,
789 filter_packet_ClientFinished,
790 filter_packet_ServerChangeCipherSpec,
791 filter_packet_ServerFinished };
793 static int run_one_test(int dropMode, int serverFinishedPermute, int serverHelloPermute, int clientFinishedPermute)
795 int fnIdx = 0;
796 int res, filterIdx;
797 filter_fn* local_filters = full ? filters_full : filters;
798 const char** local_filter_names = full ? filter_names_full : filter_names;
799 const char** permutation_namesX = full ? permutation_names5 : permutation_names3;
800 int filter_count = full ? 12 : 8;
801 run_id = ((dropMode * 2 + serverFinishedPermute) * (full ? 120 : 6) + serverHelloPermute) * (full ? 120 : 6) + clientFinishedPermute;
803 filter_clear_state();
805 if (full) {
806 filter_chain[fnIdx++] = filter_permute_ServerHelloFull;
807 state_permute_ServerHelloFull.order = permutations5[serverHelloPermute];
809 filter_chain[fnIdx++] = filter_permute_ClientFinishedFull;
810 state_permute_ClientFinishedFull.order = permutations5[clientFinishedPermute];
811 } else {
812 filter_chain[fnIdx++] = filter_permute_ServerHello;
813 state_permute_ServerHello.order = permutations3[serverHelloPermute];
815 filter_chain[fnIdx++] = filter_permute_ClientFinished;
816 state_permute_ClientFinished.order = permutations3[clientFinishedPermute];
819 filter_chain[fnIdx++] = filter_permute_ServerFinished;
820 state_permute_ServerFinished.order = permutations2[serverFinishedPermute];
822 if (dropMode) {
823 for (filterIdx = 0; filterIdx < filter_count; filterIdx++) {
824 if (dropMode & (1 << filterIdx)) {
825 filter_chain[fnIdx++] = local_filters[filterIdx];
829 filter_chain[fnIdx++] = NULL;
831 res = run_test();
833 switch (res) {
834 case 0:
835 fprintf(stdout, "%i ++ ", run_id);
836 break;
837 case 1:
838 fprintf(stdout, "%i -- ", run_id);
839 break;
840 case 2:
841 fprintf(stdout, "%i !! ", run_id);
842 break;
843 case 3:
844 fprintf(stdout, "%i TT ", run_id);
845 break;
848 fprintf(stdout, "SHello(%s), ", permutation_namesX[serverHelloPermute]);
849 fprintf(stdout, "SFinished(%s), ", permutation_names2[serverFinishedPermute]);
850 fprintf(stdout, "CFinished(%s) :- ", permutation_namesX[clientFinishedPermute]);
851 if (dropMode) {
852 for (filterIdx = 0; filterIdx < filter_count; filterIdx++) {
853 if (dropMode & (1 << filterIdx)) {
854 if (dropMode & ((1 << filterIdx) - 1)) {
855 fprintf(stdout, ", ");
857 fprintf(stdout, "%s", local_filter_names[filterIdx]);
861 fprintf(stdout, "\n");
863 return res;
866 static int run_test_by_id(int id)
868 int pscale = full ? 120 : 6;
869 int dropMode, serverFinishedPermute, serverHelloPermute, clientFinishedPermute;
871 clientFinishedPermute = id % pscale;
872 id /= pscale;
874 serverHelloPermute = id % pscale;
875 id /= pscale;
877 serverFinishedPermute = id % 2;
878 id /= 2;
880 dropMode = id;
882 return run_one_test(dropMode, serverFinishedPermute, serverHelloPermute, clientFinishedPermute);
885 int* job_pids;
886 int job_limit;
887 int children = 0;
889 static void register_child(int pid)
891 int idx;
893 children++;
894 for (idx = 0; idx < job_limit; idx++) {
895 if (job_pids[idx] == 0) {
896 job_pids[idx] = pid;
897 return;
902 static int wait_children(int child_limit)
904 int fail = 0;
905 int result = 1;
907 while (children > child_limit) {
908 int status;
909 int idx;
910 int pid = waitpid(0, &status, 0);
911 if (pid < 0 && errno == ECHILD) {
912 break;
914 for (idx = 0; idx < job_limit; idx++) {
915 if (job_pids[idx] == pid) {
916 children--;
917 if (WEXITSTATUS(status)) {
918 result = 1;
919 if (!run_to_end && !fail) {
920 fprintf(stderr, "One test failed, waiting for remaining tests\n");
921 fail = 1;
922 child_limit = 0;
925 job_pids[idx] = 0;
926 break;
931 if (fail) {
932 exit(1);
935 return result;
938 static int run_tests_from_id_list(int childcount)
940 int test_id;
941 int ret;
942 int result = 0;
944 while ((ret = fscanf(stdin, "%i\n", &test_id)) > 0) {
945 int pid;
946 if (test_id < 0 || test_id > 2 * (full ? 120 * 120 * (1 << 12) : 6 * 6 * 256)) {
947 fprintf(stderr, "Invalid test id %i\n", test_id);
948 break;
950 if (!(pid = fork())) {
951 exit(run_test_by_id(test_id));
952 } else if (pid < 0) {
953 rperror("fork");
954 result = 4;
955 break;
956 } else {
957 register_child(pid);
958 result |= wait_children(childcount);
962 if (ret < 0 && ret != EOF) {
963 fprintf(stderr, "Error reading test id list\n");
966 result |= wait_children(0);
968 return result;
971 static int run_all_tests(int childcount)
973 int dropMode, serverFinishedPermute, serverHelloPermute, clientFinishedPermute;
974 int result = 0;
976 for (dropMode = 0; dropMode != 1 << (full ? 12 : 8); dropMode++)
977 for (serverFinishedPermute = 0; serverFinishedPermute < 2; serverFinishedPermute++)
978 for (serverHelloPermute = 0; serverHelloPermute < (full ? 120 : 6); serverHelloPermute++)
979 for (clientFinishedPermute = 0; clientFinishedPermute < (full ? 120 : 6); clientFinishedPermute++) {
980 int pid;
981 if (!(pid = fork())) {
982 exit(run_one_test(dropMode, serverFinishedPermute, serverHelloPermute, clientFinishedPermute));
983 } else if (pid < 0) {
984 rperror("fork");
985 result = 4;
986 break;
987 } else {
988 register_child(pid);
989 result |= wait_children(childcount);
993 result |= wait_children(0);
995 return result;
998 // }}}
1000 static int parse_permutation(const char* arg, const char* permutations[], int* val)
1002 *val = 0;
1003 while (permutations[*val]) {
1004 if (strcmp(permutations[*val], arg) == 0) {
1005 return 1;
1006 } else {
1007 *val += 1;
1010 return 0;
1013 int main(int argc, const char* argv[])
1015 int dropMode = 0;
1016 int serverFinishedPermute = 0;
1017 int serverHelloPermute = 0;
1018 int clientFinishedPermute = 0;
1019 int batch = 0;
1020 int arg;
1022 nonblock = 0;
1023 debug = 0;
1024 timeout_seconds = 120;
1025 retransmit_milliseconds = 100;
1026 full = 0;
1027 run_to_end = 1;
1028 job_limit = 1;
1030 #define NEXT_ARG(name) \
1031 do { \
1032 if (++arg >= argc) { \
1033 fprintf(stderr, "No argument for -" #name "\n"); \
1034 exit(8); \
1036 } while (0);
1037 #define FAIL_ARG(name) \
1038 do { \
1039 fprintf(stderr, "Invalid argument for -" #name "\n"); \
1040 exit(8); \
1041 } while (0);
1043 for (arg = 1; arg < argc; arg++) {
1044 if (strcmp("-die", argv[arg]) == 0) {
1045 run_to_end = 0;
1046 } else if (strcmp("-batch", argv[arg]) == 0) {
1047 batch = 1;
1048 } else if (strcmp("-d", argv[arg]) == 0) {
1049 char* end;
1050 int level = strtol(argv[arg+1], &end, 10);
1051 if (*end == '\0') {
1052 debug = level;
1053 arg++;
1054 } else {
1055 debug++;
1057 } else if (strcmp("-nb", argv[arg]) == 0) {
1058 nonblock = 1;
1059 } else if (strcmp("-timeout", argv[arg]) == 0) {
1060 char* end;
1061 int val;
1063 NEXT_ARG(timeout);
1064 val = strtol(argv[arg], &end, 10);
1065 if (*end == '\0') {
1066 timeout_seconds = val;
1067 } else {
1068 FAIL_ARG(timeout);
1070 } else if (strcmp("-retransmit", argv[arg]) == 0) {
1071 char* end;
1072 int val;
1074 NEXT_ARG(retransmit);
1075 val = strtol(argv[arg], &end, 10);
1076 if (*end == '\0') {
1077 retransmit_milliseconds = val;
1078 } else {
1079 FAIL_ARG(retransmit);
1081 } else if (strcmp("-j", argv[arg]) == 0) {
1082 char* end;
1083 int val;
1085 NEXT_ARG(timeout);
1086 val = strtol(argv[arg], &end, 10);
1087 if (*end == '\0') {
1088 job_limit = val;
1089 } else {
1090 FAIL_ARG(j);
1092 } else if (strcmp("-full", argv[arg]) == 0) {
1093 full = 1;
1094 } else if (strcmp("-shello", argv[arg]) == 0) {
1095 NEXT_ARG(shello);
1096 if (!parse_permutation(argv[arg], full ? permutation_names5 : permutation_names3, &serverHelloPermute)) {
1097 FAIL_ARG(shell);
1099 } else if (strcmp("-sfinished", argv[arg]) == 0) {
1100 NEXT_ARG(sfinished);
1101 if (!parse_permutation(argv[arg], permutation_names2, &serverFinishedPermute)) {
1102 FAIL_ARG(sfinished);
1104 } else if (strcmp("-cfinished", argv[arg]) == 0) {
1105 NEXT_ARG(cfinished);
1106 if (!parse_permutation(argv[arg], full ? permutation_names5 : permutation_names3, &clientFinishedPermute)) {
1107 FAIL_ARG(cfinished);
1109 } else {
1110 int drop;
1111 int filter_count = full ? 12 : 8;
1112 const char** local_filter_names = full ? filter_names_full : filter_names;
1113 for (drop = 0; drop < filter_count; drop++) {
1114 if (strcmp(local_filter_names[drop], argv[arg]) == 0) {
1115 dropMode |= (1 << drop);
1116 break;
1119 if (drop == filter_count) {
1120 fprintf(stderr, "Unknown packet %s\n", argv[arg]);
1121 exit(8);
1126 setlinebuf(stdout);
1127 gnutls_global_init();
1128 cred_init();
1129 gnutls_global_set_log_function(logfn);
1130 gnutls_global_set_audit_log_function(auditfn);
1131 gnutls_global_set_log_level(debug);
1133 if (dropMode || serverFinishedPermute || serverHelloPermute || clientFinishedPermute) {
1134 return run_one_test(dropMode, serverFinishedPermute, serverHelloPermute, clientFinishedPermute);
1135 } else {
1136 job_pids = calloc(sizeof(int), job_limit);
1137 if (batch) {
1138 return run_tests_from_id_list(job_limit);
1139 } else {
1140 return run_all_tests(job_limit);
1145 // vim: foldmethod=marker
1147 #else /* NO POSIX TIMERS */
1149 int main(int argc, const char* argv[])
1151 exit(77);
1154 #endif