]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libnv/tests/nvlist_send_recv_test.c
sys/{x86,amd64}: remove one of doubled ;s
[FreeBSD/FreeBSD.git] / lib / libnv / tests / nvlist_send_recv_test.c
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 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/socket.h>
35 #include <sys/sysctl.h>
36 #include <sys/wait.h>
37 #include <sys/nv.h>
38
39 #include <stdlib.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <paths.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #include <atf-c.h>
49
50 #define ALPHABET        "abcdefghijklmnopqrstuvwxyz"
51 #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
52
53 static void
54 send_nvlist_child(int sock)
55 {
56         nvlist_t *nvl;
57         nvlist_t *empty;
58         int pfd[2];
59
60         nvl = nvlist_create(0);
61         empty = nvlist_create(0);
62
63         nvlist_add_bool(nvl, "nvlist/bool/true", true);
64         nvlist_add_bool(nvl, "nvlist/bool/false", false);
65         nvlist_add_number(nvl, "nvlist/number/0", 0);
66         nvlist_add_number(nvl, "nvlist/number/1", 1);
67         nvlist_add_number(nvl, "nvlist/number/-1", -1);
68         nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
69         nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
70         nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
71         nvlist_add_string(nvl, "nvlist/string/", "");
72         nvlist_add_string(nvl, "nvlist/string/x", "x");
73         nvlist_add_string(nvl, "nvlist/string/" ALPHABET, ALPHABET);
74
75         nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO",
76             STDERR_FILENO);
77         if (pipe(pfd) == -1)
78                 err(EXIT_FAILURE, "pipe");
79         if (write(pfd[1], "test", 4) != 4)
80                 err(EXIT_FAILURE, "write");
81         close(pfd[1]);
82         nvlist_add_descriptor(nvl, "nvlist/descriptor/pipe_rd", pfd[0]);
83         close(pfd[0]);
84
85         nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
86         nvlist_add_binary(nvl, "nvlist/binary/" ALPHABET, ALPHABET,
87             sizeof(ALPHABET));
88         nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
89         nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
90
91         nvlist_send(sock, nvl);
92
93         nvlist_destroy(nvl);
94 }
95
96 static void
97 send_nvlist_parent(int sock)
98 {
99         nvlist_t *nvl;
100         const nvlist_t *cnvl, *empty;
101         const char *name, *cname;
102         void *cookie, *ccookie;
103         int type, ctype, fd;
104         size_t size;
105         char buf[4];
106
107         nvl = nvlist_recv(sock, 0);
108         ATF_REQUIRE(nvlist_error(nvl) == 0);
109         if (nvlist_error(nvl) != 0)
110                 err(1, "nvlist_recv() failed");
111
112         cookie = NULL;
113
114         name = nvlist_next(nvl, &type, &cookie);
115         ATF_REQUIRE(name != NULL);
116         ATF_REQUIRE(type == NV_TYPE_BOOL);
117         ATF_REQUIRE(strcmp(name, "nvlist/bool/true") == 0);
118         ATF_REQUIRE(nvlist_get_bool(nvl, name) == true);
119
120         name = nvlist_next(nvl, &type, &cookie);
121         ATF_REQUIRE(name != NULL);
122         ATF_REQUIRE(type == NV_TYPE_BOOL);
123         ATF_REQUIRE(strcmp(name, "nvlist/bool/false") == 0);
124         ATF_REQUIRE(nvlist_get_bool(nvl, name) == false);
125
126         name = nvlist_next(nvl, &type, &cookie);
127         ATF_REQUIRE(name != NULL);
128         ATF_REQUIRE(type == NV_TYPE_NUMBER);
129         ATF_REQUIRE(strcmp(name, "nvlist/number/0") == 0);
130         ATF_REQUIRE(nvlist_get_number(nvl, name) == 0);
131
132         name = nvlist_next(nvl, &type, &cookie);
133         ATF_REQUIRE(name != NULL);
134         ATF_REQUIRE(type == NV_TYPE_NUMBER);
135         ATF_REQUIRE(strcmp(name, "nvlist/number/1") == 0);
136         ATF_REQUIRE(nvlist_get_number(nvl, name) == 1);
137
138         name = nvlist_next(nvl, &type, &cookie);
139         ATF_REQUIRE(name != NULL);
140         ATF_REQUIRE(type == NV_TYPE_NUMBER);
141         ATF_REQUIRE(strcmp(name, "nvlist/number/-1") == 0);
142         ATF_REQUIRE((int)nvlist_get_number(nvl, name) == -1);
143
144         name = nvlist_next(nvl, &type, &cookie);
145         ATF_REQUIRE(name != NULL);
146         ATF_REQUIRE(type == NV_TYPE_NUMBER);
147         ATF_REQUIRE(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
148         ATF_REQUIRE(nvlist_get_number(nvl, name) == UINT64_MAX);
149
150         name = nvlist_next(nvl, &type, &cookie);
151         ATF_REQUIRE(name != NULL);
152         ATF_REQUIRE(type == NV_TYPE_NUMBER);
153         ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MIN") == 0);
154         ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
155
156         name = nvlist_next(nvl, &type, &cookie);
157         ATF_REQUIRE(name != NULL);
158         ATF_REQUIRE(type == NV_TYPE_NUMBER);
159         ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MAX") == 0);
160         ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
161
162         name = nvlist_next(nvl, &type, &cookie);
163         ATF_REQUIRE(name != NULL);
164         ATF_REQUIRE(type == NV_TYPE_STRING);
165         ATF_REQUIRE(strcmp(name, "nvlist/string/") == 0);
166         ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "") == 0);
167
168         name = nvlist_next(nvl, &type, &cookie);
169         ATF_REQUIRE(name != NULL);
170         ATF_REQUIRE(type == NV_TYPE_STRING);
171         ATF_REQUIRE(strcmp(name, "nvlist/string/x") == 0);
172         ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "x") == 0);
173
174         name = nvlist_next(nvl, &type, &cookie);
175         ATF_REQUIRE(name != NULL);
176         ATF_REQUIRE(type == NV_TYPE_STRING);
177         ATF_REQUIRE(strcmp(name, "nvlist/string/" ALPHABET) == 0);
178         ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), ALPHABET) == 0);
179
180         name = nvlist_next(nvl, &type, &cookie);
181         ATF_REQUIRE(name != NULL);
182         ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
183         ATF_REQUIRE(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
184         ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(nvl, name)));
185
186         name = nvlist_next(nvl, &type, &cookie);
187         ATF_REQUIRE(name != NULL);
188         ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
189         ATF_REQUIRE(strcmp(name, "nvlist/descriptor/pipe_rd") == 0);
190         fd = nvlist_get_descriptor(nvl, name);
191         ATF_REQUIRE(fd_is_valid(fd));
192         ATF_REQUIRE(read(fd, buf, sizeof(buf)) == 4);
193         ATF_REQUIRE(strncmp(buf, "test", sizeof(buf)) == 0);
194
195         name = nvlist_next(nvl, &type, &cookie);
196         ATF_REQUIRE(name != NULL);
197         ATF_REQUIRE(type == NV_TYPE_BINARY);
198         ATF_REQUIRE(strcmp(name, "nvlist/binary/x") == 0);
199         ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
200         ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
201         ATF_REQUIRE(size == 1);
202
203         name = nvlist_next(nvl, &type, &cookie);
204         ATF_REQUIRE(name != NULL);
205         ATF_REQUIRE(type == NV_TYPE_BINARY);
206         ATF_REQUIRE(strcmp(name, "nvlist/binary/" ALPHABET) == 0);
207         ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), ALPHABET,
208             sizeof(ALPHABET)) == 0);
209         ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), ALPHABET,
210             sizeof(ALPHABET)) == 0);
211         ATF_REQUIRE(size == sizeof(ALPHABET));
212
213         name = nvlist_next(nvl, &type, &cookie);
214         ATF_REQUIRE(name != NULL);
215         ATF_REQUIRE(type == NV_TYPE_NVLIST);
216         ATF_REQUIRE(strcmp(name, "nvlist/nvlist/empty") == 0);
217         cnvl = nvlist_get_nvlist(nvl, name);
218         ATF_REQUIRE(nvlist_empty(cnvl));
219
220         name = nvlist_next(nvl, &type, &cookie);
221         ATF_REQUIRE(name != NULL);
222         ATF_REQUIRE(type == NV_TYPE_NVLIST);
223         ATF_REQUIRE(strcmp(name, "nvlist/nvlist") == 0);
224         cnvl = nvlist_get_nvlist(nvl, name);
225
226         ccookie = NULL;
227
228         cname = nvlist_next(cnvl, &ctype, &ccookie);
229         ATF_REQUIRE(cname != NULL);
230         ATF_REQUIRE(ctype == NV_TYPE_BOOL);
231         ATF_REQUIRE(strcmp(cname, "nvlist/bool/true") == 0);
232         ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == true);
233
234         cname = nvlist_next(cnvl, &ctype, &ccookie);
235         ATF_REQUIRE(cname != NULL);
236         ATF_REQUIRE(ctype == NV_TYPE_BOOL);
237         ATF_REQUIRE(strcmp(cname, "nvlist/bool/false") == 0);
238         ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == false);
239
240         cname = nvlist_next(cnvl, &ctype, &ccookie);
241         ATF_REQUIRE(cname != NULL);
242         ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
243         ATF_REQUIRE(strcmp(cname, "nvlist/number/0") == 0);
244         ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 0);
245
246         cname = nvlist_next(cnvl, &ctype, &ccookie);
247         ATF_REQUIRE(cname != NULL);
248         ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
249         ATF_REQUIRE(strcmp(cname, "nvlist/number/1") == 0);
250         ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 1);
251
252         cname = nvlist_next(cnvl, &ctype, &ccookie);
253         ATF_REQUIRE(cname != NULL);
254         ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
255         ATF_REQUIRE(strcmp(cname, "nvlist/number/-1") == 0);
256         ATF_REQUIRE((int)nvlist_get_number(cnvl, cname) == -1);
257
258         cname = nvlist_next(cnvl, &ctype, &ccookie);
259         ATF_REQUIRE(cname != NULL);
260         ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
261         ATF_REQUIRE(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
262         ATF_REQUIRE(nvlist_get_number(cnvl, cname) == UINT64_MAX);
263
264         cname = nvlist_next(cnvl, &ctype, &ccookie);
265         ATF_REQUIRE(cname != NULL);
266         ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
267         ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
268         ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
269
270         cname = nvlist_next(cnvl, &ctype, &ccookie);
271         ATF_REQUIRE(cname != NULL);
272         ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
273         ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
274         ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
275
276         cname = nvlist_next(cnvl, &ctype, &ccookie);
277         ATF_REQUIRE(cname != NULL);
278         ATF_REQUIRE(ctype == NV_TYPE_STRING);
279         ATF_REQUIRE(strcmp(cname, "nvlist/string/") == 0);
280         ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
281
282         cname = nvlist_next(cnvl, &ctype, &ccookie);
283         ATF_REQUIRE(cname != NULL);
284         ATF_REQUIRE(ctype == NV_TYPE_STRING);
285         ATF_REQUIRE(strcmp(cname, "nvlist/string/x") == 0);
286         ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
287
288         cname = nvlist_next(cnvl, &ctype, &ccookie);
289         ATF_REQUIRE(cname != NULL);
290         ATF_REQUIRE(ctype == NV_TYPE_STRING);
291         ATF_REQUIRE(strcmp(cname, "nvlist/string/" ALPHABET) == 0);
292         ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), ALPHABET) == 0);
293
294         cname = nvlist_next(cnvl, &ctype, &ccookie);
295         ATF_REQUIRE(cname != NULL);
296         ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
297         ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
298         ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
299
300         cname = nvlist_next(cnvl, &ctype, &ccookie);
301         ATF_REQUIRE(cname != NULL);
302         ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
303         ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/pipe_rd") == 0);
304         ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
305
306         cname = nvlist_next(cnvl, &ctype, &ccookie);
307         ATF_REQUIRE(cname != NULL);
308         ATF_REQUIRE(ctype == NV_TYPE_BINARY);
309         ATF_REQUIRE(strcmp(cname, "nvlist/binary/x") == 0);
310         ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
311         ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
312         ATF_REQUIRE(size == 1);
313
314         cname = nvlist_next(cnvl, &ctype, &ccookie);
315         ATF_REQUIRE(cname != NULL);
316         ATF_REQUIRE(ctype == NV_TYPE_BINARY);
317         ATF_REQUIRE(strcmp(cname, "nvlist/binary/" ALPHABET) == 0);
318         ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), ALPHABET,
319             sizeof(ALPHABET)) == 0);
320         ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), ALPHABET,
321             sizeof(ALPHABET)) == 0);
322         ATF_REQUIRE(size == sizeof(ALPHABET));
323
324         cname = nvlist_next(cnvl, &ctype, &ccookie);
325         ATF_REQUIRE(cname != NULL);
326         ATF_REQUIRE(ctype == NV_TYPE_NVLIST);
327         ATF_REQUIRE(strcmp(cname, "nvlist/nvlist/empty") == 0);
328         empty = nvlist_get_nvlist(cnvl, cname);
329         ATF_REQUIRE(nvlist_empty(empty));
330
331         cname = nvlist_next(cnvl, &ctype, &ccookie);
332         ATF_REQUIRE(cname == NULL);
333
334         name = nvlist_next(nvl, &type, &cookie);
335         ATF_REQUIRE(name == NULL);
336
337         nvlist_destroy(nvl);
338 }
339
340 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist);
341 ATF_TC_BODY(nvlist_send_recv__send_nvlist, tc)
342 {
343         int socks[2], status;
344         pid_t pid;
345
346         ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0);
347
348         pid = fork();
349         ATF_REQUIRE(pid >= 0);
350         if (pid == 0) {
351                 /* Child. */
352                 (void)close(socks[0]);
353                 send_nvlist_child(socks[1]);
354                 _exit(0);
355         }
356
357         (void)close(socks[1]);
358         send_nvlist_parent(socks[0]);
359
360         ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
361         ATF_REQUIRE(status == 0);
362 }
363
364 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd);
365 ATF_TC_BODY(nvlist_send_recv__send_closed_fd, tc)
366 {
367         nvlist_t *nvl;
368         int socks[2];
369
370         ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0);
371
372         nvl = nvlist_create(0);
373         ATF_REQUIRE(nvl != NULL);
374         nvlist_add_descriptor(nvl, "fd", 12345);
375         ATF_REQUIRE(nvlist_error(nvl) == EBADF);
376
377         ATF_REQUIRE_ERRNO(EBADF, nvlist_send(socks[1], nvl) != 0);
378 }
379
380 static int
381 nopenfds(void)
382 {
383         size_t len;
384         int error, mib[4], n;
385
386         mib[0] = CTL_KERN;
387         mib[1] = KERN_PROC;
388         mib[2] = KERN_PROC_NFDS;
389         mib[3] = 0;
390
391         len = sizeof(n);
392         error = sysctl(mib, nitems(mib), &n, &len, NULL, 0);
393         if (error != 0)
394                 return (-1);
395         return (n);
396 }
397
398 #define NFDS    512
399
400 static void
401 send_many_fds_child(int sock)
402 {
403         char name[16];
404         nvlist_t *nvl;
405         int anfds, bnfds, fd, i, j;
406
407         fd = open(_PATH_DEVNULL, O_RDONLY);
408         ATF_REQUIRE(fd >= 0);
409
410         for (i = 1; i < NFDS; i++) {
411                 nvl = nvlist_create(0);
412                 bnfds = nopenfds();
413                 if (bnfds == -1)
414                         err(EXIT_FAILURE, "sysctl");
415
416                 for (j = 0; j < i; j++) {
417                         snprintf(name, sizeof(name), "fd%d", j);
418                         nvlist_add_descriptor(nvl, name, fd);
419                 }
420                 nvlist_send(sock, nvl);
421                 nvlist_destroy(nvl);
422
423                 anfds = nopenfds();
424                 if (anfds == -1)
425                         err(EXIT_FAILURE, "sysctl");
426                 if (anfds != bnfds)
427                         errx(EXIT_FAILURE, "fd count mismatch");
428         }
429 }
430
431 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds);
432 ATF_TC_BODY(nvlist_send_recv__send_many_fds, tc)
433 {
434         char name[16];
435         nvlist_t *nvl;
436         int anfds, bnfds, fd, i, j, socks[2], status;
437         pid_t pid;
438
439         ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0);
440
441         pid = fork();
442         ATF_REQUIRE(pid >= 0);
443         if (pid == 0) {
444                 /* Child. */
445                 (void)close(socks[0]);
446                 send_many_fds_child(socks[1]);
447                 _exit(0);
448         }
449
450         (void)close(socks[1]);
451
452         for (i = 1; i < NFDS; i++) {
453                 bnfds = nopenfds();
454                 ATF_REQUIRE(bnfds != -1);
455
456                 nvl = nvlist_recv(socks[0], 0);
457                 ATF_REQUIRE(nvl != NULL);
458                 for (j = 0; j < i; j++) {
459                         snprintf(name, sizeof(name), "fd%d", j);
460                         fd = nvlist_take_descriptor(nvl, name);
461                         ATF_REQUIRE(close(fd) == 0);
462                 }
463                 nvlist_destroy(nvl);
464
465                 anfds = nopenfds();
466                 ATF_REQUIRE(anfds != -1);
467                 ATF_REQUIRE(anfds == bnfds);
468         }
469
470         ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
471         ATF_REQUIRE(status == 0);
472 }
473
474 ATF_TP_ADD_TCS(tp)
475 {
476
477         ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist);
478         ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd);
479         ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds);
480
481         return (atf_no_error());
482 }