xref: /freebsd/lib/libnv/tests/nvlist_send_recv_test.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * Copyright (c) 2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <sys/sysctl.h>
34 #include <sys/wait.h>
35 #include <sys/nv.h>
36 
37 #include <stdlib.h>
38 #include <err.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <paths.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include <atf-c.h>
47 
48 #define	ALPHABET	"abcdefghijklmnopqrstuvwxyz"
49 #define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
50 
51 static void
52 send_nvlist_child(int sock)
53 {
54 	nvlist_t *nvl;
55 	nvlist_t *empty;
56 	int pfd[2];
57 
58 	nvl = nvlist_create(0);
59 	empty = nvlist_create(0);
60 
61 	nvlist_add_bool(nvl, "nvlist/bool/true", true);
62 	nvlist_add_bool(nvl, "nvlist/bool/false", false);
63 	nvlist_add_number(nvl, "nvlist/number/0", 0);
64 	nvlist_add_number(nvl, "nvlist/number/1", 1);
65 	nvlist_add_number(nvl, "nvlist/number/-1", -1);
66 	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
67 	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
68 	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
69 	nvlist_add_string(nvl, "nvlist/string/", "");
70 	nvlist_add_string(nvl, "nvlist/string/x", "x");
71 	nvlist_add_string(nvl, "nvlist/string/" ALPHABET, ALPHABET);
72 
73 	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO",
74 	    STDERR_FILENO);
75 	if (pipe(pfd) == -1)
76 		err(EXIT_FAILURE, "pipe");
77 	if (write(pfd[1], "test", 4) != 4)
78 		err(EXIT_FAILURE, "write");
79 	close(pfd[1]);
80 	nvlist_add_descriptor(nvl, "nvlist/descriptor/pipe_rd", pfd[0]);
81 	close(pfd[0]);
82 
83 	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
84 	nvlist_add_binary(nvl, "nvlist/binary/" ALPHABET, ALPHABET,
85 	    sizeof(ALPHABET));
86 	nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
87 	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
88 
89 	nvlist_send(sock, nvl);
90 
91 	nvlist_destroy(nvl);
92 }
93 
94 static void
95 send_nvlist_parent(int sock)
96 {
97 	nvlist_t *nvl;
98 	const nvlist_t *cnvl, *empty;
99 	const char *name, *cname;
100 	void *cookie, *ccookie;
101 	int type, ctype, fd;
102 	size_t size;
103 	char buf[4];
104 
105 	nvl = nvlist_recv(sock, 0);
106 	ATF_REQUIRE(nvlist_error(nvl) == 0);
107 	if (nvlist_error(nvl) != 0)
108 		err(1, "nvlist_recv() failed");
109 
110 	cookie = NULL;
111 
112 	name = nvlist_next(nvl, &type, &cookie);
113 	ATF_REQUIRE(name != NULL);
114 	ATF_REQUIRE(type == NV_TYPE_BOOL);
115 	ATF_REQUIRE(strcmp(name, "nvlist/bool/true") == 0);
116 	ATF_REQUIRE(nvlist_get_bool(nvl, name) == true);
117 
118 	name = nvlist_next(nvl, &type, &cookie);
119 	ATF_REQUIRE(name != NULL);
120 	ATF_REQUIRE(type == NV_TYPE_BOOL);
121 	ATF_REQUIRE(strcmp(name, "nvlist/bool/false") == 0);
122 	ATF_REQUIRE(nvlist_get_bool(nvl, name) == false);
123 
124 	name = nvlist_next(nvl, &type, &cookie);
125 	ATF_REQUIRE(name != NULL);
126 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
127 	ATF_REQUIRE(strcmp(name, "nvlist/number/0") == 0);
128 	ATF_REQUIRE(nvlist_get_number(nvl, name) == 0);
129 
130 	name = nvlist_next(nvl, &type, &cookie);
131 	ATF_REQUIRE(name != NULL);
132 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
133 	ATF_REQUIRE(strcmp(name, "nvlist/number/1") == 0);
134 	ATF_REQUIRE(nvlist_get_number(nvl, name) == 1);
135 
136 	name = nvlist_next(nvl, &type, &cookie);
137 	ATF_REQUIRE(name != NULL);
138 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
139 	ATF_REQUIRE(strcmp(name, "nvlist/number/-1") == 0);
140 	ATF_REQUIRE((int)nvlist_get_number(nvl, name) == -1);
141 
142 	name = nvlist_next(nvl, &type, &cookie);
143 	ATF_REQUIRE(name != NULL);
144 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
145 	ATF_REQUIRE(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
146 	ATF_REQUIRE(nvlist_get_number(nvl, name) == UINT64_MAX);
147 
148 	name = nvlist_next(nvl, &type, &cookie);
149 	ATF_REQUIRE(name != NULL);
150 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
151 	ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MIN") == 0);
152 	ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
153 
154 	name = nvlist_next(nvl, &type, &cookie);
155 	ATF_REQUIRE(name != NULL);
156 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
157 	ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MAX") == 0);
158 	ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
159 
160 	name = nvlist_next(nvl, &type, &cookie);
161 	ATF_REQUIRE(name != NULL);
162 	ATF_REQUIRE(type == NV_TYPE_STRING);
163 	ATF_REQUIRE(strcmp(name, "nvlist/string/") == 0);
164 	ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "") == 0);
165 
166 	name = nvlist_next(nvl, &type, &cookie);
167 	ATF_REQUIRE(name != NULL);
168 	ATF_REQUIRE(type == NV_TYPE_STRING);
169 	ATF_REQUIRE(strcmp(name, "nvlist/string/x") == 0);
170 	ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "x") == 0);
171 
172 	name = nvlist_next(nvl, &type, &cookie);
173 	ATF_REQUIRE(name != NULL);
174 	ATF_REQUIRE(type == NV_TYPE_STRING);
175 	ATF_REQUIRE(strcmp(name, "nvlist/string/" ALPHABET) == 0);
176 	ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), ALPHABET) == 0);
177 
178 	name = nvlist_next(nvl, &type, &cookie);
179 	ATF_REQUIRE(name != NULL);
180 	ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
181 	ATF_REQUIRE(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
182 	ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(nvl, name)));
183 
184 	name = nvlist_next(nvl, &type, &cookie);
185 	ATF_REQUIRE(name != NULL);
186 	ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
187 	ATF_REQUIRE(strcmp(name, "nvlist/descriptor/pipe_rd") == 0);
188 	fd = nvlist_get_descriptor(nvl, name);
189 	ATF_REQUIRE(fd_is_valid(fd));
190 	ATF_REQUIRE(read(fd, buf, sizeof(buf)) == 4);
191 	ATF_REQUIRE(strncmp(buf, "test", sizeof(buf)) == 0);
192 
193 	name = nvlist_next(nvl, &type, &cookie);
194 	ATF_REQUIRE(name != NULL);
195 	ATF_REQUIRE(type == NV_TYPE_BINARY);
196 	ATF_REQUIRE(strcmp(name, "nvlist/binary/x") == 0);
197 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
198 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
199 	ATF_REQUIRE(size == 1);
200 
201 	name = nvlist_next(nvl, &type, &cookie);
202 	ATF_REQUIRE(name != NULL);
203 	ATF_REQUIRE(type == NV_TYPE_BINARY);
204 	ATF_REQUIRE(strcmp(name, "nvlist/binary/" ALPHABET) == 0);
205 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), ALPHABET,
206 	    sizeof(ALPHABET)) == 0);
207 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), ALPHABET,
208 	    sizeof(ALPHABET)) == 0);
209 	ATF_REQUIRE(size == sizeof(ALPHABET));
210 
211 	name = nvlist_next(nvl, &type, &cookie);
212 	ATF_REQUIRE(name != NULL);
213 	ATF_REQUIRE(type == NV_TYPE_NVLIST);
214 	ATF_REQUIRE(strcmp(name, "nvlist/nvlist/empty") == 0);
215 	cnvl = nvlist_get_nvlist(nvl, name);
216 	ATF_REQUIRE(nvlist_empty(cnvl));
217 
218 	name = nvlist_next(nvl, &type, &cookie);
219 	ATF_REQUIRE(name != NULL);
220 	ATF_REQUIRE(type == NV_TYPE_NVLIST);
221 	ATF_REQUIRE(strcmp(name, "nvlist/nvlist") == 0);
222 	cnvl = nvlist_get_nvlist(nvl, name);
223 
224 	ccookie = NULL;
225 
226 	cname = nvlist_next(cnvl, &ctype, &ccookie);
227 	ATF_REQUIRE(cname != NULL);
228 	ATF_REQUIRE(ctype == NV_TYPE_BOOL);
229 	ATF_REQUIRE(strcmp(cname, "nvlist/bool/true") == 0);
230 	ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == true);
231 
232 	cname = nvlist_next(cnvl, &ctype, &ccookie);
233 	ATF_REQUIRE(cname != NULL);
234 	ATF_REQUIRE(ctype == NV_TYPE_BOOL);
235 	ATF_REQUIRE(strcmp(cname, "nvlist/bool/false") == 0);
236 	ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == false);
237 
238 	cname = nvlist_next(cnvl, &ctype, &ccookie);
239 	ATF_REQUIRE(cname != NULL);
240 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
241 	ATF_REQUIRE(strcmp(cname, "nvlist/number/0") == 0);
242 	ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 0);
243 
244 	cname = nvlist_next(cnvl, &ctype, &ccookie);
245 	ATF_REQUIRE(cname != NULL);
246 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
247 	ATF_REQUIRE(strcmp(cname, "nvlist/number/1") == 0);
248 	ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 1);
249 
250 	cname = nvlist_next(cnvl, &ctype, &ccookie);
251 	ATF_REQUIRE(cname != NULL);
252 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
253 	ATF_REQUIRE(strcmp(cname, "nvlist/number/-1") == 0);
254 	ATF_REQUIRE((int)nvlist_get_number(cnvl, cname) == -1);
255 
256 	cname = nvlist_next(cnvl, &ctype, &ccookie);
257 	ATF_REQUIRE(cname != NULL);
258 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
259 	ATF_REQUIRE(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
260 	ATF_REQUIRE(nvlist_get_number(cnvl, cname) == UINT64_MAX);
261 
262 	cname = nvlist_next(cnvl, &ctype, &ccookie);
263 	ATF_REQUIRE(cname != NULL);
264 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
265 	ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
266 	ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
267 
268 	cname = nvlist_next(cnvl, &ctype, &ccookie);
269 	ATF_REQUIRE(cname != NULL);
270 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
271 	ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
272 	ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
273 
274 	cname = nvlist_next(cnvl, &ctype, &ccookie);
275 	ATF_REQUIRE(cname != NULL);
276 	ATF_REQUIRE(ctype == NV_TYPE_STRING);
277 	ATF_REQUIRE(strcmp(cname, "nvlist/string/") == 0);
278 	ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
279 
280 	cname = nvlist_next(cnvl, &ctype, &ccookie);
281 	ATF_REQUIRE(cname != NULL);
282 	ATF_REQUIRE(ctype == NV_TYPE_STRING);
283 	ATF_REQUIRE(strcmp(cname, "nvlist/string/x") == 0);
284 	ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
285 
286 	cname = nvlist_next(cnvl, &ctype, &ccookie);
287 	ATF_REQUIRE(cname != NULL);
288 	ATF_REQUIRE(ctype == NV_TYPE_STRING);
289 	ATF_REQUIRE(strcmp(cname, "nvlist/string/" ALPHABET) == 0);
290 	ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), ALPHABET) == 0);
291 
292 	cname = nvlist_next(cnvl, &ctype, &ccookie);
293 	ATF_REQUIRE(cname != NULL);
294 	ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
295 	ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
296 	ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
297 
298 	cname = nvlist_next(cnvl, &ctype, &ccookie);
299 	ATF_REQUIRE(cname != NULL);
300 	ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
301 	ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/pipe_rd") == 0);
302 	ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
303 
304 	cname = nvlist_next(cnvl, &ctype, &ccookie);
305 	ATF_REQUIRE(cname != NULL);
306 	ATF_REQUIRE(ctype == NV_TYPE_BINARY);
307 	ATF_REQUIRE(strcmp(cname, "nvlist/binary/x") == 0);
308 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
309 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
310 	ATF_REQUIRE(size == 1);
311 
312 	cname = nvlist_next(cnvl, &ctype, &ccookie);
313 	ATF_REQUIRE(cname != NULL);
314 	ATF_REQUIRE(ctype == NV_TYPE_BINARY);
315 	ATF_REQUIRE(strcmp(cname, "nvlist/binary/" ALPHABET) == 0);
316 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), ALPHABET,
317 	    sizeof(ALPHABET)) == 0);
318 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), ALPHABET,
319 	    sizeof(ALPHABET)) == 0);
320 	ATF_REQUIRE(size == sizeof(ALPHABET));
321 
322 	cname = nvlist_next(cnvl, &ctype, &ccookie);
323 	ATF_REQUIRE(cname != NULL);
324 	ATF_REQUIRE(ctype == NV_TYPE_NVLIST);
325 	ATF_REQUIRE(strcmp(cname, "nvlist/nvlist/empty") == 0);
326 	empty = nvlist_get_nvlist(cnvl, cname);
327 	ATF_REQUIRE(nvlist_empty(empty));
328 
329 	cname = nvlist_next(cnvl, &ctype, &ccookie);
330 	ATF_REQUIRE(cname == NULL);
331 
332 	name = nvlist_next(nvl, &type, &cookie);
333 	ATF_REQUIRE(name == NULL);
334 
335 	nvlist_destroy(nvl);
336 }
337 
338 static void
339 nvlist_send_recv__send_nvlist(short sotype)
340 {
341 	int socks[2], status;
342 	pid_t pid;
343 
344 	ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
345 
346 	pid = fork();
347 	ATF_REQUIRE(pid >= 0);
348 	if (pid == 0) {
349 		/* Child. */
350 		(void)close(socks[0]);
351 		send_nvlist_child(socks[1]);
352 		_exit(0);
353 	}
354 
355 	(void)close(socks[1]);
356 	send_nvlist_parent(socks[0]);
357 
358 	ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
359 	ATF_REQUIRE(status == 0);
360 }
361 
362 static void
363 nvlist_send_recv__send_closed_fd(short sotype)
364 {
365 	nvlist_t *nvl;
366 	int socks[2];
367 
368 	ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
369 
370 	nvl = nvlist_create(0);
371 	ATF_REQUIRE(nvl != NULL);
372 	nvlist_add_descriptor(nvl, "fd", 12345);
373 	ATF_REQUIRE(nvlist_error(nvl) == EBADF);
374 
375 	ATF_REQUIRE_ERRNO(EBADF, nvlist_send(socks[1], nvl) != 0);
376 }
377 
378 static int
379 nopenfds(void)
380 {
381 	size_t len;
382 	int error, mib[4], n;
383 
384 	mib[0] = CTL_KERN;
385 	mib[1] = KERN_PROC;
386 	mib[2] = KERN_PROC_NFDS;
387 	mib[3] = 0;
388 
389 	len = sizeof(n);
390 	error = sysctl(mib, nitems(mib), &n, &len, NULL, 0);
391 	if (error != 0)
392 		return (-1);
393 	return (n);
394 }
395 
396 #define	NFDS	512
397 
398 static void
399 send_many_fds_child(int sock)
400 {
401 	char name[16];
402 	nvlist_t *nvl;
403 	int anfds, bnfds, fd, i, j;
404 
405 	fd = open(_PATH_DEVNULL, O_RDONLY);
406 	ATF_REQUIRE(fd >= 0);
407 
408 	for (i = 1; i < NFDS; i++) {
409 		nvl = nvlist_create(0);
410 		bnfds = nopenfds();
411 		if (bnfds == -1)
412 			err(EXIT_FAILURE, "sysctl");
413 
414 		for (j = 0; j < i; j++) {
415 			snprintf(name, sizeof(name), "fd%d", j);
416 			nvlist_add_descriptor(nvl, name, fd);
417 		}
418 		nvlist_send(sock, nvl);
419 		nvlist_destroy(nvl);
420 
421 		anfds = nopenfds();
422 		if (anfds == -1)
423 			err(EXIT_FAILURE, "sysctl");
424 		if (anfds != bnfds)
425 			errx(EXIT_FAILURE, "fd count mismatch");
426 	}
427 }
428 
429 static void
430 nvlist_send_recv__send_many_fds(short sotype)
431 {
432 	char name[16];
433 	nvlist_t *nvl;
434 	int anfds, bnfds, fd, i, j, socks[2], status;
435 	pid_t pid;
436 
437 	ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
438 
439 	pid = fork();
440 	ATF_REQUIRE(pid >= 0);
441 	if (pid == 0) {
442 		/* Child. */
443 		(void)close(socks[0]);
444 		send_many_fds_child(socks[1]);
445 		_exit(0);
446 	}
447 
448 	(void)close(socks[1]);
449 
450 	for (i = 1; i < NFDS; i++) {
451 		bnfds = nopenfds();
452 		ATF_REQUIRE(bnfds != -1);
453 
454 		nvl = nvlist_recv(socks[0], 0);
455 		ATF_REQUIRE(nvl != NULL);
456 		for (j = 0; j < i; j++) {
457 			snprintf(name, sizeof(name), "fd%d", j);
458 			fd = nvlist_take_descriptor(nvl, name);
459 			ATF_REQUIRE(close(fd) == 0);
460 		}
461 		nvlist_destroy(nvl);
462 
463 		anfds = nopenfds();
464 		ATF_REQUIRE(anfds != -1);
465 		ATF_REQUIRE(anfds == bnfds);
466 	}
467 
468 	ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
469 	ATF_REQUIRE(status == 0);
470 }
471 
472 /*
473  * This test needs to tune the following sysctl's:
474  *      net.local.dgram.maxdgram
475  *      net.local.dgram.recvspace
476  */
477 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__dgram);
478 ATF_TC_BODY(nvlist_send_recv__send_many_fds__dgram, tc)
479 {
480 	u_long maxdgram, recvspace, temp_maxdgram, temp_recvspace;
481 	size_t len;
482 	int error;
483 
484 	atf_tc_skip("https://bugs.freebsd.org/260891");
485 
486 	/* size of the largest datagram to send */
487 	temp_maxdgram = 16772;
488 	len = sizeof(maxdgram);
489 	error = sysctlbyname("net.local.dgram.maxdgram", &maxdgram,
490 	    &len, &temp_maxdgram, sizeof(temp_maxdgram));
491 	if (error != 0)
492 		atf_tc_skip("cannot set net.local.dgram.maxdgram: %s", strerror(errno));
493 
494 	/*
495 	 * The receive queue fills up quicker than it's being emptied,
496 	 * bump it to a sufficiently large enough value, 1M.
497 	 */
498 	temp_recvspace = 1048576;
499 	len = sizeof(recvspace);
500 	error = sysctlbyname("net.local.dgram.recvspace", &recvspace,
501 	    &len, &temp_recvspace, sizeof(temp_recvspace));
502 	if (error != 0)
503 		atf_tc_skip("cannot set net.local.dgram.recvspace: %s", strerror(errno));
504 
505 	nvlist_send_recv__send_many_fds(SOCK_DGRAM);
506 
507 	/* restore original values */
508 	error = sysctlbyname("net.local.dgram.maxdgram", NULL, NULL, &maxdgram, sizeof(maxdgram));
509 	if (error != 0)
510 		warn("failed to restore net.local.dgram.maxdgram");
511 
512 	error = sysctlbyname("net.local.dgram.recvspace", NULL, NULL, &recvspace, sizeof(recvspace));
513 	if (error != 0)
514 		warn("failed to restore net.local.dgram.recvspace");
515 }
516 
517 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__stream);
518 ATF_TC_BODY(nvlist_send_recv__send_many_fds__stream, tc)
519 {
520 	nvlist_send_recv__send_many_fds(SOCK_STREAM);
521 }
522 
523 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__dgram);
524 ATF_TC_BODY(nvlist_send_recv__send_nvlist__dgram, tc)
525 {
526 	nvlist_send_recv__send_nvlist(SOCK_DGRAM);
527 }
528 
529 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__stream);
530 ATF_TC_BODY(nvlist_send_recv__send_nvlist__stream, tc)
531 {
532 	nvlist_send_recv__send_nvlist(SOCK_STREAM);
533 }
534 
535 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram);
536 ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc)
537 {
538 	nvlist_send_recv__send_closed_fd(SOCK_DGRAM);
539 }
540 
541 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__stream);
542 ATF_TC_BODY(nvlist_send_recv__send_closed_fd__stream, tc)
543 {
544 	nvlist_send_recv__send_closed_fd(SOCK_STREAM);
545 }
546 
547 ATF_TP_ADD_TCS(tp)
548 {
549 
550 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram);
551 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream);
552 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram);
553 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream);
554 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram);
555 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream);
556 
557 	return (atf_no_error());
558 }
559