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 * $FreeBSD: stable/12/lib/libnv/tests/nvlist_send_recv_test.c 370090 2021-07-06 18:26:32Z git2svn $
30 */
31
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/wait.h>
35 #include <sys/nv.h>
36
37 #include <err.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 static int ntest = 1;
45
46 #define CHECK(expr) do { \
47 if ((expr)) \
48 printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \
49 else \
50 printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
51 ntest++; \
52 } while (0)
53
54 #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
55
56 static void
child(int sock)57 child(int sock)
58 {
59 nvlist_t *nvl;
60 nvlist_t *empty;
61
62 nvl = nvlist_create(0);
63 empty = nvlist_create(0);
64
65 nvlist_add_bool(nvl, "nvlist/bool/true", true);
66 nvlist_add_bool(nvl, "nvlist/bool/false", false);
67 nvlist_add_number(nvl, "nvlist/number/0", 0);
68 nvlist_add_number(nvl, "nvlist/number/1", 1);
69 nvlist_add_number(nvl, "nvlist/number/-1", -1);
70 nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
71 nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
72 nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
73 nvlist_add_string(nvl, "nvlist/string/", "");
74 nvlist_add_string(nvl, "nvlist/string/x", "x");
75 nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
76 nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
77 nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
78 nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
79 nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
80 nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
81
82 nvlist_send(sock, nvl);
83
84 nvlist_destroy(nvl);
85 }
86
87 static void
parent(int sock)88 parent(int sock)
89 {
90 nvlist_t *nvl;
91 const nvlist_t *cnvl, *empty;
92 const char *name, *cname;
93 void *cookie, *ccookie;
94 int type, ctype;
95 size_t size;
96
97 nvl = nvlist_recv(sock, 0);
98 CHECK(nvlist_error(nvl) == 0);
99 if (nvlist_error(nvl) != 0)
100 err(1, "nvlist_recv() failed");
101
102 cookie = NULL;
103
104 name = nvlist_next(nvl, &type, &cookie);
105 CHECK(name != NULL);
106 CHECK(type == NV_TYPE_BOOL);
107 CHECK(strcmp(name, "nvlist/bool/true") == 0);
108 CHECK(nvlist_get_bool(nvl, name) == true);
109
110 name = nvlist_next(nvl, &type, &cookie);
111 CHECK(name != NULL);
112 CHECK(type == NV_TYPE_BOOL);
113 CHECK(strcmp(name, "nvlist/bool/false") == 0);
114 CHECK(nvlist_get_bool(nvl, name) == false);
115
116 name = nvlist_next(nvl, &type, &cookie);
117 CHECK(name != NULL);
118 CHECK(type == NV_TYPE_NUMBER);
119 CHECK(strcmp(name, "nvlist/number/0") == 0);
120 CHECK(nvlist_get_number(nvl, name) == 0);
121
122 name = nvlist_next(nvl, &type, &cookie);
123 CHECK(name != NULL);
124 CHECK(type == NV_TYPE_NUMBER);
125 CHECK(strcmp(name, "nvlist/number/1") == 0);
126 CHECK(nvlist_get_number(nvl, name) == 1);
127
128 name = nvlist_next(nvl, &type, &cookie);
129 CHECK(name != NULL);
130 CHECK(type == NV_TYPE_NUMBER);
131 CHECK(strcmp(name, "nvlist/number/-1") == 0);
132 CHECK((int)nvlist_get_number(nvl, name) == -1);
133
134 name = nvlist_next(nvl, &type, &cookie);
135 CHECK(name != NULL);
136 CHECK(type == NV_TYPE_NUMBER);
137 CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
138 CHECK(nvlist_get_number(nvl, name) == UINT64_MAX);
139
140 name = nvlist_next(nvl, &type, &cookie);
141 CHECK(name != NULL);
142 CHECK(type == NV_TYPE_NUMBER);
143 CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0);
144 CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
145
146 name = nvlist_next(nvl, &type, &cookie);
147 CHECK(name != NULL);
148 CHECK(type == NV_TYPE_NUMBER);
149 CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0);
150 CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
151
152 name = nvlist_next(nvl, &type, &cookie);
153 CHECK(name != NULL);
154 CHECK(type == NV_TYPE_STRING);
155 CHECK(strcmp(name, "nvlist/string/") == 0);
156 CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0);
157
158 name = nvlist_next(nvl, &type, &cookie);
159 CHECK(name != NULL);
160 CHECK(type == NV_TYPE_STRING);
161 CHECK(strcmp(name, "nvlist/string/x") == 0);
162 CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0);
163
164 name = nvlist_next(nvl, &type, &cookie);
165 CHECK(name != NULL);
166 CHECK(type == NV_TYPE_STRING);
167 CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
168 CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0);
169
170 name = nvlist_next(nvl, &type, &cookie);
171 CHECK(name != NULL);
172 CHECK(type == NV_TYPE_DESCRIPTOR);
173 CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
174 CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name)));
175
176 name = nvlist_next(nvl, &type, &cookie);
177 CHECK(name != NULL);
178 CHECK(type == NV_TYPE_BINARY);
179 CHECK(strcmp(name, "nvlist/binary/x") == 0);
180 CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
181 CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
182 CHECK(size == 1);
183
184 name = nvlist_next(nvl, &type, &cookie);
185 CHECK(name != NULL);
186 CHECK(type == NV_TYPE_BINARY);
187 CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
188 CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
189 CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
190 CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
191
192 name = nvlist_next(nvl, &type, &cookie);
193 CHECK(name != NULL);
194 CHECK(type == NV_TYPE_NVLIST);
195 CHECK(strcmp(name, "nvlist/nvlist/empty") == 0);
196 cnvl = nvlist_get_nvlist(nvl, name);
197 CHECK(nvlist_empty(cnvl));
198
199 name = nvlist_next(nvl, &type, &cookie);
200 CHECK(name != NULL);
201 CHECK(type == NV_TYPE_NVLIST);
202 CHECK(strcmp(name, "nvlist/nvlist") == 0);
203 cnvl = nvlist_get_nvlist(nvl, name);
204
205 ccookie = NULL;
206
207 cname = nvlist_next(cnvl, &ctype, &ccookie);
208 CHECK(cname != NULL);
209 CHECK(ctype == NV_TYPE_BOOL);
210 CHECK(strcmp(cname, "nvlist/bool/true") == 0);
211 CHECK(nvlist_get_bool(cnvl, cname) == true);
212
213 cname = nvlist_next(cnvl, &ctype, &ccookie);
214 CHECK(cname != NULL);
215 CHECK(ctype == NV_TYPE_BOOL);
216 CHECK(strcmp(cname, "nvlist/bool/false") == 0);
217 CHECK(nvlist_get_bool(cnvl, cname) == false);
218
219 cname = nvlist_next(cnvl, &ctype, &ccookie);
220 CHECK(cname != NULL);
221 CHECK(ctype == NV_TYPE_NUMBER);
222 CHECK(strcmp(cname, "nvlist/number/0") == 0);
223 CHECK(nvlist_get_number(cnvl, cname) == 0);
224
225 cname = nvlist_next(cnvl, &ctype, &ccookie);
226 CHECK(cname != NULL);
227 CHECK(ctype == NV_TYPE_NUMBER);
228 CHECK(strcmp(cname, "nvlist/number/1") == 0);
229 CHECK(nvlist_get_number(cnvl, cname) == 1);
230
231 cname = nvlist_next(cnvl, &ctype, &ccookie);
232 CHECK(cname != NULL);
233 CHECK(ctype == NV_TYPE_NUMBER);
234 CHECK(strcmp(cname, "nvlist/number/-1") == 0);
235 CHECK((int)nvlist_get_number(cnvl, cname) == -1);
236
237 cname = nvlist_next(cnvl, &ctype, &ccookie);
238 CHECK(cname != NULL);
239 CHECK(ctype == NV_TYPE_NUMBER);
240 CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
241 CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX);
242
243 cname = nvlist_next(cnvl, &ctype, &ccookie);
244 CHECK(cname != NULL);
245 CHECK(ctype == NV_TYPE_NUMBER);
246 CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
247 CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
248
249 cname = nvlist_next(cnvl, &ctype, &ccookie);
250 CHECK(cname != NULL);
251 CHECK(ctype == NV_TYPE_NUMBER);
252 CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
253 CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
254
255 cname = nvlist_next(cnvl, &ctype, &ccookie);
256 CHECK(cname != NULL);
257 CHECK(ctype == NV_TYPE_STRING);
258 CHECK(strcmp(cname, "nvlist/string/") == 0);
259 CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
260
261 cname = nvlist_next(cnvl, &ctype, &ccookie);
262 CHECK(cname != NULL);
263 CHECK(ctype == NV_TYPE_STRING);
264 CHECK(strcmp(cname, "nvlist/string/x") == 0);
265 CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
266
267 cname = nvlist_next(cnvl, &ctype, &ccookie);
268 CHECK(cname != NULL);
269 CHECK(ctype == NV_TYPE_STRING);
270 CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
271 CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0);
272
273 cname = nvlist_next(cnvl, &ctype, &ccookie);
274 CHECK(cname != NULL);
275 CHECK(ctype == NV_TYPE_DESCRIPTOR);
276 CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
277 CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
278
279 cname = nvlist_next(cnvl, &ctype, &ccookie);
280 CHECK(cname != NULL);
281 CHECK(ctype == NV_TYPE_BINARY);
282 CHECK(strcmp(cname, "nvlist/binary/x") == 0);
283 CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
284 CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
285 CHECK(size == 1);
286
287 cname = nvlist_next(cnvl, &ctype, &ccookie);
288 CHECK(cname != NULL);
289 CHECK(ctype == NV_TYPE_BINARY);
290 CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
291 CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
292 CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
293 CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
294
295 cname = nvlist_next(cnvl, &ctype, &ccookie);
296 CHECK(cname != NULL);
297 CHECK(ctype == NV_TYPE_NVLIST);
298 CHECK(strcmp(cname, "nvlist/nvlist/empty") == 0);
299 empty = nvlist_get_nvlist(cnvl, cname);
300 CHECK(nvlist_empty(empty));
301
302 cname = nvlist_next(cnvl, &ctype, &ccookie);
303 CHECK(cname == NULL);
304
305 name = nvlist_next(nvl, &type, &cookie);
306 CHECK(name == NULL);
307
308 nvlist_destroy(nvl);
309 }
310
311 static void
send_nvlist(void)312 send_nvlist(void)
313 {
314 int status, socks[2];
315 pid_t pid;
316
317 if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
318 err(1, "socketpair() failed");
319 pid = fork();
320 switch (pid) {
321 case -1:
322 /* Failure. */
323 err(1, "unable to fork");
324 case 0:
325 /* Child. */
326 close(socks[0]);
327 child(socks[1]);
328 _exit(0);
329 default:
330 /* Parent. */
331 close(socks[1]);
332 parent(socks[0]);
333 break;
334 }
335
336 if (waitpid(pid, &status, 0) < 0)
337 err(1, "waitpid() failed");
338 }
339
340 static void
send_closed_fd(void)341 send_closed_fd(void)
342 {
343 nvlist_t *nvl;
344 int error, socks[2];
345
346 if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
347 err(1, "socketpair() failed");
348
349 nvl = nvlist_create(0);
350 nvlist_add_descriptor(nvl, "fd", 12345);
351 error = nvlist_error(nvl);
352 CHECK(error == EBADF);
353
354 error = nvlist_send(socks[1], nvl);
355 CHECK(error != 0 && errno == EBADF);
356 }
357
358 int
main(void)359 main(void)
360 {
361
362 printf("1..136\n");
363 fflush(stdout);
364
365 send_nvlist();
366 send_closed_fd();
367
368 return (0);
369 }
370