Annotation of embedaddon/strongswan/src/libstrongswan/tests/suites/test_proposal.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2016-2018 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "test_suite.h"
17:
18: #include <crypto/proposal/proposal.h>
19:
20: static struct {
21: protocol_id_t proto;
22: char *proposal;
23: char *expected;
24: } create_data[] = {
25: { PROTO_IKE, "", NULL },
26: { PROTO_IKE, "sha256", NULL },
27: { PROTO_IKE, "sha256-modp3072", NULL },
28: { PROTO_IKE, "null-sha256-modp3072", "IKE:NULL/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072" },
29: { PROTO_IKE, "aes128", NULL },
30: { PROTO_IKE, "aes128-sha256", NULL },
31: { PROTO_IKE, "aes128-sha256-modpnone", NULL },
32: { PROTO_IKE, "aes128-prfsha256", NULL },
33: { PROTO_IKE, "aes128-prfsha256-modp2048", NULL },
34: { PROTO_IKE, "aes128-sha256-modp3072", "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072" },
35: { PROTO_IKE, "aes128-sha256-prfsha384-modp3072", "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_384/MODP_3072" },
36: { PROTO_IKE, "aes128gcm16-modp3072", NULL },
37: { PROTO_IKE, "aes128gcm16-prfsha256-modp3072", "IKE:AES_GCM_16_128/PRF_HMAC_SHA2_256/MODP_3072" },
38: { PROTO_IKE, "aes128gcm16-sha256-modp3072", "IKE:AES_GCM_16_128/PRF_HMAC_SHA2_256/MODP_3072" },
39: { PROTO_IKE, "aes128gcm16-aes128-modp3072", NULL },
40: { PROTO_IKE, "aes128gcm16-aes128-sha256-modp3072", NULL },
41: { PROTO_ESP, "", NULL },
42: { PROTO_ESP, "sha256", NULL },
43: { PROTO_ESP, "aes128-sha256", "ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ" },
44: { PROTO_ESP, "aes128-sha256-esn", "ESP:AES_CBC_128/HMAC_SHA2_256_128/EXT_SEQ" },
45: { PROTO_ESP, "aes128-sha256-noesn", "ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ" },
46: { PROTO_ESP, "aes128-sha256-esn-noesn", "ESP:AES_CBC_128/HMAC_SHA2_256_128/EXT_SEQ/NO_EXT_SEQ" },
47: { PROTO_ESP, "aes128-sha256-prfsha256-modp3072", "ESP:AES_CBC_128/HMAC_SHA2_256_128/MODP_3072/NO_EXT_SEQ" },
48: { PROTO_ESP, "aes128gcm16-aes128-sha256-modp3072", NULL },
49: { PROTO_ESP, "aes128gmac", "ESP:NULL_AES_GMAC_128/NO_EXT_SEQ" },
50: { PROTO_AH, "", NULL },
51: { PROTO_AH, "aes128", NULL },
52: { PROTO_AH, "aes128-sha256", "AH:HMAC_SHA2_256_128/NO_EXT_SEQ" },
53: { PROTO_AH, "sha256-sha1", "AH:HMAC_SHA2_256_128/HMAC_SHA1_96/NO_EXT_SEQ" },
54: { PROTO_AH, "aes128gmac-sha256", "AH:AES_128_GMAC/HMAC_SHA2_256_128/NO_EXT_SEQ" },
55: { PROTO_AH, "aes128gmac-sha256-prfsha256", "AH:AES_128_GMAC/HMAC_SHA2_256_128/NO_EXT_SEQ" },
56: { PROTO_AH, "aes128gmac-aes256gmac-aes128-sha256", "AH:AES_128_GMAC/AES_256_GMAC/HMAC_SHA2_256_128/NO_EXT_SEQ" },
57: { PROTO_AH, "sha256-esn", "AH:HMAC_SHA2_256_128/EXT_SEQ" },
58: { PROTO_AH, "sha256-noesn", "AH:HMAC_SHA2_256_128/NO_EXT_SEQ" },
59: { PROTO_AH, "sha256-esn-noesn", "AH:HMAC_SHA2_256_128/EXT_SEQ/NO_EXT_SEQ" },
60: };
61:
62: static void assert_proposal_eq(proposal_t *proposal, char *expected)
63: {
64: char str[BUF_LEN];
65:
66: if (!expected)
67: {
68: ck_assert(!proposal);
69: return;
70: }
71: snprintf(str, sizeof(str), "%P", proposal);
72: ck_assert_str_eq(expected, str);
73: }
74:
75: START_TEST(test_create_from_string)
76: {
77: proposal_t *proposal;
78:
79: proposal = proposal_create_from_string(create_data[_i].proto,
80: create_data[_i].proposal);
81: assert_proposal_eq(proposal, create_data[_i].expected);
82: DESTROY_IF(proposal);
83: }
84: END_TEST
85:
86: static struct {
87: protocol_id_t proto;
88: char *self;
89: char *other;
90: char *expected;
91: proposal_selection_flag_t flags;
92: } select_data[] = {
93: { PROTO_ESP, "aes128", "aes128", "aes128" },
94: { PROTO_ESP, "aes128", "aes256", NULL },
95: { PROTO_ESP, "aes128-aes256", "aes256-aes128", "aes128" },
96: { PROTO_ESP, "aes256-aes128", "aes128-aes256", "aes256" },
97: { PROTO_ESP, "aes128-aes256-sha1-sha256", "aes256-aes128-sha256-sha1", "aes128-sha1" },
98: { PROTO_ESP, "aes256-aes128-sha256-sha1", "aes128-aes256-sha1-sha256", "aes256-sha256" },
99: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256", NULL },
100: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256", "aes128-sha256", PROPOSAL_SKIP_DH },
101: { PROTO_ESP, "aes128-sha256", "aes128-sha256-modp3072", NULL },
102: { PROTO_ESP, "aes128-sha256", "aes128-sha256-modp3072", "aes128-sha256", PROPOSAL_SKIP_DH },
103: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256-modp3072", "aes128-sha256", PROPOSAL_SKIP_DH },
104: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256-ecp256", "aes128-sha256", PROPOSAL_SKIP_DH },
105: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256-modpnone", NULL },
106: { PROTO_ESP, "aes128-sha256-modpnone", "aes128-sha256-modp3072", NULL },
107: { PROTO_ESP, "aes128-sha256-modp3072-modpnone", "aes128-sha256", "aes128-sha256" },
108: { PROTO_ESP, "aes128-sha256", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
109: { PROTO_ESP, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072" },
110: { PROTO_ESP, "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
111: { PROTO_ESP, "aes128-sha256-esn", "aes128-sha256-esn", "aes128-sha256-esn" },
112: { PROTO_ESP, "aes128-sha256-noesn", "aes128-sha256-esn", NULL },
113: { PROTO_ESP, "aes128-sha256-noesn-esn", "aes128-sha256-esn", "aes128-sha256-esn" },
114: { PROTO_ESP, "aes128-sha256-noesn-esn", "aes128-sha256", "aes128-sha256" },
115: { PROTO_ESP, "aes128-sha256-esn-noesn", "aes128-sha256-noesn-esn", "aes128-sha256-esn" },
116: { PROTO_IKE, "aes128-sha256-modp3072", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
117: { PROTO_IKE, "aes128-sha256-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072" },
118: { PROTO_IKE, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
119: };
120:
121: START_TEST(test_select)
122: {
123: proposal_t *self, *other, *selected, *expected;
124:
125: self = proposal_create_from_string(select_data[_i].proto,
126: select_data[_i].self);
127: other = proposal_create_from_string(select_data[_i].proto,
128: select_data[_i].other);
129: selected = self->select(self, other, select_data[_i].flags);
130: if (select_data[_i].expected)
131: {
132: expected = proposal_create_from_string(select_data[_i].proto,
133: select_data[_i].expected);
134: ck_assert(selected);
135: ck_assert_msg(expected->equals(expected, selected), "proposal %P does "
136: "not match expected %P", selected, expected);
137: expected->destroy(expected);
138: }
139: else
140: {
141: ck_assert(!selected);
142: }
143: DESTROY_IF(selected);
144: other->destroy(other);
145: self->destroy(self);
146: }
147: END_TEST
148:
149: START_TEST(test_select_spi)
150: {
151: proposal_t *self, *other, *selected;
152:
153: self = proposal_create_from_string(PROTO_ESP, "aes128-sha256-modp3072");
154: other = proposal_create_from_string(PROTO_ESP, "aes128-sha256-modp3072");
155: other->set_spi(other, 0x12345678);
156:
157: selected = self->select(self, other, 0);
158: ck_assert(selected);
159: ck_assert_int_eq(selected->get_spi(selected), other->get_spi(other));
160: selected->destroy(selected);
161:
162: selected = self->select(self, other, PROPOSAL_PREFER_SUPPLIED);
163: ck_assert(selected);
164: ck_assert_int_eq(selected->get_spi(selected), self->get_spi(self));
165: selected->destroy(selected);
166:
167: other->destroy(other);
168: self->destroy(self);
169: }
170: END_TEST
171:
172: START_TEST(test_matches)
173: {
174: proposal_t *self, *other;
175:
176: self = proposal_create_from_string(select_data[_i].proto,
177: select_data[_i].self);
178: other = proposal_create_from_string(select_data[_i].proto,
179: select_data[_i].other);
180: if (select_data[_i].expected)
181: {
182: ck_assert(self->matches(self, other, select_data[_i].flags));
183: ck_assert(other->matches(other, self, select_data[_i].flags));
184: ck_assert(self->matches(self, other,
185: select_data[_i].flags | PROPOSAL_PREFER_SUPPLIED));
186: ck_assert(other->matches(other, self,
187: select_data[_i].flags | PROPOSAL_PREFER_SUPPLIED));
188: }
189: else
190: {
191: ck_assert(!self->matches(self, other, select_data[_i].flags));
192: ck_assert(!other->matches(other, self, select_data[_i].flags));
193: ck_assert(!self->matches(self, other,
194: select_data[_i].flags | PROPOSAL_PREFER_SUPPLIED));
195: ck_assert(!other->matches(other, self,
196: select_data[_i].flags | PROPOSAL_PREFER_SUPPLIED));
197: }
198: other->destroy(other);
199: self->destroy(self);
200: }
201: END_TEST
202:
203: static struct {
204: protocol_id_t proto;
205: char *self[5];
206: char *other[5];
207: char *expected;
208: proposal_selection_flag_t flags;
209: } select_proposal_data[] = {
210: { PROTO_ESP, {}, {}, NULL },
211: { PROTO_ESP, { "aes128" }, {}, NULL },
212: { PROTO_ESP, {}, { "aes128" }, NULL },
213: { PROTO_ESP, { "aes128" }, { "aes256" }, NULL },
214: { PROTO_ESP, { "aes128" }, { "aes128" }, "aes128" },
215: { PROTO_ESP, { "aes128", "aes256" }, { "aes256", "aes128" }, "aes128" },
216: { PROTO_ESP, { "aes128", "aes256" }, { "aes256", "aes128" }, "aes256",
217: PROPOSAL_PREFER_SUPPLIED },
218: { PROTO_ESP, { "aes128-modp1024", "aes256-modp1024" },
219: { "aes256-modp2048", "aes128-modp2048" }, NULL },
220: { PROTO_ESP, { "aes128-modp1024", "aes256-modp1024" },
221: { "aes256-modp2048", "aes128-modp2048" }, "aes128",
222: PROPOSAL_SKIP_DH },
223: { PROTO_ESP, { "aes128-modp1024", "aes256-modp1024" },
224: { "aes256-modp2048", "aes128-modp2048" }, "aes256",
225: PROPOSAL_PREFER_SUPPLIED | PROPOSAL_SKIP_DH },
226: };
227:
228: START_TEST(test_select_proposal)
229: {
230: linked_list_t *self, *other;
231: proposal_t *proposal, *selected, *expected;
232: int i;
233:
234: self = linked_list_create();
235: other = linked_list_create();
236:
237: for (i = 0; i < countof(select_proposal_data[_i].self); i++)
238: {
239: if (!select_proposal_data[_i].self[i])
240: {
241: break;
242: }
243: proposal = proposal_create_from_string(select_proposal_data[_i].proto,
244: select_proposal_data[_i].self[i]);
245: self->insert_last(self, proposal);
246: }
247: for (i = 0; i < countof(select_proposal_data[_i].other); i++)
248: {
249: if (!select_proposal_data[_i].other[i])
250: {
251: break;
252: }
253: proposal = proposal_create_from_string(select_proposal_data[_i].proto,
254: select_proposal_data[_i].other[i]);
255: other->insert_last(other, proposal);
256: }
257: selected = proposal_select(self, other, select_proposal_data[_i].flags);
258: if (select_proposal_data[_i].expected)
259: {
260: expected = proposal_create_from_string(select_proposal_data[_i].proto,
261: select_proposal_data[_i].expected);
262: ck_assert(selected);
263: ck_assert_msg(expected->equals(expected, selected), "proposal %P does "
264: "not match expected %P", selected, expected);
265: expected->destroy(expected);
266: }
267: else
268: {
269: ck_assert(!selected);
270: }
271: DESTROY_IF(selected);
272: other->destroy_offset(other, offsetof(proposal_t, destroy));
273: self->destroy_offset(self, offsetof(proposal_t, destroy));
274: }
275: END_TEST
276:
277: START_TEST(test_promote_dh_group)
278: {
279: proposal_t *proposal;
280:
281: proposal = proposal_create_from_string(PROTO_IKE,
282: "aes128-sha256-modp3072-ecp256");
283: ck_assert(proposal->promote_dh_group(proposal, ECP_256_BIT));
284: assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/MODP_3072");
285: proposal->destroy(proposal);
286: }
287: END_TEST
288:
289: START_TEST(test_promote_dh_group_already_front)
290: {
291: proposal_t *proposal;
292:
293: proposal = proposal_create_from_string(PROTO_IKE,
294: "aes128-sha256-modp3072-ecp256");
295: ck_assert(proposal->promote_dh_group(proposal, MODP_3072_BIT));
296: assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
297: proposal->destroy(proposal);
298: }
299: END_TEST
300:
301: START_TEST(test_promote_dh_group_not_contained)
302: {
303: proposal_t *proposal;
304:
305: proposal = proposal_create_from_string(PROTO_IKE,
306: "aes128-sha256-modp3072-ecp256");
307:
308: ck_assert(!proposal->promote_dh_group(proposal, MODP_2048_BIT));
309: assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
310: proposal->destroy(proposal);
311: }
312: END_TEST
313:
314: START_TEST(test_unknown_transform_types_print)
315: {
316: proposal_t *proposal;
317:
318: proposal = proposal_create(PROTO_IKE, 0);
319: proposal->add_algorithm(proposal, 242, 42, 128);
320: assert_proposal_eq(proposal, "IKE:UNKNOWN_242_42_128");
321: proposal->destroy(proposal);
322:
323: proposal = proposal_create_from_string(PROTO_IKE,
324: "aes128-sha256-ecp256");
325: proposal->add_algorithm(proposal, 242, 42, 128);
326: proposal->add_algorithm(proposal, 243, 1, 0);
327: assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/UNKNOWN_242_42_128/UNKNOWN_243_1");
328: proposal->destroy(proposal);
329: }
330: END_TEST
331:
332: START_TEST(test_unknown_transform_types_equals)
333: {
334: proposal_t *self, *other;
335:
336: self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
337: other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
338: other->add_algorithm(other, 242, 42, 0);
339: ck_assert(!self->equals(self, other));
340: ck_assert(!other->equals(other, self));
341: self->add_algorithm(self, 242, 42, 0);
342: ck_assert(self->equals(self, other));
343: ck_assert(other->equals(other, self));
344: other->destroy(other);
345: self->destroy(self);
346: }
347: END_TEST
348:
349: START_TEST(test_unknown_transform_types_select_fail)
350: {
351: proposal_t *self, *other, *selected;
352:
353: self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
354: other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
355: other->add_algorithm(other, 242, 42, 0);
356:
357: selected = self->select(self, other, 0);
358: ck_assert(!selected);
359: other->destroy(other);
360: self->destroy(self);
361: }
362: END_TEST
363:
364: START_TEST(test_unknown_transform_types_select_fail_subtype)
365: {
366: proposal_t *self, *other, *selected;
367:
368: self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
369: self->add_algorithm(self, 242, 8, 0);
370: other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
371: other->add_algorithm(other, 242, 42, 0);
372:
373: selected = self->select(self, other, 0);
374: ck_assert(!selected);
375: other->destroy(other);
376: self->destroy(self);
377: }
378: END_TEST
379:
380: START_TEST(test_unknown_transform_types_select_success)
381: {
382: proposal_t *self, *other, *selected;
383:
384: self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
385: self->add_algorithm(self, 242, 42, 128);
386: other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256");
387: other->add_algorithm(other, 242, 42, 128);
388: other->add_algorithm(other, 242, 1, 0);
389:
390: selected = self->select(self, other, 0);
391: ck_assert(selected);
392: assert_proposal_eq(selected, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/UNKNOWN_242_42_128");
393: selected->destroy(selected);
394: other->destroy(other);
395: self->destroy(self);
396: }
397: END_TEST
398:
399: START_TEST(test_chacha20_poly1305_key_length)
400: {
401: proposal_t *proposal;
402: uint16_t alg, ks;
403:
404: proposal = proposal_create_from_string(PROTO_IKE, "chacha20poly1305-prfsha256-ecp256");
405: proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks);
406: ck_assert_int_eq(alg, ENCR_CHACHA20_POLY1305);
407: ck_assert_int_eq(ks, 0);
408: assert_proposal_eq(proposal, "IKE:CHACHA20_POLY1305/PRF_HMAC_SHA2_256/ECP_256");
409: proposal->destroy(proposal);
410: }
411: END_TEST
412:
413: static struct {
414: protocol_id_t proto;
415: char *orig;
416: char *expected;
417: proposal_selection_flag_t flags;
418: } clone_data[] = {
419: { PROTO_ESP, "aes128", "aes128" },
420: { PROTO_ESP, "aes128-serpent", "aes128-serpent" },
421: { PROTO_ESP, "aes128-serpent", "aes128", PROPOSAL_SKIP_PRIVATE },
422: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
423: { PROTO_ESP, "aes128-sha256-modp3072", "aes128-sha256", PROPOSAL_SKIP_DH },
424: { PROTO_ESP, "aes128-serpent-modp3072", "aes128-serpent",
425: PROPOSAL_SKIP_DH },
426: { PROTO_ESP, "aes128-serpent-modp3072", "aes128",
427: PROPOSAL_SKIP_PRIVATE | PROPOSAL_SKIP_DH },
428: };
429:
430: START_TEST(test_clone)
431: {
432: proposal_t *orig, *result, *expected;
433:
434: orig = proposal_create_from_string(clone_data[_i].proto,
435: clone_data[_i].orig);
436: orig->set_spi(orig, 0x12345678);
437:
438: result = orig->clone(orig, clone_data[_i].flags);
439:
440: expected = proposal_create_from_string(clone_data[_i].proto,
441: clone_data[_i].expected);
442: ck_assert_msg(expected->equals(expected, result), "proposal %P does "
443: "not match expected %P", result, expected);
444: ck_assert_int_eq(orig->get_spi(orig), result->get_spi(result));
445:
446: expected->destroy(expected);
447: result->destroy(result);
448: orig->destroy(orig);
449: }
450: END_TEST
451:
452: Suite *proposal_suite_create()
453: {
454: Suite *s;
455: TCase *tc;
456:
457: s = suite_create("proposal");
458:
459: tc = tcase_create("create_from_string");
460: tcase_add_loop_test(tc, test_create_from_string, 0, countof(create_data));
461: suite_add_tcase(s, tc);
462:
463: tc = tcase_create("select");
464: tcase_add_loop_test(tc, test_select, 0, countof(select_data));
465: tcase_add_test(tc, test_select_spi);
466: suite_add_tcase(s, tc);
467:
468: tc = tcase_create("matches");
469: tcase_add_loop_test(tc, test_matches, 0, countof(select_data));
470: suite_add_tcase(s, tc);
471:
472: tc = tcase_create("select_proposal");
473: tcase_add_loop_test(tc, test_select_proposal, 0,
474: countof(select_proposal_data));
475: suite_add_tcase(s, tc);
476:
477: tc = tcase_create("promote_dh_group");
478: tcase_add_test(tc, test_promote_dh_group);
479: tcase_add_test(tc, test_promote_dh_group_already_front);
480: tcase_add_test(tc, test_promote_dh_group_not_contained);
481: suite_add_tcase(s, tc);
482:
483: tc = tcase_create("unknown transform types");
484: tcase_add_test(tc, test_unknown_transform_types_print);
485: tcase_add_test(tc, test_unknown_transform_types_equals);
486: tcase_add_test(tc, test_unknown_transform_types_select_fail);
487: tcase_add_test(tc, test_unknown_transform_types_select_fail_subtype);
488: tcase_add_test(tc, test_unknown_transform_types_select_success);
489: suite_add_tcase(s, tc);
490:
491: tc = tcase_create("chacha20/poly1305");
492: tcase_add_test(tc, test_chacha20_poly1305_key_length);
493: suite_add_tcase(s, tc);
494:
495: tc = tcase_create("clone");
496: tcase_add_loop_test(tc, test_clone, 0, countof(clone_data));
497: suite_add_tcase(s, tc);
498:
499: return s;
500: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>