1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 #if HAVE_CMOCKA
13 
14 #include <sched.h> /* IWYU pragma: keep */
15 #include <setjmp.h>
16 #include <stdarg.h>
17 #include <stdbool.h>
18 #include <stddef.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 
22 #define UNIT_TESTING
23 #include <cmocka.h>
24 
25 #include <isc/mem.h>
26 #include <isc/print.h>
27 #include <isc/util.h>
28 
29 #include <dns/rdatalist.h>
30 #include <dns/rdataset.h>
31 #include <dns/tsig.h>
32 
33 #include "../tsig_p.h"
34 #include "dnstest.h"
35 
36 #define CHECK(r)                               \
37 	do {                                   \
38 		result = (r);                  \
39 		if (result != ISC_R_SUCCESS) { \
40 			goto cleanup;          \
41 		}                              \
42 	} while (0)
43 
44 #define TEST_ORIGIN "test"
45 
46 static int
_setup(void ** state)47 _setup(void **state) {
48 	isc_result_t result;
49 
50 	UNUSED(state);
51 
52 	result = dns_test_begin(NULL, false);
53 	assert_int_equal(result, ISC_R_SUCCESS);
54 
55 	return (0);
56 }
57 
58 static int
_teardown(void ** state)59 _teardown(void **state) {
60 	UNUSED(state);
61 
62 	dns_test_end();
63 
64 	return (0);
65 }
66 
67 static int debug = 0;
68 
69 static isc_result_t
add_mac(dst_context_t * tsigctx,isc_buffer_t * buf)70 add_mac(dst_context_t *tsigctx, isc_buffer_t *buf) {
71 	dns_rdata_any_tsig_t tsig;
72 	dns_rdata_t rdata = DNS_RDATA_INIT;
73 	isc_buffer_t databuf;
74 	isc_region_t r;
75 	isc_result_t result;
76 	unsigned char tsigbuf[1024];
77 
78 	isc_buffer_usedregion(buf, &r);
79 	dns_rdata_fromregion(&rdata, dns_rdataclass_any, dns_rdatatype_tsig,
80 			     &r);
81 	isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf));
82 	CHECK(dns_rdata_tostruct(&rdata, &tsig, NULL));
83 	isc_buffer_putuint16(&databuf, tsig.siglen);
84 	isc_buffer_putmem(&databuf, tsig.signature, tsig.siglen);
85 	isc_buffer_usedregion(&databuf, &r);
86 	result = dst_context_adddata(tsigctx, &r);
87 	dns_rdata_freestruct(&tsig);
88 cleanup:
89 	return (result);
90 }
91 
92 static isc_result_t
add_tsig(dst_context_t * tsigctx,dns_tsigkey_t * key,isc_buffer_t * target)93 add_tsig(dst_context_t *tsigctx, dns_tsigkey_t *key, isc_buffer_t *target) {
94 	dns_compress_t cctx;
95 	dns_rdata_any_tsig_t tsig;
96 	dns_rdata_t rdata = DNS_RDATA_INIT;
97 	dns_rdatalist_t rdatalist;
98 	dns_rdataset_t rdataset;
99 	isc_buffer_t *dynbuf = NULL;
100 	isc_buffer_t databuf;
101 	isc_buffer_t sigbuf;
102 	isc_region_t r;
103 	isc_result_t result = ISC_R_SUCCESS;
104 	isc_stdtime_t now;
105 	unsigned char tsigbuf[1024];
106 	unsigned int count;
107 	unsigned int sigsize = 0;
108 	bool invalidate_ctx = false;
109 
110 	memset(&tsig, 0, sizeof(tsig));
111 
112 	CHECK(dns_compress_init(&cctx, -1, dt_mctx));
113 	invalidate_ctx = true;
114 
115 	tsig.common.rdclass = dns_rdataclass_any;
116 	tsig.common.rdtype = dns_rdatatype_tsig;
117 	ISC_LINK_INIT(&tsig.common, link);
118 	dns_name_init(&tsig.algorithm, NULL);
119 	dns_name_clone(key->algorithm, &tsig.algorithm);
120 
121 	isc_stdtime_get(&now);
122 	tsig.timesigned = now;
123 	tsig.fudge = DNS_TSIG_FUDGE;
124 	tsig.originalid = 50;
125 	tsig.error = dns_rcode_noerror;
126 	tsig.otherlen = 0;
127 	tsig.other = NULL;
128 
129 	isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf));
130 	isc_buffer_putuint48(&databuf, tsig.timesigned);
131 	isc_buffer_putuint16(&databuf, tsig.fudge);
132 	isc_buffer_usedregion(&databuf, &r);
133 	CHECK(dst_context_adddata(tsigctx, &r));
134 
135 	CHECK(dst_key_sigsize(key->key, &sigsize));
136 	tsig.signature = isc_mem_get(dt_mctx, sigsize);
137 	isc_buffer_init(&sigbuf, tsig.signature, sigsize);
138 	CHECK(dst_context_sign(tsigctx, &sigbuf));
139 	tsig.siglen = isc_buffer_usedlength(&sigbuf);
140 	assert_int_equal(sigsize, tsig.siglen);
141 
142 	isc_buffer_allocate(dt_mctx, &dynbuf, 512);
143 	CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_any,
144 				   dns_rdatatype_tsig, &tsig, dynbuf));
145 	dns_rdatalist_init(&rdatalist);
146 	rdatalist.rdclass = dns_rdataclass_any;
147 	rdatalist.type = dns_rdatatype_tsig;
148 	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
149 	dns_rdataset_init(&rdataset);
150 	CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
151 	CHECK(dns_rdataset_towire(&rdataset, &key->name, &cctx, target, 0,
152 				  &count));
153 
154 	/*
155 	 * Fixup additional record count.
156 	 */
157 	((unsigned char *)target->base)[11]++;
158 	if (((unsigned char *)target->base)[11] == 0) {
159 		((unsigned char *)target->base)[10]++;
160 	}
161 cleanup:
162 	if (tsig.signature != NULL) {
163 		isc_mem_put(dt_mctx, tsig.signature, sigsize);
164 	}
165 	if (dynbuf != NULL) {
166 		isc_buffer_free(&dynbuf);
167 	}
168 	if (invalidate_ctx) {
169 		dns_compress_invalidate(&cctx);
170 	}
171 
172 	return (result);
173 }
174 
175 static void
printmessage(dns_message_t * msg)176 printmessage(dns_message_t *msg) {
177 	isc_buffer_t b;
178 	char *buf = NULL;
179 	int len = 1024;
180 	isc_result_t result = ISC_R_SUCCESS;
181 
182 	if (!debug) {
183 		return;
184 	}
185 
186 	do {
187 		buf = isc_mem_get(dt_mctx, len);
188 
189 		isc_buffer_init(&b, buf, len);
190 		result = dns_message_totext(msg, &dns_master_style_debug, 0,
191 					    &b);
192 		if (result == ISC_R_NOSPACE) {
193 			isc_mem_put(dt_mctx, buf, len);
194 			len *= 2;
195 		} else if (result == ISC_R_SUCCESS) {
196 			printf("%.*s\n", (int)isc_buffer_usedlength(&b), buf);
197 		}
198 	} while (result == ISC_R_NOSPACE);
199 
200 	if (buf != NULL) {
201 		isc_mem_put(dt_mctx, buf, len);
202 	}
203 }
204 
205 static void
render(isc_buffer_t * buf,unsigned flags,dns_tsigkey_t * key,isc_buffer_t ** tsigin,isc_buffer_t ** tsigout,dst_context_t * tsigctx)206 render(isc_buffer_t *buf, unsigned flags, dns_tsigkey_t *key,
207        isc_buffer_t **tsigin, isc_buffer_t **tsigout, dst_context_t *tsigctx) {
208 	dns_message_t *msg = NULL;
209 	dns_compress_t cctx;
210 	isc_result_t result;
211 
212 	result = dns_message_create(dt_mctx, DNS_MESSAGE_INTENTRENDER, &msg);
213 	assert_int_equal(result, ISC_R_SUCCESS);
214 	assert_non_null(msg);
215 
216 	msg->id = 50;
217 	msg->rcode = dns_rcode_noerror;
218 	msg->flags = flags;
219 
220 	/*
221 	 * XXXMPA: this hack needs to be replaced with use of
222 	 * dns_message_reply() at some point.
223 	 */
224 	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
225 		msg->verified_sig = 1;
226 	}
227 
228 	if (tsigin == tsigout) {
229 		msg->tcp_continuation = 1;
230 	}
231 
232 	if (tsigctx == NULL) {
233 		result = dns_message_settsigkey(msg, key);
234 		assert_int_equal(result, ISC_R_SUCCESS);
235 
236 		result = dns_message_setquerytsig(msg, *tsigin);
237 		assert_int_equal(result, ISC_R_SUCCESS);
238 	}
239 
240 	result = dns_compress_init(&cctx, -1, dt_mctx);
241 	assert_int_equal(result, ISC_R_SUCCESS);
242 
243 	result = dns_message_renderbegin(msg, &cctx, buf);
244 	assert_int_equal(result, ISC_R_SUCCESS);
245 
246 	result = dns_message_renderend(msg);
247 	assert_int_equal(result, ISC_R_SUCCESS);
248 
249 	if (tsigctx != NULL) {
250 		isc_region_t r;
251 
252 		isc_buffer_usedregion(buf, &r);
253 		result = dst_context_adddata(tsigctx, &r);
254 		assert_int_equal(result, ISC_R_SUCCESS);
255 	} else {
256 		if (tsigin == tsigout && *tsigin != NULL) {
257 			isc_buffer_free(tsigin);
258 		}
259 
260 		result = dns_message_getquerytsig(msg, dt_mctx, tsigout);
261 		assert_int_equal(result, ISC_R_SUCCESS);
262 	}
263 
264 	dns_compress_invalidate(&cctx);
265 	dns_message_destroy(&msg);
266 }
267 
268 /*
269  * Test tsig tcp-continuation validation:
270  * Check that a simulated three message TCP sequence where the first
271  * and last messages contain TSIGs but the intermediate message doesn't
272  * correctly verifies.
273  */
274 static void
tsig_tcp_test(void ** state)275 tsig_tcp_test(void **state) {
276 	const dns_name_t *tsigowner = NULL;
277 	dns_fixedname_t fkeyname;
278 	dns_message_t *msg = NULL;
279 	dns_name_t *keyname;
280 	dns_tsig_keyring_t *ring = NULL;
281 	dns_tsigkey_t *key = NULL;
282 	isc_buffer_t *buf = NULL;
283 	isc_buffer_t *querytsig = NULL;
284 	isc_buffer_t *tsigin = NULL;
285 	isc_buffer_t *tsigout = NULL;
286 	isc_result_t result;
287 	unsigned char secret[16] = { 0 };
288 	dst_context_t *tsigctx = NULL;
289 	dst_context_t *outctx = NULL;
290 
291 	UNUSED(state);
292 
293 	/* isc_log_setdebuglevel(lctx, 99); */
294 
295 	keyname = dns_fixedname_initname(&fkeyname);
296 	result = dns_name_fromstring(keyname, "test", 0, NULL);
297 	assert_int_equal(result, ISC_R_SUCCESS);
298 
299 	result = dns_tsigkeyring_create(dt_mctx, &ring);
300 	assert_int_equal(result, ISC_R_SUCCESS);
301 
302 	result = dns_tsigkey_create(keyname, dns_tsig_hmacsha256_name, secret,
303 				    sizeof(secret), false, NULL, 0, 0, dt_mctx,
304 				    ring, &key);
305 	assert_int_equal(result, ISC_R_SUCCESS);
306 	assert_non_null(key);
307 
308 	/*
309 	 * Create request.
310 	 */
311 	isc_buffer_allocate(dt_mctx, &buf, 65535);
312 	render(buf, 0, key, &tsigout, &querytsig, NULL);
313 	isc_buffer_free(&buf);
314 
315 	/*
316 	 * Create response message 1.
317 	 */
318 	isc_buffer_allocate(dt_mctx, &buf, 65535);
319 	render(buf, DNS_MESSAGEFLAG_QR, key, &querytsig, &tsigout, NULL);
320 
321 	/*
322 	 * Process response message 1.
323 	 */
324 	result = dns_message_create(dt_mctx, DNS_MESSAGE_INTENTPARSE, &msg);
325 	assert_int_equal(result, ISC_R_SUCCESS);
326 	assert_non_null(msg);
327 
328 	result = dns_message_settsigkey(msg, key);
329 	assert_int_equal(result, ISC_R_SUCCESS);
330 
331 	result = dns_message_parse(msg, buf, 0);
332 	assert_int_equal(result, ISC_R_SUCCESS);
333 
334 	printmessage(msg);
335 
336 	result = dns_message_setquerytsig(msg, querytsig);
337 	assert_int_equal(result, ISC_R_SUCCESS);
338 
339 	result = dns_tsig_verify(buf, msg, NULL, NULL);
340 	assert_int_equal(result, ISC_R_SUCCESS);
341 	assert_int_equal(msg->verified_sig, 1);
342 	assert_int_equal(msg->tsigstatus, dns_rcode_noerror);
343 
344 	/*
345 	 * Check that we have a TSIG in the first message.
346 	 */
347 	assert_non_null(dns_message_gettsig(msg, &tsigowner));
348 
349 	result = dns_message_getquerytsig(msg, dt_mctx, &tsigin);
350 	assert_int_equal(result, ISC_R_SUCCESS);
351 
352 	tsigctx = msg->tsigctx;
353 	msg->tsigctx = NULL;
354 	isc_buffer_free(&buf);
355 	dns_message_destroy(&msg);
356 
357 	result = dst_context_create(key->key, dt_mctx, DNS_LOGCATEGORY_DNSSEC,
358 				    false, 0, &outctx);
359 	assert_int_equal(result, ISC_R_SUCCESS);
360 	assert_non_null(outctx);
361 
362 	/*
363 	 * Start digesting.
364 	 */
365 	result = add_mac(outctx, tsigout);
366 	assert_int_equal(result, ISC_R_SUCCESS);
367 
368 	/*
369 	 * Create response message 2.
370 	 */
371 	isc_buffer_allocate(dt_mctx, &buf, 65535);
372 
373 	assert_int_equal(result, ISC_R_SUCCESS);
374 	render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx);
375 
376 	/*
377 	 * Process response message 2.
378 	 */
379 	result = dns_message_create(dt_mctx, DNS_MESSAGE_INTENTPARSE, &msg);
380 	assert_int_equal(result, ISC_R_SUCCESS);
381 	assert_non_null(msg);
382 
383 	msg->tcp_continuation = 1;
384 	msg->tsigctx = tsigctx;
385 	tsigctx = NULL;
386 
387 	result = dns_message_settsigkey(msg, key);
388 	assert_int_equal(result, ISC_R_SUCCESS);
389 
390 	result = dns_message_parse(msg, buf, 0);
391 	assert_int_equal(result, ISC_R_SUCCESS);
392 
393 	printmessage(msg);
394 
395 	result = dns_message_setquerytsig(msg, tsigin);
396 	assert_int_equal(result, ISC_R_SUCCESS);
397 
398 	result = dns_tsig_verify(buf, msg, NULL, NULL);
399 	assert_int_equal(result, ISC_R_SUCCESS);
400 	assert_int_equal(msg->verified_sig, 0);
401 	assert_int_equal(msg->tsigstatus, dns_rcode_noerror);
402 
403 	/*
404 	 * Check that we don't have a TSIG in the second message.
405 	 */
406 	tsigowner = NULL;
407 	assert_true(dns_message_gettsig(msg, &tsigowner) == NULL);
408 
409 	tsigctx = msg->tsigctx;
410 	msg->tsigctx = NULL;
411 	isc_buffer_free(&buf);
412 	dns_message_destroy(&msg);
413 
414 	/*
415 	 * Create response message 3.
416 	 */
417 	isc_buffer_allocate(dt_mctx, &buf, 65535);
418 	render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx);
419 
420 	result = add_tsig(outctx, key, buf);
421 	assert_int_equal(result, ISC_R_SUCCESS);
422 
423 	/*
424 	 * Process response message 3.
425 	 */
426 	result = dns_message_create(dt_mctx, DNS_MESSAGE_INTENTPARSE, &msg);
427 	assert_int_equal(result, ISC_R_SUCCESS);
428 	assert_non_null(msg);
429 
430 	msg->tcp_continuation = 1;
431 	msg->tsigctx = tsigctx;
432 	tsigctx = NULL;
433 
434 	result = dns_message_settsigkey(msg, key);
435 	assert_int_equal(result, ISC_R_SUCCESS);
436 
437 	result = dns_message_parse(msg, buf, 0);
438 	assert_int_equal(result, ISC_R_SUCCESS);
439 
440 	printmessage(msg);
441 
442 	/*
443 	 * Check that we had a TSIG in the third message.
444 	 */
445 	assert_non_null(dns_message_gettsig(msg, &tsigowner));
446 
447 	result = dns_message_setquerytsig(msg, tsigin);
448 	assert_int_equal(result, ISC_R_SUCCESS);
449 
450 	result = dns_tsig_verify(buf, msg, NULL, NULL);
451 	assert_int_equal(result, ISC_R_SUCCESS);
452 	assert_int_equal(msg->verified_sig, 1);
453 	assert_int_equal(msg->tsigstatus, dns_rcode_noerror);
454 
455 	if (tsigin != NULL) {
456 		isc_buffer_free(&tsigin);
457 	}
458 
459 	result = dns_message_getquerytsig(msg, dt_mctx, &tsigin);
460 	assert_int_equal(result, ISC_R_SUCCESS);
461 
462 	isc_buffer_free(&buf);
463 	dns_message_destroy(&msg);
464 
465 	if (outctx != NULL) {
466 		dst_context_destroy(&outctx);
467 	}
468 	if (querytsig != NULL) {
469 		isc_buffer_free(&querytsig);
470 	}
471 	if (tsigin != NULL) {
472 		isc_buffer_free(&tsigin);
473 	}
474 	if (tsigout != NULL) {
475 		isc_buffer_free(&tsigout);
476 	}
477 	dns_tsigkey_detach(&key);
478 	if (ring != NULL) {
479 		dns_tsigkeyring_detach(&ring);
480 	}
481 }
482 
483 /* Tests the dns__tsig_algvalid function */
484 static void
algvalid_test(void ** state)485 algvalid_test(void **state) {
486 	UNUSED(state);
487 
488 	assert_true(dns__tsig_algvalid(DST_ALG_HMACMD5));
489 
490 	assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA1));
491 	assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA224));
492 	assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA256));
493 	assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA384));
494 	assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA512));
495 
496 	assert_false(dns__tsig_algvalid(DST_ALG_GSSAPI));
497 }
498 
499 /* Tests the dns__tsig_algfromname function */
500 static void
algfromname_test(void ** state)501 algfromname_test(void **state) {
502 	UNUSED(state);
503 
504 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACMD5_NAME),
505 			 DST_ALG_HMACMD5);
506 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA1_NAME),
507 			 DST_ALG_HMACSHA1);
508 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA224_NAME),
509 			 DST_ALG_HMACSHA224);
510 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA256_NAME),
511 			 DST_ALG_HMACSHA256);
512 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA384_NAME),
513 			 DST_ALG_HMACSHA384);
514 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA512_NAME),
515 			 DST_ALG_HMACSHA512);
516 
517 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_GSSAPI_NAME),
518 			 DST_ALG_GSSAPI);
519 	assert_int_equal(dns__tsig_algfromname(DNS_TSIG_GSSAPIMS_NAME),
520 			 DST_ALG_GSSAPI);
521 
522 	assert_int_equal(dns__tsig_algfromname(dns_rootname), 0);
523 }
524 
525 /* Tests the dns__tsig_algnamefromname function */
526 
527 /*
528  * Helper function to create a dns_name_t from a string and see if
529  * the dns__tsig_algnamefromname function can correctly match it against the
530  * static table of known algorithms.
531  */
532 static void
test_name(const char * name_string,const dns_name_t * expected)533 test_name(const char *name_string, const dns_name_t *expected) {
534 	dns_name_t name;
535 	dns_name_init(&name, NULL);
536 	assert_int_equal(dns_name_fromstring(&name, name_string, 0, dt_mctx),
537 			 ISC_R_SUCCESS);
538 	assert_int_equal(dns__tsig_algnamefromname(&name), expected);
539 	dns_name_free(&name, dt_mctx);
540 }
541 
542 static void
algnamefromname_test(void ** state)543 algnamefromname_test(void **state) {
544 	UNUSED(state);
545 
546 	/* test the standard algorithms */
547 	test_name("hmac-md5.sig-alg.reg.int", DNS_TSIG_HMACMD5_NAME);
548 	test_name("hmac-sha1", DNS_TSIG_HMACSHA1_NAME);
549 	test_name("hmac-sha224", DNS_TSIG_HMACSHA224_NAME);
550 	test_name("hmac-sha256", DNS_TSIG_HMACSHA256_NAME);
551 	test_name("hmac-sha384", DNS_TSIG_HMACSHA384_NAME);
552 	test_name("hmac-sha512", DNS_TSIG_HMACSHA512_NAME);
553 
554 	test_name("gss-tsig", DNS_TSIG_GSSAPI_NAME);
555 	test_name("gss.microsoft.com", DNS_TSIG_GSSAPIMS_NAME);
556 
557 	/* try another name that isn't a standard algorithm name */
558 	assert_int_equal(dns__tsig_algnamefromname(dns_rootname), NULL);
559 }
560 
561 /* Tests the dns__tsig_algallocated function */
562 static void
algallocated_test(void ** state)563 algallocated_test(void **state) {
564 	UNUSED(state);
565 
566 	/* test the standard algorithms */
567 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACMD5_NAME));
568 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA1_NAME));
569 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA224_NAME));
570 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA256_NAME));
571 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA384_NAME));
572 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA512_NAME));
573 
574 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA512_NAME));
575 	assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA512_NAME));
576 
577 	/* try another name that isn't a standard algorithm name */
578 	assert_true(dns__tsig_algallocated(dns_rootname));
579 }
580 
581 int
main(void)582 main(void) {
583 	const struct CMUnitTest tests[] = {
584 		cmocka_unit_test_setup_teardown(tsig_tcp_test, _setup,
585 						_teardown),
586 		cmocka_unit_test(algvalid_test),
587 		cmocka_unit_test(algfromname_test),
588 		cmocka_unit_test_setup_teardown(algnamefromname_test, _setup,
589 						_teardown),
590 		cmocka_unit_test(algallocated_test),
591 	};
592 
593 	return (cmocka_run_group_tests(tests, NULL, NULL));
594 }
595 
596 #else /* HAVE_CMOCKA */
597 
598 #include <stdio.h>
599 
600 int
main(void)601 main(void) {
602 	printf("1..0 # Skipped: cmocka not available\n");
603 	return (0);
604 }
605 
606 #endif /* if HAVE_CMOCKA */
607