1e4e21ee1SDavid van Moolenbroek /* Tests for sysctl(2) and the MIB service - by D.C. van Moolenbroek */
2e4e21ee1SDavid van Moolenbroek /* This test needs to run as root: many sysctl(2) calls are privileged. */
3e4e21ee1SDavid van Moolenbroek #include <stdlib.h>
4e4e21ee1SDavid van Moolenbroek #include <stdio.h>
5e4e21ee1SDavid van Moolenbroek #include <unistd.h>
6e4e21ee1SDavid van Moolenbroek #include <pwd.h>
7e4e21ee1SDavid van Moolenbroek #include <sys/mman.h>
8e4e21ee1SDavid van Moolenbroek #include <sys/wait.h>
9e4e21ee1SDavid van Moolenbroek #include <minix/sysctl.h>
10e4e21ee1SDavid van Moolenbroek #include <assert.h>
11e4e21ee1SDavid van Moolenbroek
12e4e21ee1SDavid van Moolenbroek #define ITERATIONS 2
13e4e21ee1SDavid van Moolenbroek
14e4e21ee1SDavid van Moolenbroek #include "common.h"
15e4e21ee1SDavid van Moolenbroek
16e4e21ee1SDavid van Moolenbroek #define NONROOT_USER "bin" /* name of any unprivileged user */
17e4e21ee1SDavid van Moolenbroek
18e4e21ee1SDavid van Moolenbroek #define NEXT_VER(n) (((n) + 1 == 0) ? 1 : ((n) + 1)) /* node version + 1 */
19e4e21ee1SDavid van Moolenbroek
20e4e21ee1SDavid van Moolenbroek static void *bad_ptr; /* a pointer to unmapped memory */
21e4e21ee1SDavid van Moolenbroek static unsigned int nodes, objects; /* stats for pre/post test check */
22e4e21ee1SDavid van Moolenbroek
23e4e21ee1SDavid van Moolenbroek /*
24e4e21ee1SDavid van Moolenbroek * Spawn a child process that drops privileges and then executes the given
25e4e21ee1SDavid van Moolenbroek * procedure. The returned PID value is of the dead, cleaned-up child, and
26e4e21ee1SDavid van Moolenbroek * should be used only to check whether the child could store its own PID.
27e4e21ee1SDavid van Moolenbroek */
28e4e21ee1SDavid van Moolenbroek static pid_t
test_nonroot(void (* proc)(void))29e4e21ee1SDavid van Moolenbroek test_nonroot(void (* proc)(void))
30e4e21ee1SDavid van Moolenbroek {
31e4e21ee1SDavid van Moolenbroek struct passwd *pw;
32e4e21ee1SDavid van Moolenbroek pid_t pid;
33e4e21ee1SDavid van Moolenbroek int status;
34e4e21ee1SDavid van Moolenbroek
35e4e21ee1SDavid van Moolenbroek pid = fork();
36e4e21ee1SDavid van Moolenbroek
37e4e21ee1SDavid van Moolenbroek switch (pid) {
38e4e21ee1SDavid van Moolenbroek case -1:
39e4e21ee1SDavid van Moolenbroek e(0);
40e4e21ee1SDavid van Moolenbroek break;
41e4e21ee1SDavid van Moolenbroek case 0:
42e4e21ee1SDavid van Moolenbroek errct = 0;
43e4e21ee1SDavid van Moolenbroek
44e4e21ee1SDavid van Moolenbroek if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
45e4e21ee1SDavid van Moolenbroek
46e4e21ee1SDavid van Moolenbroek if (setuid(pw->pw_uid) != 0) e(0);
47e4e21ee1SDavid van Moolenbroek
48e4e21ee1SDavid van Moolenbroek proc();
49e4e21ee1SDavid van Moolenbroek
50e4e21ee1SDavid van Moolenbroek exit(errct);
51e4e21ee1SDavid van Moolenbroek default:
52e4e21ee1SDavid van Moolenbroek if (wait(&status) != pid) e(0);
53e4e21ee1SDavid van Moolenbroek if (!WIFEXITED(status)) e(0);
54e4e21ee1SDavid van Moolenbroek if (WEXITSTATUS(status) != 0) e(0);
55e4e21ee1SDavid van Moolenbroek }
56e4e21ee1SDavid van Moolenbroek
57e4e21ee1SDavid van Moolenbroek return pid;
58e4e21ee1SDavid van Moolenbroek }
59e4e21ee1SDavid van Moolenbroek
60e4e21ee1SDavid van Moolenbroek /*
61e4e21ee1SDavid van Moolenbroek * Test basic operations from an unprivileged process.
62e4e21ee1SDavid van Moolenbroek */
63e4e21ee1SDavid van Moolenbroek static void
sub87a(void)64e4e21ee1SDavid van Moolenbroek sub87a(void)
65e4e21ee1SDavid van Moolenbroek {
66e4e21ee1SDavid van Moolenbroek size_t oldlen;
67e4e21ee1SDavid van Moolenbroek pid_t pid;
68e4e21ee1SDavid van Moolenbroek bool b;
69e4e21ee1SDavid van Moolenbroek int i, mib[4];
70e4e21ee1SDavid van Moolenbroek
71e4e21ee1SDavid van Moolenbroek pid = getpid();
72e4e21ee1SDavid van Moolenbroek
73e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
74e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
75e4e21ee1SDavid van Moolenbroek
76e4e21ee1SDavid van Moolenbroek /* Regular reads should succeed. */
77e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
78e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
79e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
80e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
81e4e21ee1SDavid van Moolenbroek if (i != 0x01020304) e(0);
82e4e21ee1SDavid van Moolenbroek
83e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
84e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
85e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
86e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
87e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
88e4e21ee1SDavid van Moolenbroek
89e4e21ee1SDavid van Moolenbroek /* Regular writes should fail. */
90e4e21ee1SDavid van Moolenbroek b = true;
91e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &b, sizeof(b)) != -1) e(0);
92e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
93e4e21ee1SDavid van Moolenbroek
94e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
95e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
96e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
97e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
98e4e21ee1SDavid van Moolenbroek
99e4e21ee1SDavid van Moolenbroek /* Privileged reads and writes should fail. */
100e4e21ee1SDavid van Moolenbroek mib[2] = TEST_PRIVATE;
101e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != -1) e(0);
102e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
103e4e21ee1SDavid van Moolenbroek
104e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
105e4e21ee1SDavid van Moolenbroek i = 1;
106e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != -1) e(0);
107e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
108e4e21ee1SDavid van Moolenbroek if (i != 1) e(0);
109e4e21ee1SDavid van Moolenbroek
110e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &i, sizeof(i)) != -1) e(0);
111e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
112e4e21ee1SDavid van Moolenbroek
113e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
114e4e21ee1SDavid van Moolenbroek mib[3] = SECRET_VALUE;
115e4e21ee1SDavid van Moolenbroek i = 0;
116e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
117e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &i, &oldlen, NULL, 0) != -1) e(0);
118e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
119e4e21ee1SDavid van Moolenbroek if (i == 12345) e(0);
120e4e21ee1SDavid van Moolenbroek
121e4e21ee1SDavid van Moolenbroek mib[3]++;
122e4e21ee1SDavid van Moolenbroek i = 0;
123e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
124e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &i, &oldlen, NULL, 0) != -1) e(0);
125e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
126e4e21ee1SDavid van Moolenbroek
127e4e21ee1SDavid van Moolenbroek /* Free-for-all writes should succeed. */
128e4e21ee1SDavid van Moolenbroek mib[2] = TEST_ANYWRITE;
129e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
130e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
131e4e21ee1SDavid van Moolenbroek
132e4e21ee1SDavid van Moolenbroek i = pid;
133e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &i, sizeof(i)) != 0) e(0);
134e4e21ee1SDavid van Moolenbroek
135e4e21ee1SDavid van Moolenbroek i = 0;
136e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
137e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
138e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
139e4e21ee1SDavid van Moolenbroek if (i != pid) e(0);
140e4e21ee1SDavid van Moolenbroek }
141e4e21ee1SDavid van Moolenbroek
142e4e21ee1SDavid van Moolenbroek /*
143e4e21ee1SDavid van Moolenbroek * Test the basic sysctl(2) interface.
144e4e21ee1SDavid van Moolenbroek */
145e4e21ee1SDavid van Moolenbroek static void
test87a(void)146e4e21ee1SDavid van Moolenbroek test87a(void)
147e4e21ee1SDavid van Moolenbroek {
148e4e21ee1SDavid van Moolenbroek char buf[32];
149e4e21ee1SDavid van Moolenbroek size_t len, oldlen;
150e4e21ee1SDavid van Moolenbroek pid_t pid;
151e4e21ee1SDavid van Moolenbroek u_quad_t q;
152e4e21ee1SDavid van Moolenbroek bool b, b2;
153*3083d603SDavid van Moolenbroek int i, va[2], lastva = -1 /*gcc*/, mib[CTL_MAXNAME + 1];
154e4e21ee1SDavid van Moolenbroek
155e4e21ee1SDavid van Moolenbroek subtest = 0;
156e4e21ee1SDavid van Moolenbroek
157e4e21ee1SDavid van Moolenbroek mib[0] = INT_MAX; /* some root-level identifier that does not exist */
158e4e21ee1SDavid van Moolenbroek for (i = 1; i <= CTL_MAXNAME; i++)
159e4e21ee1SDavid van Moolenbroek mib[i] = i;
160e4e21ee1SDavid van Moolenbroek
161e4e21ee1SDavid van Moolenbroek /*
162e4e21ee1SDavid van Moolenbroek * We cannot test for invalid 'name' and 'oldlenp' pointers, because
163e4e21ee1SDavid van Moolenbroek * those may be accessed directly by the libc system call stub. The
164e4e21ee1SDavid van Moolenbroek * NetBSD part of the stub even accesses name[0] without checking
165e4e21ee1SDavid van Moolenbroek * namelen first.
166e4e21ee1SDavid van Moolenbroek */
167e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 0, NULL, NULL, NULL, 0) != -1) e(0);
168e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
169e4e21ee1SDavid van Moolenbroek if (sysctl(mib, INT_MAX, NULL, NULL, NULL, 0) != -1) e(0);
170e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
171e4e21ee1SDavid van Moolenbroek if (sysctl(mib, UINT_MAX, NULL, NULL, NULL, 0) != -1) e(0);
172e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
173e4e21ee1SDavid van Moolenbroek for (i = 1; i <= CTL_MAXNAME; i++) {
174e4e21ee1SDavid van Moolenbroek if (sysctl(mib, i, NULL, NULL, NULL, 0) != -1) e(i);
175e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(i);
176e4e21ee1SDavid van Moolenbroek }
177e4e21ee1SDavid van Moolenbroek if (sysctl(mib, i, NULL, NULL, NULL, 0) != -1) e(0);
178e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
179e4e21ee1SDavid van Moolenbroek
180e4e21ee1SDavid van Moolenbroek /* Test names that are too short, right, and too long. */
181e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
182e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 1, NULL, NULL, NULL, 0) != -1) e(0);
183e4e21ee1SDavid van Moolenbroek if (errno != EISDIR) e(0);
184e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
185e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, NULL, NULL, NULL, 0) != -1) e(0);
186e4e21ee1SDavid van Moolenbroek if (errno != EISDIR) e(0);
187e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
188e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 0) != 0) e(0);
189e4e21ee1SDavid van Moolenbroek mib[3] = 0;
190e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, NULL, 0) != -1) e(0);
191e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
192e4e21ee1SDavid van Moolenbroek
193e4e21ee1SDavid van Moolenbroek /* Do some tests with meta-identifiers (special keys). */
194e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
195e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, NULL, 0) != -1) e(0);
196e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
197e4e21ee1SDavid van Moolenbroek
198e4e21ee1SDavid van Moolenbroek mib[2] = CTL_QUERY;
199e4e21ee1SDavid van Moolenbroek mib[3] = 0;
200e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, NULL, 0) != -1) e(0);
201e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
202e4e21ee1SDavid van Moolenbroek
203e4e21ee1SDavid van Moolenbroek mib[2] = CTL_EOL; /* a known-invalid meta-identifier */
204e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 0) != -1) e(0);
205e4e21ee1SDavid van Moolenbroek if (errno != EOPNOTSUPP) e(0);
206e4e21ee1SDavid van Moolenbroek
207e4e21ee1SDavid van Moolenbroek /* This case returns EINVAL now but might as well return EOPNOTSUPP. */
208e4e21ee1SDavid van Moolenbroek mib[3] = 0;
209e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, NULL, 0) != -1) e(0);
210e4e21ee1SDavid van Moolenbroek if (errno != EOPNOTSUPP && errno != EINVAL) e(0);
211e4e21ee1SDavid van Moolenbroek
212e4e21ee1SDavid van Moolenbroek /* Make sure the given oldlen value is ignored when unused. */
213e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
214e4e21ee1SDavid van Moolenbroek oldlen = 0;
215e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
216e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(int)) e(0);
217e4e21ee1SDavid van Moolenbroek oldlen = 1;
218e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
219e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(int)) e(0);
220e4e21ee1SDavid van Moolenbroek oldlen = SSIZE_MAX;
221e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
222e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(int)) e(0);
223e4e21ee1SDavid van Moolenbroek oldlen = SIZE_MAX;
224e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
225e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(int)) e(0);
226e4e21ee1SDavid van Moolenbroek
227e4e21ee1SDavid van Moolenbroek /* Test retrieval with the exact length. */
228e4e21ee1SDavid van Moolenbroek oldlen = sizeof(va[0]);
229e4e21ee1SDavid van Moolenbroek va[0] = va[1] = -1;
230e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
231e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
232e4e21ee1SDavid van Moolenbroek if (va[0] != 0x01020304) e(0);
233e4e21ee1SDavid van Moolenbroek if (va[1] != -1) e(0);
234e4e21ee1SDavid van Moolenbroek
235e4e21ee1SDavid van Moolenbroek /* Test retrieval with a length that is too short. */
236e4e21ee1SDavid van Moolenbroek for (i = 0; i < sizeof(va[0]); i++) {
237e4e21ee1SDavid van Moolenbroek va[0] = -1;
238e4e21ee1SDavid van Moolenbroek oldlen = i;
239e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != -1) e(0);
240e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
241e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
242e4e21ee1SDavid van Moolenbroek if (i == 0 && va[0] != -1) e(0);
243e4e21ee1SDavid van Moolenbroek if (i > 0 && va[0] >= lastva) e(0);
244e4e21ee1SDavid van Moolenbroek if (va[1] != -1) e(0);
245e4e21ee1SDavid van Moolenbroek lastva = va[0];
246e4e21ee1SDavid van Moolenbroek }
247e4e21ee1SDavid van Moolenbroek
248e4e21ee1SDavid van Moolenbroek /* Test retrieval with a length that is too long. */
249e4e21ee1SDavid van Moolenbroek oldlen = sizeof(va[0]) + 1;
250e4e21ee1SDavid van Moolenbroek va[0] = -1;
251e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
252e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
253e4e21ee1SDavid van Moolenbroek if (va[0] != 0x01020304) e(0);
254e4e21ee1SDavid van Moolenbroek if (va[1] != -1) e(0);
255e4e21ee1SDavid van Moolenbroek
256e4e21ee1SDavid van Moolenbroek oldlen = SSIZE_MAX;
257e4e21ee1SDavid van Moolenbroek va[0] = -1;
258e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
259e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
260e4e21ee1SDavid van Moolenbroek if (va[0] != 0x01020304) e(0);
261e4e21ee1SDavid van Moolenbroek if (va[1] != -1) e(0);
262e4e21ee1SDavid van Moolenbroek
263e4e21ee1SDavid van Moolenbroek oldlen = SIZE_MAX;
264e4e21ee1SDavid van Moolenbroek va[0] = -1;
265e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
266e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
267e4e21ee1SDavid van Moolenbroek if (va[0] != 0x01020304) e(0);
268e4e21ee1SDavid van Moolenbroek if (va[1] != -1) e(0);
269e4e21ee1SDavid van Moolenbroek
270e4e21ee1SDavid van Moolenbroek /*
271e4e21ee1SDavid van Moolenbroek * Ensure that we cannot overwrite this read-only integer. A write
272e4e21ee1SDavid van Moolenbroek * request must have both a pointer and a nonzero length, though.
273e4e21ee1SDavid van Moolenbroek */
274e4e21ee1SDavid van Moolenbroek va[0] = 0x05060708;
275e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 1) != 0) e(0);
276e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, va, 0) != 0) e(0);
277e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, va, sizeof(va[0])) != -1) e(0);
278e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
279e4e21ee1SDavid van Moolenbroek
280e4e21ee1SDavid van Moolenbroek oldlen = sizeof(va[0]);
281e4e21ee1SDavid van Moolenbroek va[0] = -1;
282e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
283e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
284e4e21ee1SDavid van Moolenbroek if (va[0] != 0x01020304) e(0);
285e4e21ee1SDavid van Moolenbroek if (va[1] != -1) e(0);
286e4e21ee1SDavid van Moolenbroek
287e4e21ee1SDavid van Moolenbroek /* Test retrieval into a bad pointer. */
288e4e21ee1SDavid van Moolenbroek oldlen = sizeof(int);
289e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, NULL, 0) != -1) e(0);
290e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
291e4e21ee1SDavid van Moolenbroek
292e4e21ee1SDavid van Moolenbroek /*
293e4e21ee1SDavid van Moolenbroek * Test reading and writing booleans. Booleans may actually be an int,
294e4e21ee1SDavid van Moolenbroek * a char, or just one bit of a char. As a result, the MIB service can
295e4e21ee1SDavid van Moolenbroek * not test properly for non-bool values being passed in bool fields,
296e4e21ee1SDavid van Moolenbroek * and we can not do effective testing on this either, because in both
297e4e21ee1SDavid van Moolenbroek * cases our efforts may simply be optimized away, and result in
298e4e21ee1SDavid van Moolenbroek * unexpected success.
299e4e21ee1SDavid van Moolenbroek */
300e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
301e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
302e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
303e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
304e4e21ee1SDavid van Moolenbroek if (b != false && b != true) e(0);
305e4e21ee1SDavid van Moolenbroek
306e4e21ee1SDavid van Moolenbroek b = true;
307e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, &b, sizeof(b)) != 0) e(0);
308e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
309e4e21ee1SDavid van Moolenbroek
310e4e21ee1SDavid van Moolenbroek b = false;
311e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
312e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
313e4e21ee1SDavid van Moolenbroek if (b != true) e(0);
314e4e21ee1SDavid van Moolenbroek
315e4e21ee1SDavid van Moolenbroek b = false;
316e4e21ee1SDavid van Moolenbroek b2 = false;
317e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b2);
318e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b2, &oldlen, &b, sizeof(b)) != 0) e(0);
319e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b2)) e(0);
320e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
321e4e21ee1SDavid van Moolenbroek if (b2 != true) e(0);
322e4e21ee1SDavid van Moolenbroek
323e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &b, sizeof(b) + 1) != -1) e(0);
324e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
325e4e21ee1SDavid van Moolenbroek
326e4e21ee1SDavid van Moolenbroek /*
327e4e21ee1SDavid van Moolenbroek * The MIB service does not support value swaps. If we pass in the
328e4e21ee1SDavid van Moolenbroek * same buffer for old and new data, we expect that the old data stays.
329e4e21ee1SDavid van Moolenbroek */
330e4e21ee1SDavid van Moolenbroek b = true;
331e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
332e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, &b, sizeof(b)) != 0) e(0);
333e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
334e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
335e4e21ee1SDavid van Moolenbroek
336e4e21ee1SDavid van Moolenbroek b = true;
337e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
338e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
339e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
340e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
341e4e21ee1SDavid van Moolenbroek
342e4e21ee1SDavid van Moolenbroek /* Test reading and writing a quad. */
343e4e21ee1SDavid van Moolenbroek mib[2] = TEST_QUAD;
344e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
345e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
346e4e21ee1SDavid van Moolenbroek
347e4e21ee1SDavid van Moolenbroek q = 0x1234567890abcdefULL;
348e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &q, sizeof(q)) != 0) e(0);
349e4e21ee1SDavid van Moolenbroek
350e4e21ee1SDavid van Moolenbroek q = 0ULL;
351e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
352e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
353e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
354e4e21ee1SDavid van Moolenbroek if (q != 0x1234567890abcdefULL) e(0);
355e4e21ee1SDavid van Moolenbroek
356e4e21ee1SDavid van Moolenbroek q = ~0ULL;
357e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &q, sizeof(q)) != 0) e(0);
358e4e21ee1SDavid van Moolenbroek
359e4e21ee1SDavid van Moolenbroek /* Test writing with a bad pointer. The value must stay. */
360e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, bad_ptr, sizeof(q)) != -1) e(0);
361e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
362e4e21ee1SDavid van Moolenbroek
363e4e21ee1SDavid van Moolenbroek q = 0ULL;
364e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
365e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
366e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
367e4e21ee1SDavid van Moolenbroek if (q != ~0ULL) e(0);
368e4e21ee1SDavid van Moolenbroek
369e4e21ee1SDavid van Moolenbroek q = 0ULL;
370e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &q, sizeof(q)) != 0) e(0);
371e4e21ee1SDavid van Moolenbroek
372e4e21ee1SDavid van Moolenbroek q = 1ULL;
373e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
374e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
375e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
376e4e21ee1SDavid van Moolenbroek if (q != 0ULL) e(0);
377e4e21ee1SDavid van Moolenbroek
378e4e21ee1SDavid van Moolenbroek /* Test reading and writing a string. */
379e4e21ee1SDavid van Moolenbroek mib[2] = TEST_STRING;
380e4e21ee1SDavid van Moolenbroek strlcpy(buf, "test", sizeof(buf));
381e4e21ee1SDavid van Moolenbroek len = strlen(buf);
382e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len + 1) != 0) e(0);
383e4e21ee1SDavid van Moolenbroek
384e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
385e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
386e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
387e4e21ee1SDavid van Moolenbroek
388e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
389e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
390e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
391e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "test")) e(0);
392e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
393e4e21ee1SDavid van Moolenbroek if (buf[len + 1] != 0x07) e(0);
394e4e21ee1SDavid van Moolenbroek
395e4e21ee1SDavid van Moolenbroek strlcpy(buf, "abc123", sizeof(buf));
396e4e21ee1SDavid van Moolenbroek oldlen = 2;
397e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, buf, strlen(buf) + 1) != 0) e(0);
398e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
399e4e21ee1SDavid van Moolenbroek len = strlen(buf);
400e4e21ee1SDavid van Moolenbroek
401e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
402e4e21ee1SDavid van Moolenbroek oldlen = len - 1;
403e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != -1) e(0);
404e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
405e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
406e4e21ee1SDavid van Moolenbroek if (strncmp(buf, "abc12", len - 1)) e(0);
407e4e21ee1SDavid van Moolenbroek if (buf[len - 1] != 0x07 || buf[len] != 0x07) e(0);
408e4e21ee1SDavid van Moolenbroek
409e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
410e4e21ee1SDavid van Moolenbroek oldlen = len + 1;
411e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
412e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
413e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "abc123")) e(0);
414e4e21ee1SDavid van Moolenbroek
415e4e21ee1SDavid van Moolenbroek /*
416e4e21ee1SDavid van Moolenbroek * Now put in a shorter string, without null terminator. The string
417e4e21ee1SDavid van Moolenbroek * must be accepted; the null terminator must be added automatically.
418e4e21ee1SDavid van Moolenbroek */
419e4e21ee1SDavid van Moolenbroek strlcpy(buf, "foolproof", sizeof(buf));
420e4e21ee1SDavid van Moolenbroek len = strlen("foo");
421e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len) != 0) e(0);
422e4e21ee1SDavid van Moolenbroek
423e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
424e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
425e4e21ee1SDavid van Moolenbroek
426e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
427e4e21ee1SDavid van Moolenbroek oldlen = len;
428e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != -1) e(0);
429e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
430e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
431e4e21ee1SDavid van Moolenbroek if (strncmp(buf, "foo", len)) e(0);
432e4e21ee1SDavid van Moolenbroek if (buf[len] != 0x07) e(0);
433e4e21ee1SDavid van Moolenbroek
434e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
435e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
436e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
437e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
438e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "foo")) e(0);
439e4e21ee1SDavid van Moolenbroek if (buf[len + 1] != 0x07) e(0);
440e4e21ee1SDavid van Moolenbroek
441e4e21ee1SDavid van Moolenbroek /*
442e4e21ee1SDavid van Moolenbroek * Passing in more data after the string is fine, but whatever comes
443e4e21ee1SDavid van Moolenbroek * after the first null terminator is disregarded.
444e4e21ee1SDavid van Moolenbroek */
445e4e21ee1SDavid van Moolenbroek strlcpy(buf, "barbapapa", sizeof(buf));
446e4e21ee1SDavid van Moolenbroek len = strlen(buf);
447e4e21ee1SDavid van Moolenbroek buf[3] = '\0';
448e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len + 1)) e(0);
449e4e21ee1SDavid van Moolenbroek len = strlen(buf);
450e4e21ee1SDavid van Moolenbroek
451e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
452e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
453e4e21ee1SDavid van Moolenbroek
454e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
455e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
456e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
457e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
458e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "bar")) e(0);
459e4e21ee1SDavid van Moolenbroek if (buf[len + 1] != 0x07) e(0);
460e4e21ee1SDavid van Moolenbroek
461e4e21ee1SDavid van Moolenbroek /* Test the maximum string length. */
462e4e21ee1SDavid van Moolenbroek strlcpy(buf, "0123456789abcdef", sizeof(buf));
463e4e21ee1SDavid van Moolenbroek len = strlen(buf);
464e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len + 1) != -1) e(0);
465e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
466e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len) != -1) e(0);
467e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
468e4e21ee1SDavid van Moolenbroek
469e4e21ee1SDavid van Moolenbroek buf[--len] = '\0';
470e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len + 1) != 0) e(0);
471e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
472e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
473e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
474e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
475e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "0123456789abcde")) e(0);
476e4e21ee1SDavid van Moolenbroek if (buf[len + 1] != 0x07) e(0);
477e4e21ee1SDavid van Moolenbroek
478e4e21ee1SDavid van Moolenbroek /*
479e4e21ee1SDavid van Moolenbroek * Clearing out the field with zero-length data is not possible,
480e4e21ee1SDavid van Moolenbroek * because zero-length updates are disregarded at a higher level.
481e4e21ee1SDavid van Moolenbroek */
482e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, "", 0) != 0) e(0);
483e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
484e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
485e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
486e4e21ee1SDavid van Moolenbroek if (oldlen != len + 1) e(0);
487e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "0123456789abcde")) e(0);
488e4e21ee1SDavid van Moolenbroek
489e4e21ee1SDavid van Moolenbroek /* To clear the field, the null terminator is required. */
490e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, "", 1) != 0) e(0);
491e4e21ee1SDavid van Moolenbroek memset(buf, 0x07, sizeof(buf));
492e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
493e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
494e4e21ee1SDavid van Moolenbroek if (oldlen != 1) e(0);
495e4e21ee1SDavid van Moolenbroek if (buf[0] != '\0') e(0);
496e4e21ee1SDavid van Moolenbroek if (buf[1] != 0x07) e(0);
497e4e21ee1SDavid van Moolenbroek
498e4e21ee1SDavid van Moolenbroek /*
499e4e21ee1SDavid van Moolenbroek * Test reading and writing structures. Structures are just blobs of
500e4e21ee1SDavid van Moolenbroek * data, with no special handling by default. They can only be read
501e4e21ee1SDavid van Moolenbroek * and written all at once.
502e4e21ee1SDavid van Moolenbroek */
503e4e21ee1SDavid van Moolenbroek mib[2] = TEST_STRUCT;
504e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
505e4e21ee1SDavid van Moolenbroek if (oldlen != 12) e(0);
506e4e21ee1SDavid van Moolenbroek len = oldlen;
507e4e21ee1SDavid van Moolenbroek
508e4e21ee1SDavid van Moolenbroek for (i = 0; i < len + 1; i++)
509e4e21ee1SDavid van Moolenbroek buf[i] = i + 1;
510e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len - 1) != -1) e(0);
511e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
512e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len + 1) != -1) e(0);
513e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
514e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len) != 0) e(0);
515e4e21ee1SDavid van Moolenbroek
516e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
517e4e21ee1SDavid van Moolenbroek oldlen = len - 1;
518e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != -1) e(0);
519e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
520e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
521e4e21ee1SDavid van Moolenbroek for (i = 0; i < len - 1; i++)
522e4e21ee1SDavid van Moolenbroek if (buf[i] != i + 1) e(0);
523e4e21ee1SDavid van Moolenbroek if (buf[i] != 0x7f) e(0);
524e4e21ee1SDavid van Moolenbroek
525e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
526e4e21ee1SDavid van Moolenbroek oldlen = len + 1;
527e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
528e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
529e4e21ee1SDavid van Moolenbroek for (i = 0; i < len; i++)
530e4e21ee1SDavid van Moolenbroek if (buf[i] != i + 1) e(0);
531e4e21ee1SDavid van Moolenbroek if (buf[i] != 0x7f) e(0);
532e4e21ee1SDavid van Moolenbroek
533e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
534e4e21ee1SDavid van Moolenbroek oldlen = len;
535e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
536e4e21ee1SDavid van Moolenbroek for (i = 0; i < len; i++)
537e4e21ee1SDavid van Moolenbroek if (buf[i] != i + 1) e(0);
538e4e21ee1SDavid van Moolenbroek if (buf[len] != 0x7f) e(0);
539e4e21ee1SDavid van Moolenbroek
540e4e21ee1SDavid van Moolenbroek /* Null characters are not treated in any special way. */
541e4e21ee1SDavid van Moolenbroek for (i = 0; i < len; i++)
542e4e21ee1SDavid van Moolenbroek buf[i] = !!i;
543e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len) != 0) e(0);
544e4e21ee1SDavid van Moolenbroek
545e4e21ee1SDavid van Moolenbroek oldlen = len;
546e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
547e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
548e4e21ee1SDavid van Moolenbroek for (i = 0; i < len; i++)
549e4e21ee1SDavid van Moolenbroek if (buf[i] != !!i) e(0);
550e4e21ee1SDavid van Moolenbroek if (buf[len] != 0x7f) e(0);
551e4e21ee1SDavid van Moolenbroek
552e4e21ee1SDavid van Moolenbroek memset(buf, 0, len);
553e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, len) != 0) e(0);
554e4e21ee1SDavid van Moolenbroek
555e4e21ee1SDavid van Moolenbroek oldlen = len;
556e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
557e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
558e4e21ee1SDavid van Moolenbroek for (i = 0; i < len; i++)
559e4e21ee1SDavid van Moolenbroek if (buf[i] != 0) e(0);
560e4e21ee1SDavid van Moolenbroek if (buf[len] != 0x7f) e(0);
561e4e21ee1SDavid van Moolenbroek
562e4e21ee1SDavid van Moolenbroek /*
563e4e21ee1SDavid van Moolenbroek * Test private read and free-for-all write operations. For starters,
564e4e21ee1SDavid van Moolenbroek * this test should run with superuser privileges, and thus should be
565e4e21ee1SDavid van Moolenbroek * able to read and write private fields.
566e4e21ee1SDavid van Moolenbroek */
567e4e21ee1SDavid van Moolenbroek mib[2] = TEST_PRIVATE;
568e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
569e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
570e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
571e4e21ee1SDavid van Moolenbroek if (va[0] != -5375) e(0);
572e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, va, sizeof(va[0])) != 0) e(0);
573e4e21ee1SDavid van Moolenbroek
574e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
575e4e21ee1SDavid van Moolenbroek mib[3] = SECRET_VALUE;
576e4e21ee1SDavid van Moolenbroek oldlen = sizeof(va[0]);
577e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, va, &oldlen, NULL, 0) != 0) e(0);
578e4e21ee1SDavid van Moolenbroek if (va[0] != 12345) e(0);
579e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, va, sizeof(va[0])) != -1) e(0);
580e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
581e4e21ee1SDavid van Moolenbroek
582e4e21ee1SDavid van Moolenbroek mib[3]++;
583e4e21ee1SDavid van Moolenbroek i = 0;
584e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
585e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &i, &oldlen, NULL, 0) != -1) e(0);
586e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
587e4e21ee1SDavid van Moolenbroek
588e4e21ee1SDavid van Moolenbroek /* Use a child process to test operations without root privileges. */
589e4e21ee1SDavid van Moolenbroek pid = test_nonroot(sub87a);
590e4e21ee1SDavid van Moolenbroek
591e4e21ee1SDavid van Moolenbroek /* The change made by the child should be visible to the parent. */
592e4e21ee1SDavid van Moolenbroek mib[2] = TEST_ANYWRITE;
593e4e21ee1SDavid van Moolenbroek va[0] = 0;
594e4e21ee1SDavid van Moolenbroek oldlen = sizeof(va[0]);
595e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, va, &oldlen, NULL, 0) != 0) e(0);
596e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(va[0])) e(0);
597e4e21ee1SDavid van Moolenbroek if (va[0] != pid) e(0);
598e4e21ee1SDavid van Moolenbroek }
599e4e21ee1SDavid van Moolenbroek
600e4e21ee1SDavid van Moolenbroek /*
601e4e21ee1SDavid van Moolenbroek * Test queries from an unprivileged process.
602e4e21ee1SDavid van Moolenbroek */
603e4e21ee1SDavid van Moolenbroek static void
sub87b(void)604e4e21ee1SDavid van Moolenbroek sub87b(void)
605e4e21ee1SDavid van Moolenbroek {
606e4e21ee1SDavid van Moolenbroek struct sysctlnode scn[32];
607e4e21ee1SDavid van Moolenbroek unsigned int count;
608e4e21ee1SDavid van Moolenbroek size_t oldlen;
609e4e21ee1SDavid van Moolenbroek int i, mib[4];
610e4e21ee1SDavid van Moolenbroek
611e4e21ee1SDavid van Moolenbroek /* Query minix.test and make sure we do not get privileged values. */
612e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
613e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
614e4e21ee1SDavid van Moolenbroek mib[2] = CTL_QUERY;
615e4e21ee1SDavid van Moolenbroek
616e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn);
617e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, scn, &oldlen, NULL, 0) != 0) e(0);
618e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn[0])) e(0);
619e4e21ee1SDavid van Moolenbroek count = oldlen / sizeof(scn[0]);
620e4e21ee1SDavid van Moolenbroek if (count < 8) e(0);
621e4e21ee1SDavid van Moolenbroek
622e4e21ee1SDavid van Moolenbroek /*
623e4e21ee1SDavid van Moolenbroek * Do not bother doing the entire check again, but test enough to
624e4e21ee1SDavid van Moolenbroek * inspire confidence that only the right values are hidden.
625e4e21ee1SDavid van Moolenbroek */
626e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_num != TEST_INT) e(0);
627e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[0].sysctl_flags) != CTLTYPE_INT) e(0);
6286f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[0].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
629e4e21ee1SDavid van Moolenbroek (CTLFLAG_READONLY | CTLFLAG_IMMEDIATE | CTLFLAG_HEX)) e(0);
630e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[0].sysctl_flags) != SYSCTL_VERSION) e(0);
631e4e21ee1SDavid van Moolenbroek if (strcmp(scn[0].sysctl_name, "int")) e(0);
632e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_ver == 0) e(0);
633e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_size != sizeof(int)) e(0);
634e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_idata != 0x01020304) e(0);
635e4e21ee1SDavid van Moolenbroek
636e4e21ee1SDavid van Moolenbroek for (i = 0; i < count; i++)
637e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_num == TEST_PRIVATE)
638e4e21ee1SDavid van Moolenbroek break;
639e4e21ee1SDavid van Moolenbroek if (i == count) e(0);
640e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[i].sysctl_flags) != CTLTYPE_INT) e(0);
6416f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[i].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
642e4e21ee1SDavid van Moolenbroek (CTLFLAG_READWRITE | CTLFLAG_PRIVATE | CTLFLAG_IMMEDIATE)) e(0);
643e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[i].sysctl_flags) != SYSCTL_VERSION) e(0);
644e4e21ee1SDavid van Moolenbroek if (strcmp(scn[i].sysctl_name, "private")) e(0);
645e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_size != sizeof(int)) e(0);
646e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_idata != 0) e(0); /* private */
647e4e21ee1SDavid van Moolenbroek
648e4e21ee1SDavid van Moolenbroek for (i = 0; i < count; i++)
649e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_num == TEST_SECRET)
650e4e21ee1SDavid van Moolenbroek break;
651e4e21ee1SDavid van Moolenbroek if (i == count) e(0);
652e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[i].sysctl_flags) != CTLTYPE_NODE) e(0);
6536f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[i].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
654e4e21ee1SDavid van Moolenbroek (CTLFLAG_READONLY | CTLFLAG_PRIVATE)) e(0);
655e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[i].sysctl_flags) != SYSCTL_VERSION) e(0);
656e4e21ee1SDavid van Moolenbroek if (strcmp(scn[i].sysctl_name, "secret")) e(0);
657e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_ver == 0) e(0);
658e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_size != sizeof(scn[0])) e(0);
659e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_csize != 0) e(0); /* private */
660e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_clen != 0) e(0); /* private */
661e4e21ee1SDavid van Moolenbroek
662e4e21ee1SDavid van Moolenbroek /* Make sure that a query on minix.test.secret fails. */
663e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
664e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
665e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, &oldlen, NULL, 0) != -1) e(0);
666e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
667e4e21ee1SDavid van Moolenbroek }
668e4e21ee1SDavid van Moolenbroek
669e4e21ee1SDavid van Moolenbroek /*
670e4e21ee1SDavid van Moolenbroek * Test sysctl(2) queries.
671e4e21ee1SDavid van Moolenbroek */
672e4e21ee1SDavid van Moolenbroek static void
test87b(void)673e4e21ee1SDavid van Moolenbroek test87b(void)
674e4e21ee1SDavid van Moolenbroek {
675e4e21ee1SDavid van Moolenbroek struct sysctlnode scn[32];
676e4e21ee1SDavid van Moolenbroek unsigned int count;
677e4e21ee1SDavid van Moolenbroek size_t len, oldlen;
678e4e21ee1SDavid van Moolenbroek u_quad_t q;
679e4e21ee1SDavid van Moolenbroek bool b;
680e4e21ee1SDavid van Moolenbroek int i, mib[4];
681e4e21ee1SDavid van Moolenbroek
682e4e21ee1SDavid van Moolenbroek subtest = 1;
683e4e21ee1SDavid van Moolenbroek
684e4e21ee1SDavid van Moolenbroek /* We should be able to query the root key. */
685e4e21ee1SDavid van Moolenbroek mib[0] = CTL_QUERY;
686e4e21ee1SDavid van Moolenbroek
687e4e21ee1SDavid van Moolenbroek oldlen = 0;
688e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 1, NULL, &oldlen, NULL, 0) != 0) e(0);
689e4e21ee1SDavid van Moolenbroek if (oldlen <= sizeof(scn[0])) e(0);
690e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn[0])) e(0);
691e4e21ee1SDavid van Moolenbroek
692e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
693e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 1, scn, &oldlen, NULL, 0) != -1) e(0);
694e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM);
695e4e21ee1SDavid van Moolenbroek if (oldlen <= sizeof(scn[0])) e(0);
696e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn[0])) e(0);
697e4e21ee1SDavid van Moolenbroek
698e4e21ee1SDavid van Moolenbroek /*
699e4e21ee1SDavid van Moolenbroek * We assume that the root node's first child is always CTL_KERN, which
700e4e21ee1SDavid van Moolenbroek * must be read-only and may have only the CTLFLAG_PERMANENT flag set.
701e4e21ee1SDavid van Moolenbroek */
702e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_num != CTL_KERN) e(0);
703e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[0].sysctl_flags) != CTLTYPE_NODE) e(0);
704e4e21ee1SDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[0].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
705e4e21ee1SDavid van Moolenbroek CTLFLAG_READONLY) e(0);
706e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[0].sysctl_flags) != SYSCTL_VERSION) e(0);
707e4e21ee1SDavid van Moolenbroek if (strcmp(scn[0].sysctl_name, "kern")) e(0);
708e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_ver == 0) e(0);
709e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_size != sizeof(scn[0])) e(0);
710e4e21ee1SDavid van Moolenbroek if ((int)scn[0].sysctl_csize <= 0) e(0);
711e4e21ee1SDavid van Moolenbroek if ((int)scn[0].sysctl_clen <= 0) e(0);
712e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_csize < scn[0].sysctl_clen) e(0);
713e4e21ee1SDavid van Moolenbroek
714e4e21ee1SDavid van Moolenbroek /* Now do a more complete test on the minix.test subtree. */
715e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
716e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
717e4e21ee1SDavid van Moolenbroek
718e4e21ee1SDavid van Moolenbroek /*
719e4e21ee1SDavid van Moolenbroek * Initialize a few immediate fields to nonzero so that we can test
720e4e21ee1SDavid van Moolenbroek * that their values are returned as a result of the query.
721e4e21ee1SDavid van Moolenbroek */
722e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
723e4e21ee1SDavid van Moolenbroek b = true;
724e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &b, sizeof(b)) != 0) e(0);
725e4e21ee1SDavid van Moolenbroek
726e4e21ee1SDavid van Moolenbroek mib[2] = TEST_QUAD;
727e4e21ee1SDavid van Moolenbroek q = ~0;
728e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &q, sizeof(q)) != 0) e(0);
729e4e21ee1SDavid van Moolenbroek
730e4e21ee1SDavid van Moolenbroek mib[2] = CTL_QUERY;
731e4e21ee1SDavid van Moolenbroek
732e4e21ee1SDavid van Moolenbroek oldlen = 1;
733e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
734e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn[0])) e(0);
735e4e21ee1SDavid van Moolenbroek if (oldlen >= sizeof(scn)) e(0);
736e4e21ee1SDavid van Moolenbroek len = oldlen;
737e4e21ee1SDavid van Moolenbroek count = len / sizeof(scn[0]);
738e4e21ee1SDavid van Moolenbroek if (count < 8) e(0);
739e4e21ee1SDavid van Moolenbroek
740e4e21ee1SDavid van Moolenbroek memset(scn, 0x7e, sizeof(scn));
741e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, scn, &oldlen, NULL, 0) != 0) e(0);
742e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
743e4e21ee1SDavid van Moolenbroek if (scn[count].sysctl_name[0] != 0x7e) e(0);
744e4e21ee1SDavid van Moolenbroek
745e4e21ee1SDavid van Moolenbroek /*
746e4e21ee1SDavid van Moolenbroek * Again, we rely on the MIB service returning entries in ascending
747e4e21ee1SDavid van Moolenbroek * order for at least the static nodes. We do not make assumptions
748e4e21ee1SDavid van Moolenbroek * about whether dynamic nodes are merged in or (as is the case as of
749e4e21ee1SDavid van Moolenbroek * writing) returned after the static nodes. At this point there
7506f3e0bcdSDavid van Moolenbroek * should be no dynamic nodes here yet anyway. We mostly ignore
7516f3e0bcdSDavid van Moolenbroek * CTLFLAG_PERMANENT in order to facilitate running this test on a
7526f3e0bcdSDavid van Moolenbroek * remotely mounted subtree.
753e4e21ee1SDavid van Moolenbroek */
754e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_num != TEST_INT) e(0);
755e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[0].sysctl_flags) != CTLTYPE_INT) e(0);
7566f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[0].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
757e4e21ee1SDavid van Moolenbroek (CTLFLAG_READONLY | CTLFLAG_IMMEDIATE | CTLFLAG_HEX)) e(0);
758e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[0].sysctl_flags) != SYSCTL_VERSION) e(0);
759e4e21ee1SDavid van Moolenbroek if (strcmp(scn[0].sysctl_name, "int")) e(0);
760e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_ver == 0) e(0);
761e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_size != sizeof(int)) e(0);
762e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_idata != 0x01020304) e(0);
763e4e21ee1SDavid van Moolenbroek
764e4e21ee1SDavid van Moolenbroek if (scn[1].sysctl_num != TEST_BOOL) e(0);
765e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[1].sysctl_flags) != CTLTYPE_BOOL) e(0);
7666f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[1].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
767e4e21ee1SDavid van Moolenbroek (CTLFLAG_READWRITE | CTLFLAG_IMMEDIATE)) e(0);
768e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[1].sysctl_flags) != SYSCTL_VERSION) e(0);
769e4e21ee1SDavid van Moolenbroek if (strcmp(scn[1].sysctl_name, "bool")) e(0);
770e4e21ee1SDavid van Moolenbroek if (scn[1].sysctl_ver == 0) e(0);
771e4e21ee1SDavid van Moolenbroek if (scn[1].sysctl_size != sizeof(bool)) e(0);
772e4e21ee1SDavid van Moolenbroek if (scn[1].sysctl_bdata != true) e(0);
773e4e21ee1SDavid van Moolenbroek
774e4e21ee1SDavid van Moolenbroek if (scn[2].sysctl_num != TEST_QUAD) e(0);
775e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[2].sysctl_flags) != CTLTYPE_QUAD) e(0);
7766f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[2].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
777e4e21ee1SDavid van Moolenbroek (CTLFLAG_READWRITE | CTLFLAG_IMMEDIATE)) e(0);
778e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[2].sysctl_flags) != SYSCTL_VERSION) e(0);
779e4e21ee1SDavid van Moolenbroek if (strcmp(scn[2].sysctl_name, "quad")) e(0);
780e4e21ee1SDavid van Moolenbroek if (scn[2].sysctl_ver == 0) e(0);
781e4e21ee1SDavid van Moolenbroek if (scn[2].sysctl_size != sizeof(u_quad_t)) e(0);
782e4e21ee1SDavid van Moolenbroek if (scn[2].sysctl_qdata != q) e(0);
783e4e21ee1SDavid van Moolenbroek
784e4e21ee1SDavid van Moolenbroek if (scn[3].sysctl_num != TEST_STRING) e(0);
785e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[3].sysctl_flags) != CTLTYPE_STRING) e(0);
7866f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[3].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
7876f3e0bcdSDavid van Moolenbroek CTLFLAG_READWRITE) e(0);
788e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[3].sysctl_flags) != SYSCTL_VERSION) e(0);
789e4e21ee1SDavid van Moolenbroek if (strcmp(scn[3].sysctl_name, "string")) e(0);
790e4e21ee1SDavid van Moolenbroek if (scn[3].sysctl_ver == 0) e(0);
791e4e21ee1SDavid van Moolenbroek if (scn[3].sysctl_size != 16) e(0);
792e4e21ee1SDavid van Moolenbroek
793e4e21ee1SDavid van Moolenbroek if (scn[4].sysctl_num != TEST_STRUCT) e(0);
794e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[4].sysctl_flags) != CTLTYPE_STRUCT) e(0);
7956f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[4].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
7966f3e0bcdSDavid van Moolenbroek CTLFLAG_READWRITE) e(0);
797e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[4].sysctl_flags) != SYSCTL_VERSION) e(0);
798e4e21ee1SDavid van Moolenbroek if (strcmp(scn[4].sysctl_name, "struct")) e(0);
799e4e21ee1SDavid van Moolenbroek if (scn[4].sysctl_ver == 0) e(0);
800e4e21ee1SDavid van Moolenbroek if (scn[4].sysctl_size != 12) e(0);
801e4e21ee1SDavid van Moolenbroek
802e4e21ee1SDavid van Moolenbroek if (scn[5].sysctl_num != TEST_PRIVATE) e(0);
803e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[5].sysctl_flags) != CTLTYPE_INT) e(0);
8046f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[5].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
805e4e21ee1SDavid van Moolenbroek (CTLFLAG_READWRITE | CTLFLAG_PRIVATE | CTLFLAG_IMMEDIATE)) e(0);
806e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[5].sysctl_flags) != SYSCTL_VERSION) e(0);
807e4e21ee1SDavid van Moolenbroek if (strcmp(scn[5].sysctl_name, "private")) e(0);
808e4e21ee1SDavid van Moolenbroek if (scn[5].sysctl_ver == 0) e(0);
809e4e21ee1SDavid van Moolenbroek if (scn[5].sysctl_size != sizeof(int)) e(0);
810e4e21ee1SDavid van Moolenbroek if (scn[5].sysctl_idata != -5375) e(0);
811e4e21ee1SDavid van Moolenbroek
812e4e21ee1SDavid van Moolenbroek if (scn[6].sysctl_num != TEST_ANYWRITE) e(0);
813e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[6].sysctl_flags) != CTLTYPE_INT) e(0);
8146f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[6].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
815e4e21ee1SDavid van Moolenbroek (CTLFLAG_READWRITE | CTLFLAG_ANYWRITE | CTLFLAG_IMMEDIATE)) e(0);
816e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[6].sysctl_flags) != SYSCTL_VERSION) e(0);
817e4e21ee1SDavid van Moolenbroek if (strcmp(scn[6].sysctl_name, "anywrite")) e(0);
818e4e21ee1SDavid van Moolenbroek if (scn[6].sysctl_ver == 0) e(0);
819e4e21ee1SDavid van Moolenbroek if (scn[6].sysctl_size != sizeof(int)) e(0);
820e4e21ee1SDavid van Moolenbroek
821e4e21ee1SDavid van Moolenbroek i = (scn[7].sysctl_num == TEST_DYNAMIC) ? 8 : 7;
822e4e21ee1SDavid van Moolenbroek
823e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_num != TEST_SECRET) e(0);
824e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[i].sysctl_flags) != CTLTYPE_NODE) e(0);
8256f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[i].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
826e4e21ee1SDavid van Moolenbroek (CTLFLAG_READONLY | CTLFLAG_PRIVATE)) e(0);
827e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[i].sysctl_flags) != SYSCTL_VERSION) e(0);
828e4e21ee1SDavid van Moolenbroek if (strcmp(scn[i].sysctl_name, "secret")) e(0);
829e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_ver == 0) e(0);
830e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_size != sizeof(scn[0])) e(0);
831e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_csize != 1) e(0);
832e4e21ee1SDavid van Moolenbroek if (scn[i].sysctl_clen != 1) e(0);
833e4e21ee1SDavid van Moolenbroek
834e4e21ee1SDavid van Moolenbroek /*
835e4e21ee1SDavid van Moolenbroek * Now that we know how many entries there are in minix.test, also look
836e4e21ee1SDavid van Moolenbroek * at whether the right child length is returned in a query on its
837e4e21ee1SDavid van Moolenbroek * parent. While doing that, see whether data structure versioning
838e4e21ee1SDavid van Moolenbroek * works as expected as well. MINIX_TEST is hardcoded to zero so we
839e4e21ee1SDavid van Moolenbroek * expect it to be the first entry returned from a query.
840e4e21ee1SDavid van Moolenbroek */
841e4e21ee1SDavid van Moolenbroek mib[1] = CTL_QUERY;
842e4e21ee1SDavid van Moolenbroek
843e4e21ee1SDavid van Moolenbroek memset(scn, 0, sizeof(scn));
844e4e21ee1SDavid van Moolenbroek scn[1].sysctl_flags = SYSCTL_VERS_0;
845e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, NULL, &oldlen, &scn[1], sizeof(scn[1])) != -1) e(0);
846e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
847e4e21ee1SDavid van Moolenbroek scn[1].sysctl_flags = SYSCTL_VERS_1;
848e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, NULL, &oldlen, &scn[1], sizeof(scn[1]) - 1) != -1)
849e4e21ee1SDavid van Moolenbroek e(0);
850e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
851e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, NULL, &oldlen, &scn[1], sizeof(scn[1]) + 1) != -1)
852e4e21ee1SDavid van Moolenbroek e(0);
853e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
854e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, NULL, &oldlen, &scn[1], sizeof(scn[1])) != 0) e(0);
855e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
856e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn[0])) e(0);
857e4e21ee1SDavid van Moolenbroek
858e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
859e4e21ee1SDavid van Moolenbroek scn[1].sysctl_flags = SYSCTL_VERS_0;
860e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, scn, &oldlen, &scn[1], sizeof(scn[1])) != -1) e(0);
861e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
862e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
863e4e21ee1SDavid van Moolenbroek scn[1].sysctl_flags = SYSCTL_VERS_1;
864e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 2, scn, &oldlen, &scn[1], sizeof(scn[1])) != 0 &&
865e4e21ee1SDavid van Moolenbroek errno != ENOMEM) e(0);
866e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
867e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn[0])) e(0);
868e4e21ee1SDavid van Moolenbroek
869e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_num != MINIX_TEST) e(0);
870e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[0].sysctl_flags) != CTLTYPE_NODE) e(0);
871e4e21ee1SDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[0].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
872e4e21ee1SDavid van Moolenbroek (CTLFLAG_READWRITE | CTLFLAG_HIDDEN)) e(0);
873e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[0].sysctl_flags) != SYSCTL_VERSION) e(0);
874e4e21ee1SDavid van Moolenbroek if (strcmp(scn[0].sysctl_name, "test")) e(0);
875e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_ver == 0) e(0);
876e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_size != sizeof(scn[0])) e(0);
877e4e21ee1SDavid van Moolenbroek if ((int)scn[0].sysctl_clen != count) e(0);
878e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_csize < scn[0].sysctl_clen) e(0);
879e4e21ee1SDavid van Moolenbroek
880e4e21ee1SDavid van Moolenbroek /*
881e4e21ee1SDavid van Moolenbroek * Test querying minix.test.secret, which should have exactly one node.
882e4e21ee1SDavid van Moolenbroek * At the same time, test bad pointers.
883e4e21ee1SDavid van Moolenbroek */
884e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
885e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
886e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
887e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn);
888e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, &oldlen, bad_ptr, sizeof(scn[0])) != -1) e(0);
889e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
890e4e21ee1SDavid van Moolenbroek
891e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]) * 2;
892e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, bad_ptr, &oldlen, NULL, 0) != -1) e(0);
893e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
894e4e21ee1SDavid van Moolenbroek
895e4e21ee1SDavid van Moolenbroek memset(scn, 0x7, sizeof(scn[0]) * 2);
896e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]) * 2;
897e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, scn, &oldlen, NULL, 0) != 0) e(0);
898e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(scn[0])) e(0);
899e4e21ee1SDavid van Moolenbroek
900e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_num != SECRET_VALUE) e(0);
901e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn[0].sysctl_flags) != CTLTYPE_INT) e(0);
9026f3e0bcdSDavid van Moolenbroek if ((SYSCTL_FLAGS(scn[0].sysctl_flags) & ~CTLFLAG_PERMANENT) !=
903e4e21ee1SDavid van Moolenbroek (CTLFLAG_READONLY | CTLFLAG_IMMEDIATE)) e(0);
904e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(scn[0].sysctl_flags) != SYSCTL_VERSION) e(0);
905e4e21ee1SDavid van Moolenbroek if (strcmp(scn[0].sysctl_name, "value")) e(0);
906e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_ver == 0) e(0);
907e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_size != sizeof(int)) e(0);
908e4e21ee1SDavid van Moolenbroek if (scn[0].sysctl_idata != 12345) e(0);
909e4e21ee1SDavid van Moolenbroek if (scn[1].sysctl_name[0] != 0x07) e(0);
910e4e21ee1SDavid van Moolenbroek
911e4e21ee1SDavid van Moolenbroek /* Use a child process to test queries without root privileges. */
912e4e21ee1SDavid van Moolenbroek (void)test_nonroot(sub87b);
913e4e21ee1SDavid van Moolenbroek
914e4e21ee1SDavid van Moolenbroek /* Do some more path-related error code tests unrelated to the rest. */
915e4e21ee1SDavid van Moolenbroek mib[1] = INT_MAX;
916e4e21ee1SDavid van Moolenbroek mib[2] = CTL_QUERY;
917e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
918e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &scn, &oldlen, NULL, 0) != -1) e(0);
919e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
920e4e21ee1SDavid van Moolenbroek
921e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
922e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
923e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
924e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
925e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &scn, &oldlen, NULL, 0) != -1) e(0);
926e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0); /* ..and not EPERM (_INT is read-only) */
927e4e21ee1SDavid van Moolenbroek
928e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
929e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
930e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &scn, &oldlen, NULL, 0) != -1) e(0);
931e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0); /* (_BOOL is read-write) */
932e4e21ee1SDavid van Moolenbroek
933e4e21ee1SDavid van Moolenbroek mib[2] = CTL_QUERY;
934e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn[0]);
935e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &scn, &oldlen, NULL, 0) != -1) e(0);
936e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
937e4e21ee1SDavid van Moolenbroek }
938e4e21ee1SDavid van Moolenbroek
939e4e21ee1SDavid van Moolenbroek /*
940e4e21ee1SDavid van Moolenbroek * Attempt to create a node, using a given node template, identifier, and name
941e4e21ee1SDavid van Moolenbroek * string. If other_id is nonnegative, the creation is expected to fail due to
942e4e21ee1SDavid van Moolenbroek * a collision with an existing node, which should have the ID other_id and the
943e4e21ee1SDavid van Moolenbroek * name string in other_name. Otherwise, the creation may succeed or fail, and
944e4e21ee1SDavid van Moolenbroek * the caller must perform the appropriate checks. On success, return the new
945e4e21ee1SDavid van Moolenbroek * node identifier. On failure, return -1, with errno set.
946e4e21ee1SDavid van Moolenbroek */
947e4e21ee1SDavid van Moolenbroek static int
create_node(const int * path,unsigned int pathlen,struct sysctlnode * tmpscn,int id,const char * name,int other_id,const char * other_name)948e4e21ee1SDavid van Moolenbroek create_node(const int * path, unsigned int pathlen, struct sysctlnode * tmpscn,
949e4e21ee1SDavid van Moolenbroek int id, const char * name, int other_id, const char * other_name)
950e4e21ee1SDavid van Moolenbroek {
951e4e21ee1SDavid van Moolenbroek struct sysctlnode scn, oldscn;
952e4e21ee1SDavid van Moolenbroek size_t oldlen;
953e4e21ee1SDavid van Moolenbroek int r, mib[CTL_MAXNAME];
954e4e21ee1SDavid van Moolenbroek
955e4e21ee1SDavid van Moolenbroek assert(pathlen < CTL_MAXNAME);
956e4e21ee1SDavid van Moolenbroek memcpy(mib, path, sizeof(mib[0]) * pathlen);
957e4e21ee1SDavid van Moolenbroek mib[pathlen] = CTL_CREATE;
958e4e21ee1SDavid van Moolenbroek
959e4e21ee1SDavid van Moolenbroek memcpy(&scn, tmpscn, sizeof(scn));
960e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id;
961e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, name, sizeof(scn.sysctl_name));
962e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
963e4e21ee1SDavid van Moolenbroek r = sysctl(mib, pathlen + 1, &oldscn, &oldlen, &scn, sizeof(scn));
964e4e21ee1SDavid van Moolenbroek if (other_id >= 0) { /* conflict expected */
965e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
966e4e21ee1SDavid van Moolenbroek if (r != -1) e(0);
967e4e21ee1SDavid van Moolenbroek if (errno != EEXIST) e(0);
968e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_num != other_id) e(0);
969e4e21ee1SDavid van Moolenbroek if (strcmp(oldscn.sysctl_name, other_name)) e(0);
970e4e21ee1SDavid van Moolenbroek return -1;
971e4e21ee1SDavid van Moolenbroek } else {
972e4e21ee1SDavid van Moolenbroek if (r != 0)
973e4e21ee1SDavid van Moolenbroek return r;
974e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
975e4e21ee1SDavid van Moolenbroek return oldscn.sysctl_num;
976e4e21ee1SDavid van Moolenbroek }
977e4e21ee1SDavid van Moolenbroek }
978e4e21ee1SDavid van Moolenbroek
979e4e21ee1SDavid van Moolenbroek /*
980e4e21ee1SDavid van Moolenbroek * Destroy a node by identifier in the given named node directory. Return 0 on
981e4e21ee1SDavid van Moolenbroek * success. Return -1 on failure, with errno set.
982e4e21ee1SDavid van Moolenbroek */
983e4e21ee1SDavid van Moolenbroek static int
destroy_node(const int * path,unsigned int pathlen,int id)984e4e21ee1SDavid van Moolenbroek destroy_node(const int * path, unsigned int pathlen, int id)
985e4e21ee1SDavid van Moolenbroek {
986e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
987e4e21ee1SDavid van Moolenbroek int mib[CTL_MAXNAME];
988e4e21ee1SDavid van Moolenbroek
989e4e21ee1SDavid van Moolenbroek assert(pathlen < CTL_MAXNAME);
990e4e21ee1SDavid van Moolenbroek memcpy(mib, path, sizeof(mib[0]) * pathlen);
991e4e21ee1SDavid van Moolenbroek mib[pathlen] = CTL_DESTROY;
992e4e21ee1SDavid van Moolenbroek
993e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
994e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
995e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id;
996e4e21ee1SDavid van Moolenbroek
997e4e21ee1SDavid van Moolenbroek return sysctl(mib, pathlen + 1, NULL, NULL, &scn, sizeof(scn));
998e4e21ee1SDavid van Moolenbroek }
999e4e21ee1SDavid van Moolenbroek
1000e4e21ee1SDavid van Moolenbroek /*
1001e4e21ee1SDavid van Moolenbroek * Obtain the node data for one particular node in a node directory, by its
1002e4e21ee1SDavid van Moolenbroek * parent path and identifier. Return 0 on success, with the node details
1003e4e21ee1SDavid van Moolenbroek * stored in 'scn', or -1 on failure.
1004e4e21ee1SDavid van Moolenbroek */
1005e4e21ee1SDavid van Moolenbroek static int
query_node(const int * path,unsigned int pathlen,int id,struct sysctlnode * scn)1006e4e21ee1SDavid van Moolenbroek query_node(const int * path, unsigned int pathlen, int id,
1007e4e21ee1SDavid van Moolenbroek struct sysctlnode * scn)
1008e4e21ee1SDavid van Moolenbroek {
1009e4e21ee1SDavid van Moolenbroek struct sysctlnode scnset[32];
1010e4e21ee1SDavid van Moolenbroek size_t oldlen;
1011e4e21ee1SDavid van Moolenbroek unsigned int i;
1012e4e21ee1SDavid van Moolenbroek int r, mib[CTL_MAXNAME];
1013e4e21ee1SDavid van Moolenbroek
1014e4e21ee1SDavid van Moolenbroek assert(pathlen < CTL_MAXNAME);
1015e4e21ee1SDavid van Moolenbroek memcpy(mib, path, sizeof(mib[0]) * pathlen);
1016e4e21ee1SDavid van Moolenbroek mib[pathlen] = CTL_QUERY;
1017e4e21ee1SDavid van Moolenbroek
1018e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scnset);
1019e4e21ee1SDavid van Moolenbroek if ((r = sysctl(mib, pathlen + 1, scnset, &oldlen, NULL, 0)) != 0 &&
1020e4e21ee1SDavid van Moolenbroek errno != ENOMEM) e(0);
1021e4e21ee1SDavid van Moolenbroek if (oldlen == 0 || oldlen % sizeof(scnset[0])) e(0);
1022e4e21ee1SDavid van Moolenbroek for (i = 0; i < oldlen / sizeof(scnset[0]); i++)
1023e4e21ee1SDavid van Moolenbroek if (scnset[i].sysctl_num == id)
1024e4e21ee1SDavid van Moolenbroek break;
1025e4e21ee1SDavid van Moolenbroek if (i == oldlen / sizeof(scnset[0])) {
1026e4e21ee1SDavid van Moolenbroek if (r != 0) e(0); /* if this triggers, make scnset[] bigger! */
1027e4e21ee1SDavid van Moolenbroek return -1;
1028e4e21ee1SDavid van Moolenbroek }
1029e4e21ee1SDavid van Moolenbroek memcpy(scn, &scnset[i], sizeof(*scn));
1030e4e21ee1SDavid van Moolenbroek return 0;
1031e4e21ee1SDavid van Moolenbroek }
1032e4e21ee1SDavid van Moolenbroek
1033e4e21ee1SDavid van Moolenbroek /*
1034e4e21ee1SDavid van Moolenbroek * Test unprivileged node creation.
1035e4e21ee1SDavid van Moolenbroek */
1036e4e21ee1SDavid van Moolenbroek static void
sub87c(void)1037e4e21ee1SDavid van Moolenbroek sub87c(void)
1038e4e21ee1SDavid van Moolenbroek {
1039e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
1040e4e21ee1SDavid van Moolenbroek int mib[4];
1041e4e21ee1SDavid van Moolenbroek
1042e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
1043e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
1044e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1045e4e21ee1SDavid van Moolenbroek mib[3] = CTL_CREATE;
1046e4e21ee1SDavid van Moolenbroek
1047e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
1048e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_IMMEDIATE |
1049e4e21ee1SDavid van Moolenbroek CTLFLAG_READONLY | CTLTYPE_INT;
1050e4e21ee1SDavid van Moolenbroek scn.sysctl_size = sizeof(int);
1051e4e21ee1SDavid van Moolenbroek scn.sysctl_num = CTL_CREATE;
1052e4e21ee1SDavid van Moolenbroek scn.sysctl_idata = 777;
1053e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "nonroot", sizeof(scn.sysctl_name));
1054e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1055e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
1056e4e21ee1SDavid van Moolenbroek
1057e4e21ee1SDavid van Moolenbroek mib[0] = CTL_CREATE;
1058e4e21ee1SDavid van Moolenbroek scn.sysctl_num = CTL_MINIX + 1;
1059e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 1, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1060e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
1061e4e21ee1SDavid van Moolenbroek }
1062e4e21ee1SDavid van Moolenbroek
1063e4e21ee1SDavid van Moolenbroek /*
1064e4e21ee1SDavid van Moolenbroek * Test sysctl(2) node creation.
1065e4e21ee1SDavid van Moolenbroek */
1066e4e21ee1SDavid van Moolenbroek static void
test87c(void)1067e4e21ee1SDavid van Moolenbroek test87c(void)
1068e4e21ee1SDavid van Moolenbroek {
1069e4e21ee1SDavid van Moolenbroek static const uint32_t badflags[] = {
1070e4e21ee1SDavid van Moolenbroek SYSCTL_VERS_MASK, SYSCTL_TYPEMASK, CTLFLAG_PERMANENT,
1071e4e21ee1SDavid van Moolenbroek CTLFLAG_ROOT, CTLFLAG_ANYNUMBER, CTLFLAG_ALIAS, CTLFLAG_MMAP,
1072e4e21ee1SDavid van Moolenbroek CTLFLAG_OWNDESC
1073e4e21ee1SDavid van Moolenbroek };
1074e4e21ee1SDavid van Moolenbroek static const size_t badintsizes[] = {
1075e4e21ee1SDavid van Moolenbroek 0, 1, sizeof(int) - 1, sizeof(int) + 1, sizeof(int) * 2,
1076e4e21ee1SDavid van Moolenbroek sizeof(int) * 4, SSIZE_MAX, SIZE_MAX
1077e4e21ee1SDavid van Moolenbroek };
1078e4e21ee1SDavid van Moolenbroek static const char *goodnames[] = {
1079e4e21ee1SDavid van Moolenbroek "_", "a", "test_name", "_____foo", "bar_0_1_2_3", "_2bornot2b",
1080e4e21ee1SDavid van Moolenbroek "abcdefghijklmnopqrstuvwxyz12345",
1081e4e21ee1SDavid van Moolenbroek "ABCDEFGHIJKLMNOPQRSTUVWXYZ67890",
1082e4e21ee1SDavid van Moolenbroek };
1083e4e21ee1SDavid van Moolenbroek static const char *badnames[] = {
1084e4e21ee1SDavid van Moolenbroek "", "0", "test.name", "2bornot2b", "@a", "b[", "c`d", "{",
1085e4e21ee1SDavid van Moolenbroek "\n", "\xff", "dir/name", "foo:bar",
1086e4e21ee1SDavid van Moolenbroek "abcdefghijklmnopqrstuvwxyz123456"
1087e4e21ee1SDavid van Moolenbroek };
1088e4e21ee1SDavid van Moolenbroek struct sysctlnode scn, pscn, oldscn, newscn, tmpscn, scnset[32];
1089e4e21ee1SDavid van Moolenbroek size_t oldlen, len;
1090e4e21ee1SDavid van Moolenbroek char buf[32], seen[5];
1091e4e21ee1SDavid van Moolenbroek bool b;
1092e4e21ee1SDavid van Moolenbroek u_quad_t q;
1093e4e21ee1SDavid van Moolenbroek int i, mib[CTL_MAXNAME], id[3];
1094e4e21ee1SDavid van Moolenbroek
1095e4e21ee1SDavid van Moolenbroek subtest = 2;
1096e4e21ee1SDavid van Moolenbroek
1097e4e21ee1SDavid van Moolenbroek /*
1098e4e21ee1SDavid van Moolenbroek * On the first run of this test, this call with actually destroy a
1099e4e21ee1SDavid van Moolenbroek * static node. On subsequent runs, it may clean up the most likely
1100e4e21ee1SDavid van Moolenbroek * leftover from a previous failed test.
1101e4e21ee1SDavid van Moolenbroek */
1102e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
1103e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
1104e4e21ee1SDavid van Moolenbroek (void)destroy_node(mib, 2, TEST_DYNAMIC);
1105e4e21ee1SDavid van Moolenbroek
1106e4e21ee1SDavid van Moolenbroek /* Get child statistics about the parent node, for later comparison. */
1107e4e21ee1SDavid van Moolenbroek if (query_node(mib, 1, MINIX_TEST, &pscn) != 0) e(0);
1108e4e21ee1SDavid van Moolenbroek if (pscn.sysctl_clen == 0) e(0);
1109e4e21ee1SDavid van Moolenbroek if (pscn.sysctl_csize <= pscn.sysctl_clen) e(0);
1110e4e21ee1SDavid van Moolenbroek
1111e4e21ee1SDavid van Moolenbroek /* Start by testing if we can actually create a node at all. */
1112e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1113e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
1114e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_IMMEDIATE |
1115e4e21ee1SDavid van Moolenbroek CTLFLAG_READONLY | CTLTYPE_INT;
1116e4e21ee1SDavid van Moolenbroek scn.sysctl_size = sizeof(int);
1117e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
1118e4e21ee1SDavid van Moolenbroek scn.sysctl_idata = 777;
1119e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
1120e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn);
1121e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
1122e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newscn)) e(0);
1123e4e21ee1SDavid van Moolenbroek
1124e4e21ee1SDavid van Moolenbroek memcpy(&tmpscn, &scn, sizeof(scn));
1125e4e21ee1SDavid van Moolenbroek
1126e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_num != TEST_DYNAMIC) e(0);
1127e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(newscn.sysctl_flags) != CTLTYPE_INT) e(0);
1128e4e21ee1SDavid van Moolenbroek if (SYSCTL_FLAGS(newscn.sysctl_flags) !=
1129e4e21ee1SDavid van Moolenbroek (CTLFLAG_READONLY | CTLFLAG_IMMEDIATE)) e(0);
1130e4e21ee1SDavid van Moolenbroek if (SYSCTL_VERS(newscn.sysctl_flags) != SYSCTL_VERSION) e(0);
1131e4e21ee1SDavid van Moolenbroek if (strcmp(newscn.sysctl_name, "dynamic")) e(0);
1132e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_ver == 0) e(0);
1133e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_size != sizeof(int)) e(0);
1134e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_idata != 777) e(0);
1135e4e21ee1SDavid van Moolenbroek
1136e4e21ee1SDavid van Moolenbroek /* Can we also read its value? */
1137e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1138e4e21ee1SDavid van Moolenbroek i = 0;
1139e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
1140e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
1141e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
1142e4e21ee1SDavid van Moolenbroek if (i != 777) e(0);
1143e4e21ee1SDavid van Moolenbroek
1144e4e21ee1SDavid van Moolenbroek /* For now, we assume that basic node destruction works. */
1145e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1146e4e21ee1SDavid van Moolenbroek
1147e4e21ee1SDavid van Moolenbroek /* Try some variants of invalid new node data. */
1148e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1149e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1150e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 0) != -1) e(0);
1151e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1152e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn) - 1) != -1) e(0);
1153e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1154e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn) + 1) != -1) e(0);
1155e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1156e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, bad_ptr, sizeof(scn)) != -1) e(0);
1157e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1158e4e21ee1SDavid van Moolenbroek
1159e4e21ee1SDavid van Moolenbroek /* Try with an invalid flags field. */
1160e4e21ee1SDavid van Moolenbroek scn.sysctl_flags =
1161e4e21ee1SDavid van Moolenbroek (scn.sysctl_flags & ~SYSCTL_VERS_MASK) | SYSCTL_VERS_0;
1162e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1163e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1164e4e21ee1SDavid van Moolenbroek
1165e4e21ee1SDavid van Moolenbroek scn.sysctl_flags &= ~SYSCTL_TYPEMASK; /* type 0 does not exist */
1166e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1167e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1168e4e21ee1SDavid van Moolenbroek
1169e4e21ee1SDavid van Moolenbroek for (i = 0; i < __arraycount(badflags); i++) {
1170e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1171e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= badflags[i];
1172e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(i);
1173e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(i);
1174e4e21ee1SDavid van Moolenbroek }
1175e4e21ee1SDavid van Moolenbroek
1176e4e21ee1SDavid van Moolenbroek /* Try successful creation (and destruction) once more. */
1177e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1178e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1179e4e21ee1SDavid van Moolenbroek
1180e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1181e4e21ee1SDavid van Moolenbroek
1182e4e21ee1SDavid van Moolenbroek /* Try a combination of most valid flags. */
1183e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1184e4e21ee1SDavid van Moolenbroek scn.sysctl_flags &= ~CTLFLAG_READONLY; /* noop */
1185e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_READWRITE | CTLFLAG_ANYWRITE |
1186e4e21ee1SDavid van Moolenbroek CTLFLAG_PRIVATE | CTLFLAG_HEX | CTLFLAG_HIDDEN | CTLFLAG_UNSIGNED;
1187e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1188e4e21ee1SDavid van Moolenbroek
1189e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1190e4e21ee1SDavid van Moolenbroek
1191e4e21ee1SDavid van Moolenbroek /* Try invalid integer sizes. We will get to other types in a bit. */
1192e4e21ee1SDavid van Moolenbroek for (i = 0; i < __arraycount(badintsizes); i++) {
1193e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1194e4e21ee1SDavid van Moolenbroek scn.sysctl_size = badintsizes[i];
1195e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(i);
1196e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(i);
1197e4e21ee1SDavid van Moolenbroek }
1198e4e21ee1SDavid van Moolenbroek
1199e4e21ee1SDavid van Moolenbroek /*
1200e4e21ee1SDavid van Moolenbroek * For the value, we can supply IMMEDIATE, OWNDATA, or neither. For
1201e4e21ee1SDavid van Moolenbroek * IMMEDIATE, the integer value is taken directly from sysctl_idata.
1202e4e21ee1SDavid van Moolenbroek * If OWNDATA is set, sysctl_data may be set, in which case the integer
1203e4e21ee1SDavid van Moolenbroek * value is copied in from there. If sysctl_data is NULL, the integer
1204e4e21ee1SDavid van Moolenbroek * is initalized to zero. If neither flag is set, sysctl_data must be
1205e4e21ee1SDavid van Moolenbroek * NULL, since we do not support kernel addresses, and the integer will
1206e4e21ee1SDavid van Moolenbroek * similarly be initialized to zero. If both flags are set, the call
1207e4e21ee1SDavid van Moolenbroek * fails with EINVAL.
1208e4e21ee1SDavid van Moolenbroek */
1209e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1210e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA; /* both flags are now set */
1211e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1212e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1213e4e21ee1SDavid van Moolenbroek
1214e4e21ee1SDavid van Moolenbroek scn.sysctl_flags &= ~(CTLFLAG_IMMEDIATE | CTLFLAG_OWNDATA);
1215e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &i;
1216e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1217e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1218e4e21ee1SDavid van Moolenbroek
1219e4e21ee1SDavid van Moolenbroek scn.sysctl_data = NULL;
1220e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn);
1221e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
1222e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newscn)) e(0);
1223e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_flags & CTLFLAG_IMMEDIATE) e(0);
1224e4e21ee1SDavid van Moolenbroek if (!(newscn.sysctl_flags & CTLFLAG_OWNDATA)) e(0); /* auto-set */
1225e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_idata != 0) e(0);
1226e4e21ee1SDavid van Moolenbroek
1227e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1228e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
1229e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
1230e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
1231e4e21ee1SDavid van Moolenbroek if (i != 0) e(0);
1232e4e21ee1SDavid van Moolenbroek
1233e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1234e4e21ee1SDavid van Moolenbroek
1235e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1236e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1237e4e21ee1SDavid van Moolenbroek scn.sysctl_data = NULL;
1238e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1239e4e21ee1SDavid van Moolenbroek
1240e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1241e4e21ee1SDavid van Moolenbroek i = -1;
1242e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
1243e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
1244e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
1245e4e21ee1SDavid van Moolenbroek if (i != 0) e(0);
1246e4e21ee1SDavid van Moolenbroek
1247e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1248e4e21ee1SDavid van Moolenbroek
1249e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1250e4e21ee1SDavid van Moolenbroek scn.sysctl_data = bad_ptr;
1251e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1252e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1253e4e21ee1SDavid van Moolenbroek
1254e4e21ee1SDavid van Moolenbroek i = 999;
1255e4e21ee1SDavid van Moolenbroek scn.sysctl_data = (void *)&i;
1256e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn);
1257e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
1258e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newscn)) e(0);
1259e4e21ee1SDavid van Moolenbroek if ((newscn.sysctl_flags & (CTLFLAG_IMMEDIATE | CTLFLAG_OWNDATA)) !=
1260e4e21ee1SDavid van Moolenbroek CTLFLAG_OWNDATA) e(0);
1261e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_idata != 0) e(0);
1262e4e21ee1SDavid van Moolenbroek
1263e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1264e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
1265e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
1266e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
1267e4e21ee1SDavid van Moolenbroek if (i != 999) e(0);
1268e4e21ee1SDavid van Moolenbroek
1269e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1270e4e21ee1SDavid van Moolenbroek
1271e4e21ee1SDavid van Moolenbroek /* The user may never supply a function pointer or a parent. */
1272e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1273e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1274e4e21ee1SDavid van Moolenbroek scn.sysctl_func = (sysctlfn)test87c;
1275e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1276e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1277e4e21ee1SDavid van Moolenbroek
1278e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1279e4e21ee1SDavid van Moolenbroek scn.sysctl_parent = &scn;
1280e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1281e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1282e4e21ee1SDavid van Moolenbroek
1283e4e21ee1SDavid van Moolenbroek /* Test some good and bad node names. */
1284e4e21ee1SDavid van Moolenbroek for (i = 0; i < __arraycount(goodnames); i++) {
1285e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1286e4e21ee1SDavid van Moolenbroek len = strlen(goodnames[i]);
1287e4e21ee1SDavid van Moolenbroek memcpy(scn.sysctl_name, goodnames[i], len);
1288e4e21ee1SDavid van Moolenbroek memset(&scn.sysctl_name[len], 0, SYSCTL_NAMELEN - len);
1289e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(i);
1290e4e21ee1SDavid van Moolenbroek
1291e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(i);
1292e4e21ee1SDavid van Moolenbroek }
1293e4e21ee1SDavid van Moolenbroek
1294e4e21ee1SDavid van Moolenbroek for (i = 0; i < __arraycount(badnames); i++) {
1295e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1296e4e21ee1SDavid van Moolenbroek len = strlen(badnames[i]);
1297e4e21ee1SDavid van Moolenbroek memcpy(scn.sysctl_name, badnames[i], len);
1298e4e21ee1SDavid van Moolenbroek memset(&scn.sysctl_name[len], 0, SYSCTL_NAMELEN - len);
1299e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(i);
1300e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(i);
1301e4e21ee1SDavid van Moolenbroek }
1302e4e21ee1SDavid van Moolenbroek
1303e4e21ee1SDavid van Moolenbroek /*
1304e4e21ee1SDavid van Moolenbroek * Check for ID and name conflicts with existing nodes, starting with
1305e4e21ee1SDavid van Moolenbroek * the basics.
1306e4e21ee1SDavid van Moolenbroek */
1307e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1308e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1309e4e21ee1SDavid van Moolenbroek
1310e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1311e4e21ee1SDavid van Moolenbroek if (errno != EEXIST) e(0);
1312e4e21ee1SDavid van Moolenbroek
1313e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
1314e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != -1) e(0);
1315e4e21ee1SDavid van Moolenbroek if (errno != EEXIST) e(0);
1316e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
1317e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_ver == 0) e(0);
1318e4e21ee1SDavid van Moolenbroek oldscn.sysctl_ver = 0;
1319e4e21ee1SDavid van Moolenbroek if (memcmp(&oldscn, &tmpscn, sizeof(oldscn))) e(0);
1320e4e21ee1SDavid van Moolenbroek
1321e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn) - 1;
1322e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != -1) e(0);
1323e4e21ee1SDavid van Moolenbroek if (errno != EEXIST) e(0); /* ..we should not get ENOMEM now */
1324e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
1325e4e21ee1SDavid van Moolenbroek
1326e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
1327e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, &scn, sizeof(scn)) != -1) e(0);
1328e4e21ee1SDavid van Moolenbroek if (errno != EEXIST) e(0); /* ..we should not get EFAULT now */
1329e4e21ee1SDavid van Moolenbroek if (oldlen != 0) e(0); /* this is arguably an implementation detail */
1330e4e21ee1SDavid van Moolenbroek
1331e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1332e4e21ee1SDavid van Moolenbroek
1333e4e21ee1SDavid van Moolenbroek /* Test ID and name conflicts against static nodes. */
1334e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_INT, "dynamic", TEST_INT,
1335e4e21ee1SDavid van Moolenbroek "int") != -1) e(0);
1336e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_SECRET, "dynamic", TEST_SECRET,
1337e4e21ee1SDavid van Moolenbroek "secret") != -1) e(0);
1338e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_DYNAMIC, "quad", TEST_QUAD,
1339e4e21ee1SDavid van Moolenbroek "quad") != -1) e(0);
1340e4e21ee1SDavid van Moolenbroek
1341e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_DYNAMIC, "dynamic", -1,
1342e4e21ee1SDavid van Moolenbroek NULL) != TEST_DYNAMIC) e(0);
1343e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1344e4e21ee1SDavid van Moolenbroek
1345e4e21ee1SDavid van Moolenbroek /* Test unique ID generation and LL back insertion. */
1346e4e21ee1SDavid van Moolenbroek if ((id[0] = create_node(mib, 2, &tmpscn, CTL_CREATE, "id0", -1,
1347e4e21ee1SDavid van Moolenbroek NULL)) == -1) e(0);
1348e4e21ee1SDavid van Moolenbroek if ((id[1] = create_node(mib, 2, &tmpscn, CTL_CREATE, "id1", -1,
1349e4e21ee1SDavid van Moolenbroek NULL)) == -1) e(0);
1350e4e21ee1SDavid van Moolenbroek if ((id[2] = create_node(mib, 2, &tmpscn, CTL_CREATE, "id2", -1,
1351e4e21ee1SDavid van Moolenbroek NULL)) == -1) e(0);
1352e4e21ee1SDavid van Moolenbroek if (id[0] < CREATE_BASE || id[1] < CREATE_BASE || id[2] < CREATE_BASE)
1353e4e21ee1SDavid van Moolenbroek e(0);
1354e4e21ee1SDavid van Moolenbroek if (id[0] == id[1] || id[1] == id[2] || id[0] == id[2]) e(0);
1355e4e21ee1SDavid van Moolenbroek
1356e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, id[1]) != 0) e(0);
1357e4e21ee1SDavid van Moolenbroek
1358e4e21ee1SDavid van Moolenbroek /* Test ID and name conflicts against dynamic nodes. */
1359e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, id[0], "id1", id[0],
1360e4e21ee1SDavid van Moolenbroek "id0") != -1) e(0);
1361e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, id[2], "id1", id[2],
1362e4e21ee1SDavid van Moolenbroek "id2") != -1) e(0);
1363e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, id[1], "id0", id[0],
1364e4e21ee1SDavid van Moolenbroek "id0") != -1) e(0);
1365e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, id[1], "id2", id[2],
1366e4e21ee1SDavid van Moolenbroek "id2") != -1) e(0);
1367e4e21ee1SDavid van Moolenbroek
1368e4e21ee1SDavid van Moolenbroek /* Test name conflicts before and after LL insertion point. */
1369e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, CTL_CREATE, "id0", id[0],
1370e4e21ee1SDavid van Moolenbroek "id0") != -1) e(0);
1371e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, CTL_CREATE, "id2", id[2],
1372e4e21ee1SDavid van Moolenbroek "id2") != -1) e(0);
1373e4e21ee1SDavid van Moolenbroek
1374e4e21ee1SDavid van Moolenbroek /* Test recreation by ID and LL middle insertion. */
1375e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, id[1], "id1", -1, NULL) == -1) e(0);
1376e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, id[1]) != 0) e(0);
1377e4e21ee1SDavid van Moolenbroek
1378e4e21ee1SDavid van Moolenbroek /* Test dynamic recreation and more LL middle insertion. */
1379e4e21ee1SDavid van Moolenbroek if ((id[1] = create_node(mib, 2, &tmpscn, CTL_CREATE, "id1", -1,
1380e4e21ee1SDavid van Moolenbroek NULL)) == -1) e(0);
1381e4e21ee1SDavid van Moolenbroek if (id[1] < CREATE_BASE) e(0);
1382e4e21ee1SDavid van Moolenbroek if (id[1] == id[0] || id[1] == id[2]) e(0);
1383e4e21ee1SDavid van Moolenbroek
1384e4e21ee1SDavid van Moolenbroek /* Test LL front insertion. */
1385e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_DYNAMIC, "dynamic", -1,
1386e4e21ee1SDavid van Moolenbroek NULL) == -1) e(0);
1387e4e21ee1SDavid van Moolenbroek
1388e4e21ee1SDavid van Moolenbroek /* Ensure that all dynamic nodes show up in a query. */
1389e4e21ee1SDavid van Moolenbroek mib[2] = CTL_QUERY;
1390e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scnset);
1391e4e21ee1SDavid van Moolenbroek memset(seen, 0, sizeof(seen));
1392e4e21ee1SDavid van Moolenbroek memset(scnset, 0, sizeof(scnset));
1393e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, scnset, &oldlen, NULL, 0) != 0) e(0);
1394e4e21ee1SDavid van Moolenbroek if (oldlen % sizeof(scn)) e(0);
1395e4e21ee1SDavid van Moolenbroek for (i = 0; (unsigned int)i < oldlen / sizeof(scn); i++) {
1396e4e21ee1SDavid van Moolenbroek if (scnset[i].sysctl_num == TEST_INT) {
1397e4e21ee1SDavid van Moolenbroek if (strcmp(scnset[i].sysctl_name, "int")) e(0);
1398e4e21ee1SDavid van Moolenbroek seen[0]++;
1399e4e21ee1SDavid van Moolenbroek } else if (scnset[i].sysctl_num == TEST_DYNAMIC) {
1400e4e21ee1SDavid van Moolenbroek if (strcmp(scnset[i].sysctl_name, "dynamic")) e(0);
1401e4e21ee1SDavid van Moolenbroek seen[1]++;
1402e4e21ee1SDavid van Moolenbroek } else if (scnset[i].sysctl_num == id[0]) {
1403e4e21ee1SDavid van Moolenbroek if (strcmp(scnset[i].sysctl_name, "id0")) e(0);
1404e4e21ee1SDavid van Moolenbroek seen[2]++;
1405e4e21ee1SDavid van Moolenbroek } else if (scnset[i].sysctl_num == id[1]) {
1406e4e21ee1SDavid van Moolenbroek if (strcmp(scnset[i].sysctl_name, "id1")) e(0);
1407e4e21ee1SDavid van Moolenbroek seen[3]++;
1408e4e21ee1SDavid van Moolenbroek } else if (scnset[i].sysctl_num == id[2]) {
1409e4e21ee1SDavid van Moolenbroek if (strcmp(scnset[i].sysctl_name, "id2")) e(0);
1410e4e21ee1SDavid van Moolenbroek seen[4]++;
1411e4e21ee1SDavid van Moolenbroek }
1412e4e21ee1SDavid van Moolenbroek }
1413e4e21ee1SDavid van Moolenbroek for (i = 0; i < 5; i++)
1414e4e21ee1SDavid van Moolenbroek if (seen[i] != 1) e(i);
1415e4e21ee1SDavid van Moolenbroek
1416e4e21ee1SDavid van Moolenbroek /* Compare the parent's statistics with those obtained earlier. */
1417e4e21ee1SDavid van Moolenbroek if (query_node(mib, 1, MINIX_TEST, &scn) != 0) e(0);
1418e4e21ee1SDavid van Moolenbroek if (scn.sysctl_clen != pscn.sysctl_clen + 4) e(0);
1419e4e21ee1SDavid van Moolenbroek if (scn.sysctl_csize != pscn.sysctl_csize + 4) e(0);
1420e4e21ee1SDavid van Moolenbroek
1421e4e21ee1SDavid van Moolenbroek /* Clean up. */
1422e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, id[0]) != 0) e(0);
1423e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, id[1]) != 0) e(0);
1424e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, id[2]) != 0) e(0);
1425e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1426e4e21ee1SDavid van Moolenbroek
1427e4e21ee1SDavid van Moolenbroek /* Copy-out errors should not result in the node not being created. */
1428e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1429e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1430e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn) - 1;
1431e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newscn, &oldlen, &scn, sizeof(scn)) != -1) e(0);
1432e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
1433e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newscn)) e(0);
1434e4e21ee1SDavid van Moolenbroek
1435e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1436e4e21ee1SDavid van Moolenbroek
1437e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn);
1438e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, &scn, sizeof(scn)) != -1) e(0);
1439e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1440e4e21ee1SDavid van Moolenbroek
1441e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1442e4e21ee1SDavid van Moolenbroek
1443e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn) + 1;
1444e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
1445e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newscn)) e(0);
1446e4e21ee1SDavid van Moolenbroek
1447e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1448e4e21ee1SDavid van Moolenbroek
1449e4e21ee1SDavid van Moolenbroek /*
1450e4e21ee1SDavid van Moolenbroek * Now that we are done with the integer template, try other data
1451e4e21ee1SDavid van Moolenbroek * types, starting with booleans. A big part of these tests is that
1452e4e21ee1SDavid van Moolenbroek * the creation results in a usable node, regardless of the way its
1453e4e21ee1SDavid van Moolenbroek * contents were initialized.
1454e4e21ee1SDavid van Moolenbroek */
1455e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_flags =
1456e4e21ee1SDavid van Moolenbroek SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_BOOL;
1457e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_size = sizeof(b);
1458e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_data = NULL;
1459e4e21ee1SDavid van Moolenbroek
1460e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1461e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1462e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1463e4e21ee1SDavid van Moolenbroek
1464e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1465e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1466e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1467e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1468e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
1469e4e21ee1SDavid van Moolenbroek
1470e4e21ee1SDavid van Moolenbroek b = true;
1471e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &b, sizeof(b)) != 0) e(0);
1472e4e21ee1SDavid van Moolenbroek
1473e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1474e4e21ee1SDavid van Moolenbroek b = false;
1475e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1476e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1477e4e21ee1SDavid van Moolenbroek if (b != true) e(0);
1478e4e21ee1SDavid van Moolenbroek
1479e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1480e4e21ee1SDavid van Moolenbroek
1481e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1482e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1483e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_IMMEDIATE;
1484e4e21ee1SDavid van Moolenbroek scn.sysctl_bdata = true;
1485e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1486e4e21ee1SDavid van Moolenbroek
1487e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1488e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1489e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1490e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1491e4e21ee1SDavid van Moolenbroek if (b != true) e(0);
1492e4e21ee1SDavid van Moolenbroek
1493e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1494e4e21ee1SDavid van Moolenbroek
1495e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1496e4e21ee1SDavid van Moolenbroek scn.sysctl_bdata = false;
1497e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1498e4e21ee1SDavid van Moolenbroek
1499e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1500e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1501e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1502e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1503e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
1504e4e21ee1SDavid van Moolenbroek
1505e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1506e4e21ee1SDavid van Moolenbroek
1507e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1508e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1509e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &b;
1510e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1511e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1512e4e21ee1SDavid van Moolenbroek
1513e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1514e4e21ee1SDavid van Moolenbroek scn.sysctl_size++;
1515e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1516e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1517e4e21ee1SDavid van Moolenbroek
1518e4e21ee1SDavid van Moolenbroek scn.sysctl_size--;
1519e4e21ee1SDavid van Moolenbroek scn.sysctl_data = bad_ptr;
1520e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1521e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1522e4e21ee1SDavid van Moolenbroek
1523e4e21ee1SDavid van Moolenbroek b = true;
1524e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &b;
1525e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1526e4e21ee1SDavid van Moolenbroek
1527e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1528e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1529e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1530e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1531e4e21ee1SDavid van Moolenbroek if (b != true) e(0);
1532e4e21ee1SDavid van Moolenbroek
1533e4e21ee1SDavid van Moolenbroek b = false;
1534e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1535e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1536e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1537e4e21ee1SDavid van Moolenbroek if (b != true) e(0);
1538e4e21ee1SDavid van Moolenbroek
1539e4e21ee1SDavid van Moolenbroek b = false;
1540e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &b, sizeof(b)) != 0) e(0);
1541e4e21ee1SDavid van Moolenbroek
1542e4e21ee1SDavid van Moolenbroek oldlen = sizeof(b);
1543e4e21ee1SDavid van Moolenbroek b = true;
1544e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &b, &oldlen, NULL, 0) != 0) e(0);
1545e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(b)) e(0);
1546e4e21ee1SDavid van Moolenbroek if (b != false) e(0);
1547e4e21ee1SDavid van Moolenbroek
1548e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1549e4e21ee1SDavid van Moolenbroek
1550e4e21ee1SDavid van Moolenbroek /* Test quads next. */
1551e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_flags =
1552e4e21ee1SDavid van Moolenbroek SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_QUAD;
1553e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_size = sizeof(q);
1554e4e21ee1SDavid van Moolenbroek
1555e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1556e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1557e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1558e4e21ee1SDavid van Moolenbroek
1559e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1560e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
1561e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
1562e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
1563e4e21ee1SDavid van Moolenbroek if (q != 0) e(0);
1564e4e21ee1SDavid van Moolenbroek
1565e4e21ee1SDavid van Moolenbroek q = ~0ULL;
1566e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &q, sizeof(q)) != 0) e(0);
1567e4e21ee1SDavid van Moolenbroek
1568e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
1569e4e21ee1SDavid van Moolenbroek q = 0;
1570e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
1571e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
1572e4e21ee1SDavid van Moolenbroek if (q != ~0ULL) e(0);
1573e4e21ee1SDavid van Moolenbroek
1574e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1575e4e21ee1SDavid van Moolenbroek
1576e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1577e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1578e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_IMMEDIATE;
1579e4e21ee1SDavid van Moolenbroek scn.sysctl_qdata = 1ULL << 48;
1580e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1581e4e21ee1SDavid van Moolenbroek
1582e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1583e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
1584e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
1585e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
1586e4e21ee1SDavid van Moolenbroek if (q != (1ULL << 48)) e(0);
1587e4e21ee1SDavid van Moolenbroek
1588e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1589e4e21ee1SDavid van Moolenbroek
1590e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1591e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1592e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &q;
1593e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1594e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1595e4e21ee1SDavid van Moolenbroek
1596e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1597e4e21ee1SDavid van Moolenbroek scn.sysctl_size <<= 1;
1598e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1599e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1600e4e21ee1SDavid van Moolenbroek
1601e4e21ee1SDavid van Moolenbroek scn.sysctl_size >>= 1;
1602e4e21ee1SDavid van Moolenbroek scn.sysctl_data = bad_ptr;
1603e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1604e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1605e4e21ee1SDavid van Moolenbroek
1606e4e21ee1SDavid van Moolenbroek q = 123ULL << 31;
1607e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &q;
1608e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1609e4e21ee1SDavid van Moolenbroek
1610e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1611e4e21ee1SDavid van Moolenbroek oldlen = sizeof(q);
1612e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &q, &oldlen, NULL, 0) != 0) e(0);
1613e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(q)) e(0);
1614e4e21ee1SDavid van Moolenbroek if (q != (123ULL << 31)) e(0);
1615e4e21ee1SDavid van Moolenbroek
1616e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1617e4e21ee1SDavid van Moolenbroek
1618e4e21ee1SDavid van Moolenbroek /* Test strings. */
1619e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_flags =
1620e4e21ee1SDavid van Moolenbroek SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_STRING;
1621e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_size = 7;
1622e4e21ee1SDavid van Moolenbroek
1623e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1624e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1625e4e21ee1SDavid van Moolenbroek scn.sysctl_data = buf;
1626e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1627e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1628e4e21ee1SDavid van Moolenbroek
1629e4e21ee1SDavid van Moolenbroek scn.sysctl_data = NULL;
1630e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1631e4e21ee1SDavid van Moolenbroek
1632e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1633e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1634e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1635e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1636e4e21ee1SDavid van Moolenbroek if (oldlen != 1) e(0);
1637e4e21ee1SDavid van Moolenbroek if (buf[0] != '\0') e(0);
1638e4e21ee1SDavid van Moolenbroek if (buf[1] != 0x7f) e(0);
1639e4e21ee1SDavid van Moolenbroek
1640e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, "woobie!", 8) != -1) e(0);
1641e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1642e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, "woobie!", 7) != -1) e(0);
1643e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1644e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, "woobie", 7) != 0) e(0);
1645e4e21ee1SDavid van Moolenbroek
1646e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1647e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1648e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1649e4e21ee1SDavid van Moolenbroek if (oldlen != 7) e(0);
1650e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "woobie")) e(0);
1651e4e21ee1SDavid van Moolenbroek if (buf[7] != 0x7f) e(0);
1652e4e21ee1SDavid van Moolenbroek
1653e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1654e4e21ee1SDavid van Moolenbroek
1655e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1656e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1657e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_IMMEDIATE;
1658e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1659e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1660e4e21ee1SDavid van Moolenbroek
1661e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1662e4e21ee1SDavid van Moolenbroek scn.sysctl_size = 0;
1663e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1664e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1665e4e21ee1SDavid van Moolenbroek
1666e4e21ee1SDavid van Moolenbroek scn.sysctl_data = buf;
1667e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1668e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1669e4e21ee1SDavid van Moolenbroek
1670e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1671*3083d603SDavid van Moolenbroek scn.sysctl_size = (size_t)SSIZE_MAX + 1;
1672e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1673e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1674e4e21ee1SDavid van Moolenbroek
1675e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1676e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1677e4e21ee1SDavid van Moolenbroek scn.sysctl_data = bad_ptr;
1678e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1679e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1680e4e21ee1SDavid van Moolenbroek
1681e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1682e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1683e4e21ee1SDavid van Moolenbroek scn.sysctl_data = "abc123?";
1684e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1685e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1686e4e21ee1SDavid van Moolenbroek
1687e4e21ee1SDavid van Moolenbroek scn.sysctl_data = "abc123";
1688e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1689e4e21ee1SDavid van Moolenbroek
1690e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1691e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1692e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1693e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1694e4e21ee1SDavid van Moolenbroek if (oldlen != 7) e(0);
1695e4e21ee1SDavid van Moolenbroek if (strcmp(buf, "abc123")) e(0);
1696e4e21ee1SDavid van Moolenbroek if (buf[7] != 0x7f) e(0);
1697e4e21ee1SDavid van Moolenbroek
1698e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, "", 1) != 0) e(0);
1699e4e21ee1SDavid van Moolenbroek
1700e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1701e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1702e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1703e4e21ee1SDavid van Moolenbroek if (oldlen != 1) e(0);
1704e4e21ee1SDavid van Moolenbroek if (buf[0] != '\0') e(0);
1705e4e21ee1SDavid van Moolenbroek if (buf[1] != 0x7f) e(0);
1706e4e21ee1SDavid van Moolenbroek
1707e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1708e4e21ee1SDavid van Moolenbroek
1709e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1710e4e21ee1SDavid van Moolenbroek scn.sysctl_data = "";
1711e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1712e4e21ee1SDavid van Moolenbroek
1713e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1714e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1715e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1716e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1717e4e21ee1SDavid van Moolenbroek if (oldlen != 1) e(0);
1718e4e21ee1SDavid van Moolenbroek if (buf[0] != '\0') e(0);
1719e4e21ee1SDavid van Moolenbroek if (buf[7] != 0x7f) e(0);
1720e4e21ee1SDavid van Moolenbroek
1721e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1722e4e21ee1SDavid van Moolenbroek
1723e4e21ee1SDavid van Moolenbroek /*
1724e4e21ee1SDavid van Moolenbroek * For strings, a zero node size means that the string length
1725e4e21ee1SDavid van Moolenbroek * determines the buffer size.
1726e4e21ee1SDavid van Moolenbroek */
1727e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1728e4e21ee1SDavid van Moolenbroek scn.sysctl_size = 0;
1729e4e21ee1SDavid van Moolenbroek scn.sysctl_data = NULL;
1730e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1731e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1732e4e21ee1SDavid van Moolenbroek
1733e4e21ee1SDavid van Moolenbroek scn.sysctl_data = bad_ptr;
1734e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1735e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1736e4e21ee1SDavid van Moolenbroek
1737e4e21ee1SDavid van Moolenbroek scn.sysctl_data = "This is a string initializer."; /* size 29+1 */
1738e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1739e4e21ee1SDavid van Moolenbroek
1740e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1741e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1742e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1743e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1744e4e21ee1SDavid van Moolenbroek if (oldlen != strlen(scn.sysctl_data) + 1) e(0);
1745e4e21ee1SDavid van Moolenbroek if (buf[oldlen - 1] != '\0') e(0);
1746e4e21ee1SDavid van Moolenbroek if (buf[oldlen] != 0x7f) e(0);
1747e4e21ee1SDavid van Moolenbroek
1748e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &newscn) != 0) e(0);
1749e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_size != strlen(scn.sysctl_data) + 1) e(0);
1750e4e21ee1SDavid van Moolenbroek
1751e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1752e4e21ee1SDavid van Moolenbroek
1753e4e21ee1SDavid van Moolenbroek /* Test structs. */
1754e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_flags =
1755e4e21ee1SDavid van Moolenbroek SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_STRUCT;
1756e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_size = 21;
1757e4e21ee1SDavid van Moolenbroek
1758e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1759e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1760e4e21ee1SDavid van Moolenbroek scn.sysctl_data = buf;
1761e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1762e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1763e4e21ee1SDavid van Moolenbroek
1764e4e21ee1SDavid van Moolenbroek scn.sysctl_data = NULL;
1765e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1766e4e21ee1SDavid van Moolenbroek
1767e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1768e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1769e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1770e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1771e4e21ee1SDavid van Moolenbroek if (oldlen != 21) e(0);
1772e4e21ee1SDavid van Moolenbroek for (i = 0; i < 21; i++)
1773e4e21ee1SDavid van Moolenbroek if (buf[i] != 0) e(i);
1774e4e21ee1SDavid van Moolenbroek if (buf[i] != 0x7f) e(0);
1775e4e21ee1SDavid van Moolenbroek
1776e4e21ee1SDavid van Moolenbroek memset(buf, 'x', 32);
1777e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, 20) != -1) e(0);
1778e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1779e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, 22) != -1) e(0);
1780e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1781e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, buf, 21) != 0) e(0);
1782e4e21ee1SDavid van Moolenbroek
1783e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1784e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1785e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1786e4e21ee1SDavid van Moolenbroek if (oldlen != 21) e(0);
1787e4e21ee1SDavid van Moolenbroek for (i = 0; i < 21; i++)
1788e4e21ee1SDavid van Moolenbroek if (buf[i] != 'x') e(i);
1789e4e21ee1SDavid van Moolenbroek if (buf[i] != 0x7f) e(0);
1790e4e21ee1SDavid van Moolenbroek
1791e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1792e4e21ee1SDavid van Moolenbroek
1793e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1794e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1795e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_IMMEDIATE;
1796e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1797e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1798e4e21ee1SDavid van Moolenbroek
1799e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1800e4e21ee1SDavid van Moolenbroek scn.sysctl_size = 0;
1801e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1802e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1803e4e21ee1SDavid van Moolenbroek
1804e4e21ee1SDavid van Moolenbroek scn.sysctl_data = buf;
1805e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1806e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1807e4e21ee1SDavid van Moolenbroek
1808e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1809*3083d603SDavid van Moolenbroek scn.sysctl_size = (size_t)SSIZE_MAX + 1;
1810e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1811e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1812e4e21ee1SDavid van Moolenbroek
1813e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1814e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1815e4e21ee1SDavid van Moolenbroek scn.sysctl_data = bad_ptr;
1816e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1817e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
1818e4e21ee1SDavid van Moolenbroek
1819e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1820e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1821e4e21ee1SDavid van Moolenbroek for (i = 0; i < sizeof(buf); i++)
1822e4e21ee1SDavid van Moolenbroek buf[i] = i;
1823e4e21ee1SDavid van Moolenbroek scn.sysctl_data = buf;
1824e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1825e4e21ee1SDavid van Moolenbroek
1826e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1827e4e21ee1SDavid van Moolenbroek memset(buf, 0x7f, sizeof(buf));
1828e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1829e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
1830e4e21ee1SDavid van Moolenbroek if (oldlen != 21) e(0);
1831e4e21ee1SDavid van Moolenbroek for (i = 0; i < 21; i++)
1832e4e21ee1SDavid van Moolenbroek if (buf[i] != i) e(i);
1833e4e21ee1SDavid van Moolenbroek if (buf[i] != 0x7f) e(0);
1834e4e21ee1SDavid van Moolenbroek
1835e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1836e4e21ee1SDavid van Moolenbroek
1837e4e21ee1SDavid van Moolenbroek /* Finally, test node-type nodes. */
1838e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_flags =
1839e4e21ee1SDavid van Moolenbroek SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_NODE;
1840e4e21ee1SDavid van Moolenbroek tmpscn.sysctl_size = 0;
1841e4e21ee1SDavid van Moolenbroek
1842e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1843e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1844e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1845e4e21ee1SDavid van Moolenbroek
1846e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1847e4e21ee1SDavid van Moolenbroek
1848e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_IMMEDIATE;
1849e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1850e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1851e4e21ee1SDavid van Moolenbroek
1852e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1853e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_IMMEDIATE;
1854e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1855e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1856e4e21ee1SDavid van Moolenbroek
1857e4e21ee1SDavid van Moolenbroek scn.sysctl_size = sizeof(scn);
1858e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1859e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1860e4e21ee1SDavid van Moolenbroek
1861e4e21ee1SDavid van Moolenbroek scn.sysctl_flags &= ~CTLFLAG_IMMEDIATE;
1862e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1863e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1864e4e21ee1SDavid van Moolenbroek
1865e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_OWNDATA;
1866e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1867e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1868e4e21ee1SDavid van Moolenbroek
1869e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1870e4e21ee1SDavid van Moolenbroek scn.sysctl_csize = 8;
1871e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1872e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1873e4e21ee1SDavid van Moolenbroek
1874e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1875e4e21ee1SDavid van Moolenbroek scn.sysctl_clen = 1;
1876e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1877e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1878e4e21ee1SDavid van Moolenbroek
1879e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1880e4e21ee1SDavid van Moolenbroek scn.sysctl_child = &scn;
1881e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1882e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1883e4e21ee1SDavid van Moolenbroek
1884e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1885e4e21ee1SDavid van Moolenbroek scn.sysctl_parent = &scn;
1886e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1887e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1888e4e21ee1SDavid van Moolenbroek
1889e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1890e4e21ee1SDavid van Moolenbroek scn.sysctl_func = (sysctlfn)test87c;
1891e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
1892e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1893e4e21ee1SDavid van Moolenbroek
1894e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1895e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1896e4e21ee1SDavid van Moolenbroek
1897e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &scn) != 0) e(0);
1898e4e21ee1SDavid van Moolenbroek if (scn.sysctl_csize != 0) e(0);
1899e4e21ee1SDavid van Moolenbroek if (scn.sysctl_clen != 0) e(0);
1900e4e21ee1SDavid van Moolenbroek
1901e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
1902e4e21ee1SDavid van Moolenbroek
1903e4e21ee1SDavid van Moolenbroek for (i = 3; i < CTL_MAXNAME; i++) {
1904e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1905e4e21ee1SDavid van Moolenbroek if (i % 2)
1906e4e21ee1SDavid van Moolenbroek scn.sysctl_num = i - 3;
1907e4e21ee1SDavid van Moolenbroek else
1908e4e21ee1SDavid van Moolenbroek scn.sysctl_num = CTL_CREATE;
1909e4e21ee1SDavid van Moolenbroek /*
1910e4e21ee1SDavid van Moolenbroek * Test both names with different length (depthN vs depthNN)
1911e4e21ee1SDavid van Moolenbroek * and cross-directory name duplicates (depth7.depth7).
1912e4e21ee1SDavid van Moolenbroek */
1913e4e21ee1SDavid van Moolenbroek snprintf(scn.sysctl_name, sizeof(scn.sysctl_name), "depth%u",
1914e4e21ee1SDavid van Moolenbroek 7 + i / 2);
1915e4e21ee1SDavid van Moolenbroek mib[i] = CTL_CREATE;
1916e4e21ee1SDavid van Moolenbroek
1917e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn);
1918e4e21ee1SDavid van Moolenbroek if (sysctl(mib, i + 1, &newscn, &oldlen, &scn,
1919e4e21ee1SDavid van Moolenbroek sizeof(scn)) != 0) e(0);
1920e4e21ee1SDavid van Moolenbroek mib[i] = newscn.sysctl_num;
1921e4e21ee1SDavid van Moolenbroek }
1922e4e21ee1SDavid van Moolenbroek
1923e4e21ee1SDavid van Moolenbroek id[0] = mib[i - 1];
1924e4e21ee1SDavid van Moolenbroek mib[i - 1] = CTL_CREATE;
1925e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
1926e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READONLY |
1927e4e21ee1SDavid van Moolenbroek CTLFLAG_OWNDATA | CTLTYPE_STRING;
1928e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id[0] + 1;
1929e4e21ee1SDavid van Moolenbroek scn.sysctl_data = "bar";
1930e4e21ee1SDavid van Moolenbroek scn.sysctl_size = strlen(scn.sysctl_data) + 1;
1931e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "foo", sizeof(scn.sysctl_name));
1932e4e21ee1SDavid van Moolenbroek if (sysctl(mib, i, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1933e4e21ee1SDavid van Moolenbroek mib[i - 1] = id[0] + 1;
1934e4e21ee1SDavid van Moolenbroek
1935e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
1936e4e21ee1SDavid van Moolenbroek if (sysctl(mib, i, buf, &oldlen, NULL, 0) != 0) e(0);
1937e4e21ee1SDavid van Moolenbroek if (oldlen != strlen(scn.sysctl_data) + 1) e(0);
1938e4e21ee1SDavid van Moolenbroek if (strcmp(buf, scn.sysctl_data)) e(0);
1939e4e21ee1SDavid van Moolenbroek
1940e4e21ee1SDavid van Moolenbroek if (query_node(mib, i - 2, mib[i - 2], &scn) != 0) e(0);
1941e4e21ee1SDavid van Moolenbroek if (scn.sysctl_csize != 2) e(0);
1942e4e21ee1SDavid van Moolenbroek if (scn.sysctl_clen != 2) e(0);
1943e4e21ee1SDavid van Moolenbroek
1944e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &scn) != 0) e(0);
1945e4e21ee1SDavid van Moolenbroek if (scn.sysctl_csize != 1) e(0);
1946e4e21ee1SDavid van Moolenbroek if (scn.sysctl_clen != 1) e(0);
1947e4e21ee1SDavid van Moolenbroek
1948e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, i - 1, mib[i - 1]) != 0) e(0);
1949e4e21ee1SDavid van Moolenbroek mib[i - 1]--;
1950e4e21ee1SDavid van Moolenbroek
1951e4e21ee1SDavid van Moolenbroek for (i--; i > 2; i--)
1952e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, i, mib[i]) != 0) e(0);
1953e4e21ee1SDavid van Moolenbroek
1954e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &scn) != 0) e(0);
1955e4e21ee1SDavid van Moolenbroek if (scn.sysctl_csize != 0) e(0);
1956e4e21ee1SDavid van Moolenbroek if (scn.sysctl_clen != 0) e(0);
1957e4e21ee1SDavid van Moolenbroek
1958e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1959e4e21ee1SDavid van Moolenbroek
1960e4e21ee1SDavid van Moolenbroek /*
1961e4e21ee1SDavid van Moolenbroek * Finally, ensure that unprivileged processes cannot create nodes,
1962e4e21ee1SDavid van Moolenbroek * even in the most friendly place possible.
1963e4e21ee1SDavid van Moolenbroek */
1964e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1965e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1966e4e21ee1SDavid van Moolenbroek scn.sysctl_flags |= CTLFLAG_ANYWRITE;
1967e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
1968e4e21ee1SDavid van Moolenbroek
1969e4e21ee1SDavid van Moolenbroek (void)test_nonroot(sub87c);
1970e4e21ee1SDavid van Moolenbroek
1971e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
1972e4e21ee1SDavid van Moolenbroek
1973e4e21ee1SDavid van Moolenbroek /*
1974e4e21ee1SDavid van Moolenbroek * Now that we are done, compare the parent's statistics with those
1975e4e21ee1SDavid van Moolenbroek * obtained earlier once more. There must be no differences.
1976e4e21ee1SDavid van Moolenbroek */
1977e4e21ee1SDavid van Moolenbroek if (query_node(mib, 1, MINIX_TEST, &scn) != 0) e(0);
1978e4e21ee1SDavid van Moolenbroek if (scn.sysctl_clen != pscn.sysctl_clen) e(0);
1979e4e21ee1SDavid van Moolenbroek if (scn.sysctl_csize != pscn.sysctl_csize) e(0);
1980e4e21ee1SDavid van Moolenbroek
1981e4e21ee1SDavid van Moolenbroek /* Do some more path-related error code tests unrelated to the rest. */
1982e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
1983e4e21ee1SDavid van Moolenbroek mib[1] = INT_MAX;
1984e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &scn, TEST_DYNAMIC, "d", -1, NULL) != -1) e(0);
1985e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
1986e4e21ee1SDavid van Moolenbroek
1987e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
1988e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
1989e4e21ee1SDavid van Moolenbroek if (create_node(mib, 3, &scn, TEST_DYNAMIC, "d", -1, NULL) != -1) e(0);
1990e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
1991e4e21ee1SDavid van Moolenbroek
1992e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
1993e4e21ee1SDavid van Moolenbroek if (create_node(mib, 3, &scn, TEST_DYNAMIC, "d", -1, NULL) != -1) e(0);
1994e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
1995e4e21ee1SDavid van Moolenbroek
1996e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
1997e4e21ee1SDavid van Moolenbroek if (create_node(mib, 3, &scn, TEST_DYNAMIC, "d", -1, NULL) != -1) e(0);
1998e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
1999e4e21ee1SDavid van Moolenbroek
2000e4e21ee1SDavid van Moolenbroek /* Finally, try to create a node in a read-only directory node. */
2001e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
2002e4e21ee1SDavid van Moolenbroek if (create_node(mib, 3, &scn, -1, "d", -1, NULL) != -1) e(0);
2003e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2004e4e21ee1SDavid van Moolenbroek }
2005e4e21ee1SDavid van Moolenbroek
2006e4e21ee1SDavid van Moolenbroek /*
2007e4e21ee1SDavid van Moolenbroek * Test unprivileged node destruction.
2008e4e21ee1SDavid van Moolenbroek */
2009e4e21ee1SDavid van Moolenbroek static void
sub87d(void)2010e4e21ee1SDavid van Moolenbroek sub87d(void)
2011e4e21ee1SDavid van Moolenbroek {
2012e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
2013e4e21ee1SDavid van Moolenbroek int mib[3];
2014e4e21ee1SDavid van Moolenbroek
2015e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2016e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2017e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESTROY;
2018e4e21ee1SDavid van Moolenbroek
2019e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2020e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2021e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_ANYWRITE;
2022e4e21ee1SDavid van Moolenbroek
2023e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2024e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2025e4e21ee1SDavid van Moolenbroek
2026e4e21ee1SDavid van Moolenbroek mib[0] = CTL_DESTROY;
2027e4e21ee1SDavid van Moolenbroek scn.sysctl_num = CTL_MINIX;
2028e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 1, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2029e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2030e4e21ee1SDavid van Moolenbroek }
2031e4e21ee1SDavid van Moolenbroek
2032e4e21ee1SDavid van Moolenbroek /*
2033e4e21ee1SDavid van Moolenbroek * Test sysctl(2) node destruction.
2034e4e21ee1SDavid van Moolenbroek */
2035e4e21ee1SDavid van Moolenbroek static void
test87d(void)2036e4e21ee1SDavid van Moolenbroek test87d(void)
2037e4e21ee1SDavid van Moolenbroek {
2038e4e21ee1SDavid van Moolenbroek struct sysctlnode scn, oldscn, newscn, tmpscn;
2039e4e21ee1SDavid van Moolenbroek size_t oldlen;
2040e4e21ee1SDavid van Moolenbroek char buf[16];
2041e4e21ee1SDavid van Moolenbroek int i, r, mib[4], id[15];
2042e4e21ee1SDavid van Moolenbroek
2043e4e21ee1SDavid van Moolenbroek subtest = 3;
2044e4e21ee1SDavid van Moolenbroek
2045e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2046e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2047e4e21ee1SDavid van Moolenbroek (void)destroy_node(mib, 2, TEST_DYNAMIC);
2048e4e21ee1SDavid van Moolenbroek
2049e4e21ee1SDavid van Moolenbroek /* Start with the path-related error code tests this time. */
2050e4e21ee1SDavid van Moolenbroek mib[1] = INT_MAX;
2051e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(0);
2052e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2053e4e21ee1SDavid van Moolenbroek
2054e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2055e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
2056e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, TEST_DYNAMIC) != -1) e(0);
2057e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
2058e4e21ee1SDavid van Moolenbroek
2059e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
2060e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, TEST_DYNAMIC) != -1) e(0);
2061e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
2062e4e21ee1SDavid van Moolenbroek
2063e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESTROY;
2064e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, TEST_DYNAMIC) != -1) e(0);
2065e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2066e4e21ee1SDavid van Moolenbroek
2067e4e21ee1SDavid van Moolenbroek /* Actual API tests. */
2068e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2069e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
2070e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2071e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_IMMEDIATE |
2072e4e21ee1SDavid van Moolenbroek CTLFLAG_READONLY | CTLTYPE_INT;
2073e4e21ee1SDavid van Moolenbroek scn.sysctl_size = sizeof(int);
2074e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2075e4e21ee1SDavid van Moolenbroek scn.sysctl_idata = 31415926;
2076e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
2077e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
2078e4e21ee1SDavid van Moolenbroek
2079e4e21ee1SDavid van Moolenbroek memcpy(&tmpscn, &scn, sizeof(scn));
2080e4e21ee1SDavid van Moolenbroek
2081e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESTROY;
2082e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 0) != -1) e(0);
2083e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2084e4e21ee1SDavid van Moolenbroek
2085e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, bad_ptr, sizeof(scn)) != -1) e(0);
2086e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2087e4e21ee1SDavid van Moolenbroek
2088e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2089e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERS_0;
2090e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2091e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2092e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2093e4e21ee1SDavid van Moolenbroek
2094e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2095e4e21ee1SDavid van Moolenbroek scn.sysctl_num = INT_MAX; /* anything not valid */
2096e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn);
2097e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2098e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2099e4e21ee1SDavid van Moolenbroek if (oldlen != 0) e(0);
2100e4e21ee1SDavid van Moolenbroek
2101e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_PERM;
2102e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn);
2103e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2104e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2105e4e21ee1SDavid van Moolenbroek if (oldlen != 0) e(0);
2106e4e21ee1SDavid van Moolenbroek
2107e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_SECRET;
2108e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2109e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(0);
2110e4e21ee1SDavid van Moolenbroek
2111e4e21ee1SDavid van Moolenbroek scn.sysctl_num = -1;
2112e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
2113e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2114e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2115e4e21ee1SDavid van Moolenbroek
2116e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2117e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynami", sizeof(scn.sysctl_name));
2118e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2119e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2120e4e21ee1SDavid van Moolenbroek
2121e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic2", sizeof(scn.sysctl_name));
2122e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2123e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2124e4e21ee1SDavid van Moolenbroek
2125e4e21ee1SDavid van Moolenbroek memset(scn.sysctl_name, 'd', sizeof(scn.sysctl_name));
2126e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2127e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2128e4e21ee1SDavid van Moolenbroek
2129e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
2130e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
2131e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
2132e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
2133e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_ver == 0) e(0);
2134e4e21ee1SDavid van Moolenbroek oldscn.sysctl_ver = 0;
2135e4e21ee1SDavid van Moolenbroek if (memcmp(&oldscn, &tmpscn, sizeof(oldscn))) e(0);
2136e4e21ee1SDavid van Moolenbroek
2137e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2138e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2139e4e21ee1SDavid van Moolenbroek
2140e4e21ee1SDavid van Moolenbroek /*
2141e4e21ee1SDavid van Moolenbroek * We already tested destruction of one static node, by destroying
2142e4e21ee1SDavid van Moolenbroek * TEST_DYNAMIC on the first run. We now do a second deletion of a
2143e4e21ee1SDavid van Moolenbroek * static node, TEST_DESTROY2, to test proper adjustment of parent
2144e4e21ee1SDavid van Moolenbroek * stats. We do a third static node deletion (on TEST_DESTROY1) later,
2145e4e21ee1SDavid van Moolenbroek * to see that static nodes with dynamic descriptions can be freed.
2146e4e21ee1SDavid van Moolenbroek */
2147e4e21ee1SDavid van Moolenbroek if (query_node(mib, 1, MINIX_TEST, &oldscn) != 0) e(0);
2148e4e21ee1SDavid van Moolenbroek
2149e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2150e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2151e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DESTROY2;
2152e4e21ee1SDavid van Moolenbroek r = sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn));
2153e4e21ee1SDavid van Moolenbroek if (r != 0 && r != -1) e(0);
2154e4e21ee1SDavid van Moolenbroek if (r == -1 && errno != ENOENT) e(0);
2155e4e21ee1SDavid van Moolenbroek
2156e4e21ee1SDavid van Moolenbroek if (query_node(mib, 1, MINIX_TEST, &newscn) != 0) e(0);
2157e4e21ee1SDavid van Moolenbroek
2158e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_csize != oldscn.sysctl_csize) e(0);
2159e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_clen != oldscn.sysctl_clen - !r) e(0);
2160e4e21ee1SDavid van Moolenbroek
2161e4e21ee1SDavid van Moolenbroek /* Try to destroy a (static) node in a read-only directory node. */
2162e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
2163e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, SECRET_VALUE) != -1) e(0);
2164e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2165e4e21ee1SDavid van Moolenbroek
2166e4e21ee1SDavid van Moolenbroek /*
2167e4e21ee1SDavid van Moolenbroek * Errors during data copy-out of the destroyed node should not undo
2168e4e21ee1SDavid van Moolenbroek * its destruction.
2169e4e21ee1SDavid van Moolenbroek */
2170e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
2171e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
2172e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
2173e4e21ee1SDavid van Moolenbroek
2174e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
2175e4e21ee1SDavid van Moolenbroek i = 0;
2176e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
2177e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != 0) e(0);
2178e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(i)) e(0);
2179e4e21ee1SDavid van Moolenbroek if (i != 31415926) e(0);
2180e4e21ee1SDavid van Moolenbroek
2181e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESTROY;
2182e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn);
2183e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2184e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2185e4e21ee1SDavid van Moolenbroek
2186e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
2187e4e21ee1SDavid van Moolenbroek i = 0;
2188e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
2189e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != -1) e(0);
2190e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2191e4e21ee1SDavid van Moolenbroek if (oldlen != 0) e(0);
2192e4e21ee1SDavid van Moolenbroek if (i != 0) e(0);
2193e4e21ee1SDavid van Moolenbroek
2194e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
2195e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
2196e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
2197e4e21ee1SDavid van Moolenbroek
2198e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESTROY;
2199e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scn) - 1;
2200e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &scn, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2201e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
2202e4e21ee1SDavid van Moolenbroek
2203e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
2204e4e21ee1SDavid van Moolenbroek oldlen = sizeof(i);
2205e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &i, &oldlen, NULL, 0) != -1) e(0);
2206e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2207e4e21ee1SDavid van Moolenbroek
2208e4e21ee1SDavid van Moolenbroek /*
2209e4e21ee1SDavid van Moolenbroek * Now create and destroy a whole bunch of nodes in a subtree, mostly
2210e4e21ee1SDavid van Moolenbroek * test linked list manipulation, but also to ensure that a nonempty
2211e4e21ee1SDavid van Moolenbroek * tree node cannot be destroyed.
2212e4e21ee1SDavid van Moolenbroek */
2213e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2214e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_NODE;
2215e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &scn, TEST_DYNAMIC, "dynamic", -1, NULL) == -1)
2216e4e21ee1SDavid van Moolenbroek e(0);
2217e4e21ee1SDavid van Moolenbroek
2218e4e21ee1SDavid van Moolenbroek for (i = 0; i < 15; i++) {
2219e4e21ee1SDavid van Moolenbroek snprintf(buf, sizeof(buf), "node%d", i);
2220e4e21ee1SDavid van Moolenbroek if ((id[i] = create_node(mib, 3, &scn, -1, buf, -1,
2221e4e21ee1SDavid van Moolenbroek NULL)) == -1) e(i);
2222e4e21ee1SDavid van Moolenbroek
2223e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(i);
2224e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(i);
2225e4e21ee1SDavid van Moolenbroek }
2226e4e21ee1SDavid van Moolenbroek
2227e4e21ee1SDavid van Moolenbroek for (i = 0; i < 15; i += 2)
2228e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[i]) != 0) e(i);
2229e4e21ee1SDavid van Moolenbroek
2230e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(0);
2231e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(0);
2232e4e21ee1SDavid van Moolenbroek
2233e4e21ee1SDavid van Moolenbroek for (i = 0; i < 15; i += 2) {
2234e4e21ee1SDavid van Moolenbroek snprintf(buf, sizeof(buf), "node%d", i);
2235e4e21ee1SDavid van Moolenbroek if ((id[i] = create_node(mib, 3, &scn, -1, buf, -1,
2236e4e21ee1SDavid van Moolenbroek NULL)) == -1) e(i);
2237e4e21ee1SDavid van Moolenbroek }
2238e4e21ee1SDavid van Moolenbroek
2239e4e21ee1SDavid van Moolenbroek for (i = 0; i < 3; i++)
2240e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[i]) != 0) e(i);
2241e4e21ee1SDavid van Moolenbroek
2242e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(0);
2243e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(0);
2244e4e21ee1SDavid van Moolenbroek
2245e4e21ee1SDavid van Moolenbroek for (i = 12; i < 15; i++)
2246e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[i]) != 0) e(i);
2247e4e21ee1SDavid van Moolenbroek
2248e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(0);
2249e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(0);
2250e4e21ee1SDavid van Moolenbroek
2251e4e21ee1SDavid van Moolenbroek for (i = 6; i < 9; i++)
2252e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[i]) != 0) e(i);
2253e4e21ee1SDavid van Moolenbroek
2254e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(0);
2255e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(0);
2256e4e21ee1SDavid van Moolenbroek
2257e4e21ee1SDavid van Moolenbroek for (i = 3; i < 6; i++)
2258e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[i]) != 0) e(i);
2259e4e21ee1SDavid van Moolenbroek
2260e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != -1) e(0);
2261e4e21ee1SDavid van Moolenbroek if (errno != ENOTEMPTY) e(0);
2262e4e21ee1SDavid van Moolenbroek
2263e4e21ee1SDavid van Moolenbroek for (i = 9; i < 12; i++)
2264e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[i]) != 0) e(i);
2265e4e21ee1SDavid van Moolenbroek
2266e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2267e4e21ee1SDavid van Moolenbroek
2268e4e21ee1SDavid van Moolenbroek /* Finally, ensure that unprivileged users cannot destroy nodes. */
2269e4e21ee1SDavid van Moolenbroek (void)test_nonroot(sub87d);
2270e4e21ee1SDavid van Moolenbroek }
2271e4e21ee1SDavid van Moolenbroek
2272e4e21ee1SDavid van Moolenbroek /*
2273e4e21ee1SDavid van Moolenbroek * Get or a set the description for a particular node. Compare the results
2274e4e21ee1SDavid van Moolenbroek * with the given description. Return 0 on success, or -1 on failure with
2275e4e21ee1SDavid van Moolenbroek * errno set.
2276e4e21ee1SDavid van Moolenbroek */
2277e4e21ee1SDavid van Moolenbroek static int
describe_node(const int * path,unsigned int pathlen,int id,const char * desc,int set)2278e4e21ee1SDavid van Moolenbroek describe_node(const int * path, unsigned int pathlen, int id,
2279e4e21ee1SDavid van Moolenbroek const char * desc, int set)
2280e4e21ee1SDavid van Moolenbroek {
2281e4e21ee1SDavid van Moolenbroek char buf[256], *p;
2282e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
2283e4e21ee1SDavid van Moolenbroek struct sysctldesc *scd;
2284e4e21ee1SDavid van Moolenbroek size_t oldlen;
2285e4e21ee1SDavid van Moolenbroek int mib[CTL_MAXNAME];
2286e4e21ee1SDavid van Moolenbroek
2287e4e21ee1SDavid van Moolenbroek if (pathlen >= CTL_MAXNAME) e(0);
2288e4e21ee1SDavid van Moolenbroek memcpy(mib, path, sizeof(mib[0]) * pathlen);
2289e4e21ee1SDavid van Moolenbroek mib[pathlen] = CTL_DESCRIBE;
2290e4e21ee1SDavid van Moolenbroek
2291e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2292e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2293e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2294e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2295e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id;
2296e4e21ee1SDavid van Moolenbroek if (set)
2297e4e21ee1SDavid van Moolenbroek scn.sysctl_desc = desc;
2298e4e21ee1SDavid van Moolenbroek if (sysctl(mib, pathlen + 1, buf, &oldlen, &scn, sizeof(scn)) != 0)
2299e4e21ee1SDavid van Moolenbroek return -1;
2300e4e21ee1SDavid van Moolenbroek
2301e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2302e4e21ee1SDavid van Moolenbroek if (scd->descr_num != id) e(0);
2303e4e21ee1SDavid van Moolenbroek if (scd->descr_ver == 0) e(0);
2304e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2305e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scd->descr_str) + 1) e(0);
2306e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, desc)) e(0);
2307e4e21ee1SDavid van Moolenbroek if (oldlen != (size_t)((char *)NEXT_DESCR(scd) - buf)) e(0);
2308e4e21ee1SDavid van Moolenbroek for (p = scd->descr_str + scd->descr_len; p != &buf[oldlen]; p++)
2309e4e21ee1SDavid van Moolenbroek if (*p != '\0') e(0);
2310e4e21ee1SDavid van Moolenbroek return 0;
2311e4e21ee1SDavid van Moolenbroek }
2312e4e21ee1SDavid van Moolenbroek
2313e4e21ee1SDavid van Moolenbroek /*
2314e4e21ee1SDavid van Moolenbroek * Test getting descriptions from an unprivileged process.
2315e4e21ee1SDavid van Moolenbroek */
2316e4e21ee1SDavid van Moolenbroek static void
sub87e(void)2317e4e21ee1SDavid van Moolenbroek sub87e(void)
2318e4e21ee1SDavid van Moolenbroek {
2319e4e21ee1SDavid van Moolenbroek static char buf[2048];
2320e4e21ee1SDavid van Moolenbroek char seen[32], *p;
2321e4e21ee1SDavid van Moolenbroek struct sysctldesc *scd, *endscd;
2322e4e21ee1SDavid van Moolenbroek size_t oldlen;
2323e4e21ee1SDavid van Moolenbroek int mib[4];
2324e4e21ee1SDavid van Moolenbroek
2325e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2326e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2327e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2328e4e21ee1SDavid van Moolenbroek
2329e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2330e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2331e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
2332e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
2333e4e21ee1SDavid van Moolenbroek
2334e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2335e4e21ee1SDavid van Moolenbroek endscd = (struct sysctldesc *)&buf[oldlen];
2336e4e21ee1SDavid van Moolenbroek memset(seen, 0, sizeof(seen));
2337e4e21ee1SDavid van Moolenbroek
2338e4e21ee1SDavid van Moolenbroek while (scd < endscd) {
2339e4e21ee1SDavid van Moolenbroek if (scd->descr_num >= __arraycount(seen)) e(0);
2340e4e21ee1SDavid van Moolenbroek if (seen[scd->descr_num]++) e(0);
2341e4e21ee1SDavid van Moolenbroek
2342e4e21ee1SDavid van Moolenbroek if (scd->descr_ver == 0) e(0);
2343e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2344e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scd->descr_str) + 1) e(0);
2345e4e21ee1SDavid van Moolenbroek
2346e4e21ee1SDavid van Moolenbroek p = scd->descr_str + scd->descr_len;
2347e4e21ee1SDavid van Moolenbroek while (p != (char *)NEXT_DESCR(scd))
2348e4e21ee1SDavid van Moolenbroek if (*p++ != '\0') e(0);
2349e4e21ee1SDavid van Moolenbroek
2350e4e21ee1SDavid van Moolenbroek scd = NEXT_DESCR(scd);
2351e4e21ee1SDavid van Moolenbroek }
2352e4e21ee1SDavid van Moolenbroek if (scd != endscd) e(0);
2353e4e21ee1SDavid van Moolenbroek
2354e4e21ee1SDavid van Moolenbroek if (!seen[TEST_INT]) e(0);
2355e4e21ee1SDavid van Moolenbroek if (!seen[TEST_BOOL]) e(0);
2356e4e21ee1SDavid van Moolenbroek if (!seen[TEST_QUAD]) e(0);
2357e4e21ee1SDavid van Moolenbroek if (!seen[TEST_STRING]) e(0);
2358e4e21ee1SDavid van Moolenbroek if (!seen[TEST_STRUCT]) e(0);
2359e4e21ee1SDavid van Moolenbroek if (seen[TEST_PRIVATE]) e(0);
2360e4e21ee1SDavid van Moolenbroek if (!seen[TEST_ANYWRITE]) e(0);
2361e4e21ee1SDavid van Moolenbroek if (seen[TEST_SECRET]) e(0);
2362e4e21ee1SDavid van Moolenbroek if (!seen[TEST_PERM]) e(0);
2363e4e21ee1SDavid van Moolenbroek
2364e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_INT, "Value test field", 0) != 0) e(0);
2365e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_PRIVATE, "", 0) != -1) e(0);
2366e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2367e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_SECRET, "", 0) != -1) e(0);
2368e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2369e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_PERM, "", 0) != 0) e(0);
2370e4e21ee1SDavid van Moolenbroek
2371e4e21ee1SDavid van Moolenbroek mib[2] = TEST_SECRET;
2372e4e21ee1SDavid van Moolenbroek mib[3] = CTL_DESCRIBE;
2373e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 0) != -1) e(0);
2374e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2375e4e21ee1SDavid van Moolenbroek
2376e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 3, SECRET_VALUE, "", 0) != -1) e(0);
2377e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2378e4e21ee1SDavid van Moolenbroek }
2379e4e21ee1SDavid van Moolenbroek
2380e4e21ee1SDavid van Moolenbroek /*
2381e4e21ee1SDavid van Moolenbroek * Test sysctl(2) node descriptions, part 1: getting descriptions.
2382e4e21ee1SDavid van Moolenbroek */
2383e4e21ee1SDavid van Moolenbroek static void
test87e(void)2384e4e21ee1SDavid van Moolenbroek test87e(void)
2385e4e21ee1SDavid van Moolenbroek {
2386e4e21ee1SDavid van Moolenbroek static char buf[2048];
2387e4e21ee1SDavid van Moolenbroek char seen[32], *p;
2388e4e21ee1SDavid van Moolenbroek struct sysctldesc *scd, *endscd;
2389e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
2390e4e21ee1SDavid van Moolenbroek size_t oldlen, len, sublen;
2391e4e21ee1SDavid van Moolenbroek int mib[4];
2392e4e21ee1SDavid van Moolenbroek
2393e4e21ee1SDavid van Moolenbroek subtest = 4;
2394e4e21ee1SDavid van Moolenbroek
2395e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2396e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2397e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2398e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2399e4e21ee1SDavid van Moolenbroek
2400e4e21ee1SDavid van Moolenbroek /* Start with tests for getting a description listing. */
2401e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, NULL, 0) != 0) e(0);
2402e4e21ee1SDavid van Moolenbroek
2403e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
2404e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
2405e4e21ee1SDavid van Moolenbroek len = oldlen;
2406e4e21ee1SDavid van Moolenbroek
2407e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2408e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
2409e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
2410e4e21ee1SDavid van Moolenbroek
2411e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2412e4e21ee1SDavid van Moolenbroek endscd = (struct sysctldesc *)&buf[len];
2413e4e21ee1SDavid van Moolenbroek memset(seen, 0, sizeof(seen));
2414e4e21ee1SDavid van Moolenbroek
2415e4e21ee1SDavid van Moolenbroek sublen = (size_t)((char *)NEXT_DESCR(scd) - buf);
2416e4e21ee1SDavid van Moolenbroek
2417e4e21ee1SDavid van Moolenbroek while (scd < endscd) {
2418e4e21ee1SDavid van Moolenbroek if (scd->descr_num >= __arraycount(seen)) e(0);
2419e4e21ee1SDavid van Moolenbroek if (seen[scd->descr_num]++) e(0);
2420e4e21ee1SDavid van Moolenbroek
2421e4e21ee1SDavid van Moolenbroek if (scd->descr_ver == 0) e(0);
2422e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2423e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scd->descr_str) + 1) e(0);
2424e4e21ee1SDavid van Moolenbroek
2425e4e21ee1SDavid van Moolenbroek /*
2426e4e21ee1SDavid van Moolenbroek * This is not supposed to be complete. We test different
2427e4e21ee1SDavid van Moolenbroek * string lengths, private fields, and empty descriptions.
2428e4e21ee1SDavid van Moolenbroek */
2429e4e21ee1SDavid van Moolenbroek switch (scd->descr_num) {
2430e4e21ee1SDavid van Moolenbroek case TEST_INT:
2431e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Value test field")) e(0);
2432e4e21ee1SDavid van Moolenbroek break;
2433e4e21ee1SDavid van Moolenbroek case TEST_BOOL:
2434e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Boolean test field")) e(0);
2435e4e21ee1SDavid van Moolenbroek break;
2436e4e21ee1SDavid van Moolenbroek case TEST_QUAD:
2437e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Quad test field")) e(0);
2438e4e21ee1SDavid van Moolenbroek break;
2439e4e21ee1SDavid van Moolenbroek case TEST_STRING:
2440e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "String test field")) e(0);
2441e4e21ee1SDavid van Moolenbroek break;
2442e4e21ee1SDavid van Moolenbroek case TEST_PRIVATE:
2443e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Private test field")) e(0);
2444e4e21ee1SDavid van Moolenbroek break;
2445e4e21ee1SDavid van Moolenbroek case TEST_SECRET:
2446e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Private subtree")) e(0);
2447e4e21ee1SDavid van Moolenbroek break;
2448e4e21ee1SDavid van Moolenbroek case TEST_PERM:
2449e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "")) e(0);
2450e4e21ee1SDavid van Moolenbroek break;
2451e4e21ee1SDavid van Moolenbroek }
2452e4e21ee1SDavid van Moolenbroek
2453e4e21ee1SDavid van Moolenbroek /*
2454e4e21ee1SDavid van Moolenbroek * If there are padding bytes, they must be zero, whether it is
2455e4e21ee1SDavid van Moolenbroek * because we set them or the MIB service copied out zeroes.
2456e4e21ee1SDavid van Moolenbroek */
2457e4e21ee1SDavid van Moolenbroek p = scd->descr_str + scd->descr_len;
2458e4e21ee1SDavid van Moolenbroek while (p != (char *)NEXT_DESCR(scd))
2459e4e21ee1SDavid van Moolenbroek if (*p++ != '\0') e(0);
2460e4e21ee1SDavid van Moolenbroek
2461e4e21ee1SDavid van Moolenbroek scd = NEXT_DESCR(scd);
2462e4e21ee1SDavid van Moolenbroek }
2463e4e21ee1SDavid van Moolenbroek if (scd != endscd) e(0);
2464e4e21ee1SDavid van Moolenbroek
2465e4e21ee1SDavid van Moolenbroek if (!seen[TEST_INT]) e(0);
2466e4e21ee1SDavid van Moolenbroek if (!seen[TEST_BOOL]) e(0);
2467e4e21ee1SDavid van Moolenbroek if (!seen[TEST_QUAD]) e(0);
2468e4e21ee1SDavid van Moolenbroek if (!seen[TEST_STRING]) e(0);
2469e4e21ee1SDavid van Moolenbroek if (!seen[TEST_STRUCT]) e(0);
2470e4e21ee1SDavid van Moolenbroek if (!seen[TEST_PRIVATE]) e(0);
2471e4e21ee1SDavid van Moolenbroek if (!seen[TEST_ANYWRITE]) e(0);
2472e4e21ee1SDavid van Moolenbroek if (!seen[TEST_SECRET]) e(0);
2473e4e21ee1SDavid van Moolenbroek if (!seen[TEST_PERM]) e(0);
2474e4e21ee1SDavid van Moolenbroek
2475e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2476e4e21ee1SDavid van Moolenbroek oldlen = sublen;
2477e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != -1) e(0);
2478e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
2479e4e21ee1SDavid van Moolenbroek
2480e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2481e4e21ee1SDavid van Moolenbroek if (scd->descr_num != TEST_INT) e(0);
2482e4e21ee1SDavid van Moolenbroek if (scd->descr_ver == 0) e(0);
2483e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2484e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scd->descr_str) + 1) e(0);
2485e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Value test field")) e(0);
2486e4e21ee1SDavid van Moolenbroek
2487e4e21ee1SDavid van Moolenbroek /* Next up, tests for getting a particular node's description. */
2488e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2489e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2490e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, NULL, 0) != -1) e(0);
2491e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2492e4e21ee1SDavid van Moolenbroek
2493e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, bad_ptr, sizeof(scn) - 1) != -1) e(0);
2494e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2495e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, bad_ptr, sizeof(scn) + 1) != -1) e(0);
2496e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2497e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, bad_ptr, sizeof(scn)) != -1) e(0);
2498e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2499e4e21ee1SDavid van Moolenbroek
2500e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2501e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERS_0;
2502e4e21ee1SDavid van Moolenbroek scn.sysctl_num = INT_MAX;
2503e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2504e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2505e4e21ee1SDavid van Moolenbroek
2506e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2507e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2508e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2509e4e21ee1SDavid van Moolenbroek
2510e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_BOOL;
2511e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
2512e4e21ee1SDavid van Moolenbroek
2513e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2514e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_INT;
2515e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2516e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2517e4e21ee1SDavid van Moolenbroek
2518e4e21ee1SDavid van Moolenbroek oldlen = sublen - 1;
2519e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_INT;
2520e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2521e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
2522e4e21ee1SDavid van Moolenbroek if (oldlen != sublen) e(0);
2523e4e21ee1SDavid van Moolenbroek
2524e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_INT, "Value test field", 0) != 0) e(0);
2525e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_QUAD, "Quad test field", 0) != 0) e(0);
2526e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_PRIVATE, "Private test field",
2527e4e21ee1SDavid van Moolenbroek 0) != 0) e(0);
2528e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_SECRET, "Private subtree",
2529e4e21ee1SDavid van Moolenbroek 0) != 0) e(0);
2530e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_PERM, "", 0) != 0) e(0);
2531e4e21ee1SDavid van Moolenbroek
2532e4e21ee1SDavid van Moolenbroek /*
2533e4e21ee1SDavid van Moolenbroek * Make sure that unprivileged users cannot access privileged nodes'
2534e4e21ee1SDavid van Moolenbroek * descriptions. It doesn't sound too bad to me if they could, but
2535e4e21ee1SDavid van Moolenbroek * these are apparently the rules..
2536e4e21ee1SDavid van Moolenbroek */
2537e4e21ee1SDavid van Moolenbroek (void)test_nonroot(sub87e);
2538e4e21ee1SDavid van Moolenbroek
2539e4e21ee1SDavid van Moolenbroek /* Do some more path-related error code tests unrelated to the rest. */
2540e4e21ee1SDavid van Moolenbroek mib[1] = INT_MAX;
2541e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "", 0) != -1) e(0);
2542e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2543e4e21ee1SDavid van Moolenbroek
2544e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2545e4e21ee1SDavid van Moolenbroek mib[2] = TEST_INT;
2546e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 3, TEST_DYNAMIC, "", 0) != -1) e(0);
2547e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
2548e4e21ee1SDavid van Moolenbroek
2549e4e21ee1SDavid van Moolenbroek mib[2] = TEST_BOOL;
2550e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 3, TEST_DYNAMIC, "", 0) != -1) e(0);
2551e4e21ee1SDavid van Moolenbroek if (errno != ENOTDIR) e(0);
2552e4e21ee1SDavid van Moolenbroek
2553e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2554e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 3, TEST_DYNAMIC, "", 0) != -1) e(0);
2555e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2556e4e21ee1SDavid van Moolenbroek }
2557e4e21ee1SDavid van Moolenbroek
2558e4e21ee1SDavid van Moolenbroek /*
2559e4e21ee1SDavid van Moolenbroek * Test setting descriptions from an unprivileged process.
2560e4e21ee1SDavid van Moolenbroek */
2561e4e21ee1SDavid van Moolenbroek static void
sub87f(void)2562e4e21ee1SDavid van Moolenbroek sub87f(void)
2563e4e21ee1SDavid van Moolenbroek {
2564e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
2565e4e21ee1SDavid van Moolenbroek int mib[3];
2566e4e21ee1SDavid van Moolenbroek
2567e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2568e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2569e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2570e4e21ee1SDavid van Moolenbroek
2571e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2572e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2573e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2574e4e21ee1SDavid van Moolenbroek scn.sysctl_desc = "Description.";
2575e4e21ee1SDavid van Moolenbroek
2576e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2577e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2578e4e21ee1SDavid van Moolenbroek }
2579e4e21ee1SDavid van Moolenbroek
2580e4e21ee1SDavid van Moolenbroek /*
2581e4e21ee1SDavid van Moolenbroek * Test sysctl(2) node descriptions, part 2: setting descriptions.
2582e4e21ee1SDavid van Moolenbroek */
2583e4e21ee1SDavid van Moolenbroek static void
test87f(void)2584e4e21ee1SDavid van Moolenbroek test87f(void)
2585e4e21ee1SDavid van Moolenbroek {
2586e4e21ee1SDavid van Moolenbroek static char buf[2048];
2587e4e21ee1SDavid van Moolenbroek char seen, *p;
2588e4e21ee1SDavid van Moolenbroek struct sysctlnode scn, tmpscn, scnset[3];
2589e4e21ee1SDavid van Moolenbroek struct sysctldesc *scd, *endscd, *scdset[2];
2590e4e21ee1SDavid van Moolenbroek size_t oldlen, len;
2591e4e21ee1SDavid van Moolenbroek int i, r, mib[4], id[2];
2592e4e21ee1SDavid van Moolenbroek
2593e4e21ee1SDavid van Moolenbroek subtest = 5;
2594e4e21ee1SDavid van Moolenbroek
2595e4e21ee1SDavid van Moolenbroek /*
2596e4e21ee1SDavid van Moolenbroek * All tests that experiment with dynamic nodes must start with trying
2597e4e21ee1SDavid van Moolenbroek * to destroy the TEST_DYNAMIC node first, as tests may be run
2598e4e21ee1SDavid van Moolenbroek * individually, and this node exists as a static node after booting.
2599e4e21ee1SDavid van Moolenbroek */
2600e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2601e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2602e4e21ee1SDavid van Moolenbroek (void)destroy_node(mib, 2, TEST_DYNAMIC);
2603e4e21ee1SDavid van Moolenbroek
2604e4e21ee1SDavid van Moolenbroek /*
2605e4e21ee1SDavid van Moolenbroek * First try setting and retrieving the description of a dynamic node
2606e4e21ee1SDavid van Moolenbroek * in a directory full of static nodes.
2607e4e21ee1SDavid van Moolenbroek */
2608e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
2609e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2610e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_IMMEDIATE |
2611e4e21ee1SDavid van Moolenbroek CTLFLAG_READONLY | CTLTYPE_INT;
2612e4e21ee1SDavid van Moolenbroek scn.sysctl_size = sizeof(int);
2613e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2614e4e21ee1SDavid van Moolenbroek scn.sysctl_idata = 27182818;
2615e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
2616e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
2617e4e21ee1SDavid van Moolenbroek
2618e4e21ee1SDavid van Moolenbroek memcpy(&tmpscn, &scn, sizeof(tmpscn));
2619e4e21ee1SDavid van Moolenbroek
2620e4e21ee1SDavid van Moolenbroek /* We should get an empty description for the node in a listing. */
2621e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2622e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2623e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2624e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
2625e4e21ee1SDavid van Moolenbroek
2626e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2627e4e21ee1SDavid van Moolenbroek endscd = (struct sysctldesc *)&buf[oldlen];
2628e4e21ee1SDavid van Moolenbroek seen = 0;
2629e4e21ee1SDavid van Moolenbroek
2630e4e21ee1SDavid van Moolenbroek while (scd < endscd) {
2631e4e21ee1SDavid van Moolenbroek if (scd->descr_num == TEST_DYNAMIC) {
2632e4e21ee1SDavid van Moolenbroek if (seen++) e(0);
2633e4e21ee1SDavid van Moolenbroek
2634e4e21ee1SDavid van Moolenbroek if (scd->descr_len != 1) e(0);
2635e4e21ee1SDavid van Moolenbroek if (scd->descr_str[0] != '\0') e(0);
2636e4e21ee1SDavid van Moolenbroek }
2637e4e21ee1SDavid van Moolenbroek
2638e4e21ee1SDavid van Moolenbroek if (scd->descr_ver == 0) e(0);
2639e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2640e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scd->descr_str) + 1) e(0);
2641e4e21ee1SDavid van Moolenbroek
2642e4e21ee1SDavid van Moolenbroek p = scd->descr_str + scd->descr_len;
2643e4e21ee1SDavid van Moolenbroek while (p != (char *)NEXT_DESCR(scd))
2644e4e21ee1SDavid van Moolenbroek if (*p++ != '\0') e(0);
2645e4e21ee1SDavid van Moolenbroek
2646e4e21ee1SDavid van Moolenbroek scd = NEXT_DESCR(scd);
2647e4e21ee1SDavid van Moolenbroek }
2648e4e21ee1SDavid van Moolenbroek if (scd != endscd) e(0);
2649e4e21ee1SDavid van Moolenbroek
2650e4e21ee1SDavid van Moolenbroek if (!seen) e(0);
2651e4e21ee1SDavid van Moolenbroek
2652e4e21ee1SDavid van Moolenbroek /* We should get an empty description quering the node directly. */
2653e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "", 0) != 0) e(0);
2654e4e21ee1SDavid van Moolenbroek
2655e4e21ee1SDavid van Moolenbroek /* Attempt to set a description with a bad description pointer. */
2656e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, bad_ptr, 1) != -1) e(0);
2657e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2658e4e21ee1SDavid van Moolenbroek
2659e4e21ee1SDavid van Moolenbroek /* Attempt to set a description that is longer than allowed. */
2660e4e21ee1SDavid van Moolenbroek memset(buf, 'A', sizeof(buf) - 1);
2661e4e21ee1SDavid van Moolenbroek buf[sizeof(buf) - 1] = '\0';
2662e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, buf, 1) != -1) e(0);
2663e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2664e4e21ee1SDavid van Moolenbroek
2665e4e21ee1SDavid van Moolenbroek /* Now actually set a description. */
2666e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "Dynamic node", 1) != 0) e(0);
2667e4e21ee1SDavid van Moolenbroek len = strlen("Dynamic node") + 1;
2668e4e21ee1SDavid van Moolenbroek
2669e4e21ee1SDavid van Moolenbroek /* We should get the new description for the node in a listing. */
2670e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2671e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2672e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, NULL, 0) != 0) e(0);
2673e4e21ee1SDavid van Moolenbroek
2674e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2675e4e21ee1SDavid van Moolenbroek endscd = (struct sysctldesc *)&buf[oldlen];
2676e4e21ee1SDavid van Moolenbroek seen = 0;
2677e4e21ee1SDavid van Moolenbroek
2678e4e21ee1SDavid van Moolenbroek while (scd < endscd) {
2679e4e21ee1SDavid van Moolenbroek if (scd->descr_num == TEST_DYNAMIC) {
2680e4e21ee1SDavid van Moolenbroek if (seen++) e(0);
2681e4e21ee1SDavid van Moolenbroek
2682e4e21ee1SDavid van Moolenbroek if (scd->descr_len != len) e(0);
2683e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, "Dynamic node")) e(0);
2684e4e21ee1SDavid van Moolenbroek }
2685e4e21ee1SDavid van Moolenbroek
2686e4e21ee1SDavid van Moolenbroek if (scd->descr_ver == 0) e(0);
2687e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2688e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scd->descr_str) + 1) e(0);
2689e4e21ee1SDavid van Moolenbroek
2690e4e21ee1SDavid van Moolenbroek p = scd->descr_str + scd->descr_len;
2691e4e21ee1SDavid van Moolenbroek while (p != (char *)NEXT_DESCR(scd))
2692e4e21ee1SDavid van Moolenbroek if (*p++ != '\0') e(0);
2693e4e21ee1SDavid van Moolenbroek
2694e4e21ee1SDavid van Moolenbroek scd = NEXT_DESCR(scd);
2695e4e21ee1SDavid van Moolenbroek }
2696e4e21ee1SDavid van Moolenbroek if (scd != endscd) e(0);
2697e4e21ee1SDavid van Moolenbroek
2698e4e21ee1SDavid van Moolenbroek if (!seen) e(0);
2699e4e21ee1SDavid van Moolenbroek
2700e4e21ee1SDavid van Moolenbroek /* We should get the new description quering the node directly. */
2701e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "Dynamic node", 0) != 0) e(0);
2702e4e21ee1SDavid van Moolenbroek
2703e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2704e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2705e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERS_0;
2706e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_INT;
2707e4e21ee1SDavid van Moolenbroek scn.sysctl_desc = "Test description";
2708e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2709e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
2710e4e21ee1SDavid van Moolenbroek
2711e4e21ee1SDavid van Moolenbroek /* It is not possible to replace an existing static description. */
2712e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2713e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2714e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2715e4e21ee1SDavid van Moolenbroek
2716e4e21ee1SDavid van Moolenbroek /* Nonexistent nodes cannot be given a description. */
2717e4e21ee1SDavid van Moolenbroek scn.sysctl_num = INT_MAX;
2718e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2719e4e21ee1SDavid van Moolenbroek if (errno != ENOENT) e(0);
2720e4e21ee1SDavid van Moolenbroek
2721e4e21ee1SDavid van Moolenbroek /* It is not possible to replace an existing dynamic description. */
2722e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2723e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2724e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2725e4e21ee1SDavid van Moolenbroek
2726e4e21ee1SDavid van Moolenbroek /* It is not possible to set a description on a permanent node. */
2727e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_PERM;
2728e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
2729e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
2730e4e21ee1SDavid van Moolenbroek
2731e4e21ee1SDavid van Moolenbroek /* Verify that TEST_DYNAMIC now has CTLFLAG_OWNDESC set. */
2732e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &scn) != 0) e(0);
2733e4e21ee1SDavid van Moolenbroek if (!(scn.sysctl_flags & CTLFLAG_OWNDESC)) e(0);
2734e4e21ee1SDavid van Moolenbroek
2735e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2736e4e21ee1SDavid van Moolenbroek
2737e4e21ee1SDavid van Moolenbroek /*
2738e4e21ee1SDavid van Moolenbroek * Set a description on a static node, ensure that CTLFLAG_OWNDESC is
2739e4e21ee1SDavid van Moolenbroek * set, and then destroy the static node. This should still free the
2740e4e21ee1SDavid van Moolenbroek * memory allocated for the description. We cannot test whether the
2741e4e21ee1SDavid van Moolenbroek * memory is really freed, but at least we can trigger this case at
2742e4e21ee1SDavid van Moolenbroek * all, and leave the rest up to memory checkers or whatever. Since we
2743e4e21ee1SDavid van Moolenbroek * destroy the static node, we can not do this more than once, and thus
2744e4e21ee1SDavid van Moolenbroek * we skip this test if the static node does not exist.
2745e4e21ee1SDavid van Moolenbroek */
2746e4e21ee1SDavid van Moolenbroek r = describe_node(mib, 2, TEST_DESTROY1, "Destroy me", 1);
2747e4e21ee1SDavid van Moolenbroek
2748e4e21ee1SDavid van Moolenbroek if (r == -1 && errno != ENOENT) e(0);
2749e4e21ee1SDavid van Moolenbroek else if (r == 0) {
2750e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DESTROY1, &scn) != 0) e(0);
2751e4e21ee1SDavid van Moolenbroek if (!(scn.sysctl_flags & CTLFLAG_OWNDESC)) e(0);
2752e4e21ee1SDavid van Moolenbroek
2753e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DESTROY1, "Destroy me", 0) != 0)
2754e4e21ee1SDavid van Moolenbroek e(0);
2755e4e21ee1SDavid van Moolenbroek
2756e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DESTROY1) != 0) e(0);
2757e4e21ee1SDavid van Moolenbroek }
2758e4e21ee1SDavid van Moolenbroek
2759e4e21ee1SDavid van Moolenbroek /*
2760e4e21ee1SDavid van Moolenbroek * Test queries and description listings in subtrees.
2761e4e21ee1SDavid van Moolenbroek */
2762e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
2763e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2764e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_NODE;
2765e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2766e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
2767e4e21ee1SDavid van Moolenbroek scn.sysctl_desc = "This will not be set.";
2768e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
2769e4e21ee1SDavid van Moolenbroek
2770e4e21ee1SDavid van Moolenbroek /* Setting sysctl_desc should have no effect during creation. */
2771e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "", 0) != 0) e(0);
2772e4e21ee1SDavid van Moolenbroek
2773e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
2774e4e21ee1SDavid van Moolenbroek id[0] = create_node(mib, 3, &tmpscn, CTL_CREATE, "NodeA", -1, NULL);
2775e4e21ee1SDavid van Moolenbroek if (id[0] < 0) e(0);
2776e4e21ee1SDavid van Moolenbroek id[1] = create_node(mib, 3, &tmpscn, CTL_CREATE, "NodeB", -1, NULL);
2777e4e21ee1SDavid van Moolenbroek if (id[1] < 0) e(0);
2778e4e21ee1SDavid van Moolenbroek if (id[0] == id[1]) e(0);
2779e4e21ee1SDavid van Moolenbroek
2780e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
2781e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scnset);
2782e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, scnset, &oldlen, NULL, 0) != 0) e(0);
2783e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(scnset[0]) * 2) e(0);
2784e4e21ee1SDavid van Moolenbroek i = (scnset[0].sysctl_num != id[0]);
2785e4e21ee1SDavid van Moolenbroek if (scnset[i].sysctl_num != id[0]) e(0);
2786e4e21ee1SDavid van Moolenbroek if (scnset[1 - i].sysctl_num != id[1]) e(0);
2787e4e21ee1SDavid van Moolenbroek if (scnset[i].sysctl_flags & CTLFLAG_OWNDESC) e(0);
2788e4e21ee1SDavid van Moolenbroek if (scnset[1 - i].sysctl_flags & CTLFLAG_OWNDESC) e(0);
2789e4e21ee1SDavid van Moolenbroek
2790e4e21ee1SDavid van Moolenbroek mib[3] = CTL_DESCRIBE;
2791e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2792e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2793e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, buf, &oldlen, NULL, 0) != 0) e(0);
2794e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
2795e4e21ee1SDavid van Moolenbroek
2796e4e21ee1SDavid van Moolenbroek scdset[0] = (struct sysctldesc *)buf;
2797e4e21ee1SDavid van Moolenbroek scdset[1] = NEXT_DESCR(scdset[0]);
2798e4e21ee1SDavid van Moolenbroek if ((char *)NEXT_DESCR(scdset[1]) != &buf[oldlen]) e(0);
2799e4e21ee1SDavid van Moolenbroek i = (scdset[0]->descr_num != id[0]);
2800e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_num != id[0]) e(0);
2801e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_ver == 0) e(0);
2802e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_len != 1) e(0);
2803e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_str[0] != '\0') e(0);
2804e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_num != id[1]) e(0);
2805e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_ver == 0) e(0);
2806e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_len != 1) e(0);
2807e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_str[0] != '\0') e(0);
2808e4e21ee1SDavid van Moolenbroek
2809e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 3, id[0], "Description A", 1) != 0) e(0);
2810e4e21ee1SDavid van Moolenbroek
2811e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
2812e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scnset);
2813e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, scnset, &oldlen, NULL, 0) != 0) e(0);
2814e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(scnset[0]) * 2) e(0);
2815e4e21ee1SDavid van Moolenbroek i = (scnset[0].sysctl_num != id[0]);
2816e4e21ee1SDavid van Moolenbroek if (scnset[i].sysctl_num != id[0]) e(0);
2817e4e21ee1SDavid van Moolenbroek if (scnset[1 - i].sysctl_num != id[1]) e(0);
2818e4e21ee1SDavid van Moolenbroek if (!(scnset[i].sysctl_flags & CTLFLAG_OWNDESC)) e(0);
2819e4e21ee1SDavid van Moolenbroek if (scnset[1 - i].sysctl_flags & CTLFLAG_OWNDESC) e(0);
2820e4e21ee1SDavid van Moolenbroek
2821e4e21ee1SDavid van Moolenbroek mib[3] = CTL_DESCRIBE;
2822e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2823e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2824e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, buf, &oldlen, NULL, 0) != 0) e(0);
2825e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
2826e4e21ee1SDavid van Moolenbroek
2827e4e21ee1SDavid van Moolenbroek scdset[0] = (struct sysctldesc *)buf;
2828e4e21ee1SDavid van Moolenbroek scdset[1] = NEXT_DESCR(scdset[0]);
2829e4e21ee1SDavid van Moolenbroek if ((char *)NEXT_DESCR(scdset[1]) != &buf[oldlen]) e(0);
2830e4e21ee1SDavid van Moolenbroek i = (scdset[0]->descr_num != id[0]);
2831e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_num != id[0]) e(0);
2832e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_ver == 0) e(0);
2833e4e21ee1SDavid van Moolenbroek if (strcmp(scdset[i]->descr_str, "Description A")) e(0);
2834e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_len != strlen(scdset[i]->descr_str) + 1) e(0);
2835e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_num != id[1]) e(0);
2836e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_ver == 0) e(0);
2837e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_len != 1) e(0);
2838e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_str[0] != '\0') e(0);
2839e4e21ee1SDavid van Moolenbroek
2840e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 3, id[1], "Description B", 1) != 0) e(0);
2841e4e21ee1SDavid van Moolenbroek
2842e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
2843e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scnset);
2844e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, scnset, &oldlen, NULL, 0) != 0) e(0);
2845e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(scnset[0]) * 2) e(0);
2846e4e21ee1SDavid van Moolenbroek i = (scnset[0].sysctl_num != id[0]);
2847e4e21ee1SDavid van Moolenbroek if (scnset[i].sysctl_num != id[0]) e(0);
2848e4e21ee1SDavid van Moolenbroek if (scnset[1 - i].sysctl_num != id[1]) e(0);
2849e4e21ee1SDavid van Moolenbroek if (!(scnset[i].sysctl_flags & CTLFLAG_OWNDESC)) e(0);
2850e4e21ee1SDavid van Moolenbroek if (!(scnset[1 - i].sysctl_flags & CTLFLAG_OWNDESC)) e(0);
2851e4e21ee1SDavid van Moolenbroek
2852e4e21ee1SDavid van Moolenbroek mib[3] = CTL_DESCRIBE;
2853e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2854e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2855e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, buf, &oldlen, NULL, 0) != 0) e(0);
2856e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
2857e4e21ee1SDavid van Moolenbroek
2858e4e21ee1SDavid van Moolenbroek scdset[0] = (struct sysctldesc *)buf;
2859e4e21ee1SDavid van Moolenbroek scdset[1] = NEXT_DESCR(scdset[0]);
2860e4e21ee1SDavid van Moolenbroek if ((char *)NEXT_DESCR(scdset[1]) != &buf[oldlen]) e(0);
2861e4e21ee1SDavid van Moolenbroek i = (scdset[0]->descr_num != id[0]);
2862e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_num != id[0]) e(0);
2863e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_ver == 0) e(0);
2864e4e21ee1SDavid van Moolenbroek if (strcmp(scdset[i]->descr_str, "Description A")) e(0);
2865e4e21ee1SDavid van Moolenbroek if (scdset[i]->descr_len != strlen(scdset[i]->descr_str) + 1) e(0);
2866e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_num != id[1]) e(0);
2867e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_ver == 0) e(0);
2868e4e21ee1SDavid van Moolenbroek if (strcmp(scdset[1 - i]->descr_str, "Description B")) e(0);
2869e4e21ee1SDavid van Moolenbroek if (scdset[1 - i]->descr_len != strlen(scdset[1 - i]->descr_str) + 1)
2870e4e21ee1SDavid van Moolenbroek e(0);
2871e4e21ee1SDavid van Moolenbroek
2872e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[0]) != 0) e(0);
2873e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 3, id[1]) != 0) e(0);
2874e4e21ee1SDavid van Moolenbroek
2875e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2876e4e21ee1SDavid van Moolenbroek
2877e4e21ee1SDavid van Moolenbroek /*
2878e4e21ee1SDavid van Moolenbroek * Test that the resulting description is copied out after setting it,
2879e4e21ee1SDavid van Moolenbroek * and that copy failures do not undo the description getting set.
2880e4e21ee1SDavid van Moolenbroek */
2881e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_DYNAMIC, "dynamic", -1,
2882e4e21ee1SDavid van Moolenbroek NULL) == -1) e(0);
2883e4e21ee1SDavid van Moolenbroek
2884e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
2885e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
2886e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
2887e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
2888e4e21ee1SDavid van Moolenbroek scn.sysctl_desc = "Testing..";
2889e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2890e4e21ee1SDavid van Moolenbroek oldlen = sizeof(buf);
2891e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, &scn, sizeof(scn)) != 0) e(0);
2892e4e21ee1SDavid van Moolenbroek if (oldlen == 0) e(0);
2893e4e21ee1SDavid van Moolenbroek len = oldlen;
2894e4e21ee1SDavid van Moolenbroek
2895e4e21ee1SDavid van Moolenbroek scd = (struct sysctldesc *)buf;
2896e4e21ee1SDavid van Moolenbroek if (scd->descr_str[scd->descr_len - 1] != '\0') e(0);
2897e4e21ee1SDavid van Moolenbroek if (scd->descr_len != strlen(scn.sysctl_desc) + 1) e(0);
2898e4e21ee1SDavid van Moolenbroek if (strcmp(scd->descr_str, scn.sysctl_desc)) e(0);
2899e4e21ee1SDavid van Moolenbroek if (oldlen != (size_t)((char *)NEXT_DESCR(scd) - buf)) e(0);
2900e4e21ee1SDavid van Moolenbroek p = scd->descr_str + scd->descr_len;
2901e4e21ee1SDavid van Moolenbroek while (p != (char *)NEXT_DESCR(scd))
2902e4e21ee1SDavid van Moolenbroek if (*p++ != '\0') e(0);
2903e4e21ee1SDavid van Moolenbroek
2904e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "Testing..", 0) != 0) e(0);
2905e4e21ee1SDavid van Moolenbroek
2906e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2907e4e21ee1SDavid van Moolenbroek
2908e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_DYNAMIC, "dynamic", -1,
2909e4e21ee1SDavid van Moolenbroek NULL) == -1) e(0);
2910e4e21ee1SDavid van Moolenbroek
2911e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2912e4e21ee1SDavid van Moolenbroek oldlen = len - 1;
2913e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, buf, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2914e4e21ee1SDavid van Moolenbroek if (errno != ENOMEM) e(0);
2915e4e21ee1SDavid van Moolenbroek if (oldlen != len) e(0);
2916e4e21ee1SDavid van Moolenbroek
2917e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "Testing..", 0) != 0) e(0);
2918e4e21ee1SDavid van Moolenbroek
2919e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2920e4e21ee1SDavid van Moolenbroek
2921e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &tmpscn, TEST_DYNAMIC, "dynamic", -1,
2922e4e21ee1SDavid van Moolenbroek NULL) == -1) e(0);
2923e4e21ee1SDavid van Moolenbroek
2924e4e21ee1SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
2925e4e21ee1SDavid van Moolenbroek oldlen = len;
2926e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, bad_ptr, &oldlen, &scn, sizeof(scn)) != -1) e(0);
2927e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
2928e4e21ee1SDavid van Moolenbroek
2929e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, TEST_DYNAMIC, "Testing..", 0) != 0) e(0);
2930e4e21ee1SDavid van Moolenbroek
2931e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2932e4e21ee1SDavid van Moolenbroek
2933e4e21ee1SDavid van Moolenbroek /* Finally, ensure that unprivileged users cannot set descriptions. */
2934e4e21ee1SDavid van Moolenbroek memcpy(&scn, &tmpscn, sizeof(scn));
2935e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_IMMEDIATE |
2936e4e21ee1SDavid van Moolenbroek CTLFLAG_READWRITE | CTLFLAG_ANYWRITE | CTLTYPE_INT;
2937e4e21ee1SDavid van Moolenbroek if (create_node(mib, 2, &scn, TEST_DYNAMIC, "dynamic", -1,
2938e4e21ee1SDavid van Moolenbroek NULL) == -1) e(0);
2939e4e21ee1SDavid van Moolenbroek
2940e4e21ee1SDavid van Moolenbroek (void)test_nonroot(sub87f);
2941e4e21ee1SDavid van Moolenbroek
2942e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
2943e4e21ee1SDavid van Moolenbroek }
2944e4e21ee1SDavid van Moolenbroek
2945e4e21ee1SDavid van Moolenbroek /*
2946e4e21ee1SDavid van Moolenbroek * Set or test buffer contents. When setting, the buffer is filled with a
2947e4e21ee1SDavid van Moolenbroek * sequence of bytes that is a) free of null characters and b) likely to cause
2948e4e21ee1SDavid van Moolenbroek * detection of wrongly copied subsequences. When testing, for any size up to
2949e4e21ee1SDavid van Moolenbroek * the size used to set the buffer contents, 0 is returned if the buffer
2950e4e21ee1SDavid van Moolenbroek * contents match expectations, or -1 if they do not.
2951e4e21ee1SDavid van Moolenbroek */
2952e4e21ee1SDavid van Moolenbroek static int
test_buf(char * buf,unsigned char c,size_t size,int set)2953*3083d603SDavid van Moolenbroek test_buf(char * buf, unsigned char c, size_t size, int set)
2954e4e21ee1SDavid van Moolenbroek {
2955*3083d603SDavid van Moolenbroek unsigned char *ptr;
2956e4e21ee1SDavid van Moolenbroek int step;
2957e4e21ee1SDavid van Moolenbroek
2958*3083d603SDavid van Moolenbroek ptr = (unsigned char *)buf;
2959*3083d603SDavid van Moolenbroek
2960e4e21ee1SDavid van Moolenbroek for (step = 1; size > 0; size--) {
2961e4e21ee1SDavid van Moolenbroek if (set)
2962*3083d603SDavid van Moolenbroek *ptr++ = c;
2963*3083d603SDavid van Moolenbroek else if (*ptr++ != c)
2964e4e21ee1SDavid van Moolenbroek return -1;
2965e4e21ee1SDavid van Moolenbroek
2966e4e21ee1SDavid van Moolenbroek c += step;
2967e4e21ee1SDavid van Moolenbroek if (c == 0) {
2968e4e21ee1SDavid van Moolenbroek if (++step == 256)
2969e4e21ee1SDavid van Moolenbroek step = 1;
2970e4e21ee1SDavid van Moolenbroek c += step;
2971e4e21ee1SDavid van Moolenbroek }
2972e4e21ee1SDavid van Moolenbroek }
2973e4e21ee1SDavid van Moolenbroek
2974e4e21ee1SDavid van Moolenbroek return 0;
2975e4e21ee1SDavid van Moolenbroek }
2976e4e21ee1SDavid van Moolenbroek
2977e4e21ee1SDavid van Moolenbroek /*
2978e4e21ee1SDavid van Moolenbroek * Test large data sizes from an unprivileged process.
2979e4e21ee1SDavid van Moolenbroek */
2980e4e21ee1SDavid van Moolenbroek static void
sub87g(void)2981e4e21ee1SDavid van Moolenbroek sub87g(void)
2982e4e21ee1SDavid van Moolenbroek {
2983e4e21ee1SDavid van Moolenbroek char *ptr;
2984e4e21ee1SDavid van Moolenbroek size_t size, oldlen;
2985e4e21ee1SDavid van Moolenbroek int id, mib[3];
2986e4e21ee1SDavid van Moolenbroek
2987e4e21ee1SDavid van Moolenbroek size = getpagesize() * 3;
2988e4e21ee1SDavid van Moolenbroek
2989e4e21ee1SDavid van Moolenbroek if ((ptr = mmap(NULL, size, PROT_READ, MAP_ANON | MAP_PRIVATE, -1,
2990e4e21ee1SDavid van Moolenbroek 0)) == MAP_FAILED) e(0);
2991e4e21ee1SDavid van Moolenbroek memset(ptr, 0x2f, size);
2992e4e21ee1SDavid van Moolenbroek
2993e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
2994e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
2995e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
2996e4e21ee1SDavid van Moolenbroek oldlen = size - 2;
2997e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
2998e4e21ee1SDavid van Moolenbroek if (oldlen != size - 2) e(0);
2999e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'D', size - 2, 0) != 0) e(0);
3000e4e21ee1SDavid van Moolenbroek
3001e4e21ee1SDavid van Moolenbroek /*
3002e4e21ee1SDavid van Moolenbroek * Given the large data size, we currently expect this attempt to
3003e4e21ee1SDavid van Moolenbroek * write to the structure to be blocked by the MIB service.
3004e4e21ee1SDavid van Moolenbroek */
3005e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, ptr, oldlen) != -1) e(0);
3006e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
3007e4e21ee1SDavid van Moolenbroek
3008e4e21ee1SDavid van Moolenbroek /* Get the ID of the second dynamic node. */
3009e4e21ee1SDavid van Moolenbroek mib[2] = TEST_ANYWRITE;
3010e4e21ee1SDavid van Moolenbroek oldlen = sizeof(id);
3011e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &id, &oldlen, NULL, 0) != 0) e(0);
3012e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(id)) e(0);
3013e4e21ee1SDavid van Moolenbroek if (id < 0) e(0);
3014e4e21ee1SDavid van Moolenbroek
3015e4e21ee1SDavid van Moolenbroek /*
3016e4e21ee1SDavid van Moolenbroek * Test data size limits for strings as well, although here we can also
3017e4e21ee1SDavid van Moolenbroek * ensure that we hit the right check by testing with a shorter string.
3018e4e21ee1SDavid van Moolenbroek */
3019e4e21ee1SDavid van Moolenbroek mib[2] = id;
3020e4e21ee1SDavid van Moolenbroek oldlen = size;
3021e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3022e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3023e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'f', size - 1, 0) != 0) e(0);
3024e4e21ee1SDavid van Moolenbroek if (ptr[size - 1] != '\0') e(0);
3025e4e21ee1SDavid van Moolenbroek
3026e4e21ee1SDavid van Moolenbroek test_buf(ptr, 'h', size - 1, 1);
3027e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, ptr, size) != -1) e(0);
3028e4e21ee1SDavid van Moolenbroek if (errno != EPERM) e(0);
3029e4e21ee1SDavid van Moolenbroek
3030e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, ptr, getpagesize() - 1) != 0) e(0);
3031e4e21ee1SDavid van Moolenbroek
3032e4e21ee1SDavid van Moolenbroek if (munmap(ptr, size) != 0) e(0);
3033e4e21ee1SDavid van Moolenbroek }
3034e4e21ee1SDavid van Moolenbroek
3035e4e21ee1SDavid van Moolenbroek /*
3036e4e21ee1SDavid van Moolenbroek * Test large data sizes and mid-data page faults.
3037e4e21ee1SDavid van Moolenbroek */
3038e4e21ee1SDavid van Moolenbroek static void
test87g(void)3039e4e21ee1SDavid van Moolenbroek test87g(void)
3040e4e21ee1SDavid van Moolenbroek {
3041e4e21ee1SDavid van Moolenbroek struct sysctlnode scn, newscn;
3042e4e21ee1SDavid van Moolenbroek char *ptr;
3043e4e21ee1SDavid van Moolenbroek size_t pgsz, size, oldlen;
3044e4e21ee1SDavid van Moolenbroek int id, mib[3];
3045e4e21ee1SDavid van Moolenbroek
3046e4e21ee1SDavid van Moolenbroek subtest = 6;
3047e4e21ee1SDavid van Moolenbroek
3048e4e21ee1SDavid van Moolenbroek /*
3049e4e21ee1SDavid van Moolenbroek * No need to go overboard with sizes here; it will just cause the MIB
3050e4e21ee1SDavid van Moolenbroek * service's memory usage to grow - permanently. Three pages followed
3051e4e21ee1SDavid van Moolenbroek * by an unmapped page is plenty for this test.
3052e4e21ee1SDavid van Moolenbroek */
3053e4e21ee1SDavid van Moolenbroek pgsz = getpagesize();
3054e4e21ee1SDavid van Moolenbroek size = pgsz * 3;
3055e4e21ee1SDavid van Moolenbroek
3056e4e21ee1SDavid van Moolenbroek if ((ptr = mmap(NULL, size + pgsz, PROT_READ, MAP_ANON | MAP_PRIVATE,
3057e4e21ee1SDavid van Moolenbroek -1, 0)) == MAP_FAILED) e(0);
3058e4e21ee1SDavid van Moolenbroek if (munmap(ptr + size, pgsz) != 0) e(0);
3059e4e21ee1SDavid van Moolenbroek
3060e4e21ee1SDavid van Moolenbroek (void)destroy_node(mib, 2, TEST_DYNAMIC);
3061e4e21ee1SDavid van Moolenbroek
3062e4e21ee1SDavid van Moolenbroek /* Test string creation initializers with an accurate length. */
3063e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
3064e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
3065e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
3066e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
3067e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_OWNDATA |
3068e4e21ee1SDavid van Moolenbroek CTLFLAG_READWRITE | CTLTYPE_STRING;
3069e4e21ee1SDavid van Moolenbroek scn.sysctl_num = TEST_DYNAMIC;
3070e4e21ee1SDavid van Moolenbroek scn.sysctl_data = ptr;
3071e4e21ee1SDavid van Moolenbroek scn.sysctl_size = size;
3072e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic", sizeof(scn.sysctl_name));
3073e4e21ee1SDavid van Moolenbroek test_buf(ptr, 'a', size, 1);
3074e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3075e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0); /* no null terminator */
3076e4e21ee1SDavid van Moolenbroek
3077e4e21ee1SDavid van Moolenbroek scn.sysctl_size++;
3078e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3079e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3080e4e21ee1SDavid van Moolenbroek
3081e4e21ee1SDavid van Moolenbroek scn.sysctl_size--;
3082e4e21ee1SDavid van Moolenbroek ptr[size - 1] = '\0';
3083e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3084e4e21ee1SDavid van Moolenbroek
3085e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
3086e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
3087e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3088e4e21ee1SDavid van Moolenbroek
3089e4e21ee1SDavid van Moolenbroek memset(ptr, 0, size);
3090e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3091e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3092e4e21ee1SDavid van Moolenbroek if (ptr[size - 1] != '\0') e(0);
3093e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'a', size - 1, 0) != 0) e(0);
3094e4e21ee1SDavid van Moolenbroek
3095e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
3096e4e21ee1SDavid van Moolenbroek
3097e4e21ee1SDavid van Moolenbroek /* Test string creation initializers with no length. */
3098e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
3099e4e21ee1SDavid van Moolenbroek scn.sysctl_size = 0;
3100e4e21ee1SDavid van Moolenbroek test_buf(ptr, 'b', size, 1);
3101e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3102e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3103e4e21ee1SDavid van Moolenbroek
3104e4e21ee1SDavid van Moolenbroek test_buf(ptr, 'b', size - 1, 1);
3105e4e21ee1SDavid van Moolenbroek ptr[size - 1] = '\0';
3106e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3107e4e21ee1SDavid van Moolenbroek
3108e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &newscn) != 0) e(0);
3109e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_size != size) e(0);
3110e4e21ee1SDavid van Moolenbroek
3111e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
3112e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) != 0) e(0);
3113e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3114e4e21ee1SDavid van Moolenbroek
3115e4e21ee1SDavid van Moolenbroek memset(ptr, 0x7e, size);
3116e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3117e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3118e4e21ee1SDavid van Moolenbroek if (ptr[size - 1] != '\0') e(0);
3119e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'b', size - 1, 0) != 0) e(0);
3120e4e21ee1SDavid van Moolenbroek
3121e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
3122e4e21ee1SDavid van Moolenbroek
3123e4e21ee1SDavid van Moolenbroek /*
3124e4e21ee1SDavid van Moolenbroek * Test string creation initializers with a length exceeding the string
3125e4e21ee1SDavid van Moolenbroek * length. If the string is properly null terminated, this should not
3126e4e21ee1SDavid van Moolenbroek * result in a fault.
3127e4e21ee1SDavid van Moolenbroek */
3128e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
3129e4e21ee1SDavid van Moolenbroek scn.sysctl_size = size;
3130e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &ptr[size - pgsz - 5];
3131e4e21ee1SDavid van Moolenbroek test_buf(&ptr[size - pgsz - 5], 'c', pgsz + 5, 1);
3132e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3133e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3134e4e21ee1SDavid van Moolenbroek
3135e4e21ee1SDavid van Moolenbroek ptr[size - 1] = '\0';
3136e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3137e4e21ee1SDavid van Moolenbroek
3138e4e21ee1SDavid van Moolenbroek if (query_node(mib, 2, TEST_DYNAMIC, &newscn) != 0) e(0);
3139e4e21ee1SDavid van Moolenbroek if (newscn.sysctl_size != size) e(0);
3140e4e21ee1SDavid van Moolenbroek
3141e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
3142e4e21ee1SDavid van Moolenbroek oldlen = size - pgsz - 6;
3143e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3144e4e21ee1SDavid van Moolenbroek if (oldlen != pgsz + 5) e(0);
3145e4e21ee1SDavid van Moolenbroek /* We rely on only the actual string getting copied out here. */
3146e4e21ee1SDavid van Moolenbroek if (memcmp(ptr, &ptr[size - pgsz - 5], pgsz + 5)) e(0);
3147e4e21ee1SDavid van Moolenbroek
3148e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
3149e4e21ee1SDavid van Moolenbroek
3150e4e21ee1SDavid van Moolenbroek /* Test structure creation initializers. */
3151e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
3152e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_OWNDATA |
3153e4e21ee1SDavid van Moolenbroek CTLFLAG_ANYWRITE | CTLFLAG_READWRITE | CTLTYPE_STRUCT;
3154e4e21ee1SDavid van Moolenbroek scn.sysctl_size = size - 2;
3155e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &ptr[3];
3156e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3157e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3158e4e21ee1SDavid van Moolenbroek
3159e4e21ee1SDavid van Moolenbroek scn.sysctl_data = &ptr[2];
3160e4e21ee1SDavid van Moolenbroek test_buf(&ptr[2], 'd', size - 2, 1);
3161e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3162e4e21ee1SDavid van Moolenbroek
3163e4e21ee1SDavid van Moolenbroek mib[2] = TEST_DYNAMIC;
3164e4e21ee1SDavid van Moolenbroek memset(ptr, 0x3b, size);
3165e4e21ee1SDavid van Moolenbroek oldlen = size - 2;
3166e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &ptr[3], &oldlen, NULL, 0) != -1) e(0);
3167e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3168e4e21ee1SDavid van Moolenbroek oldlen = size - 2;
3169e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &ptr[2], &oldlen, NULL, 0) != 0) e(0);
3170e4e21ee1SDavid van Moolenbroek if (oldlen != size - 2) e(0);
3171e4e21ee1SDavid van Moolenbroek if (test_buf(&ptr[2], 'd', size - 2, 0) != 0) e(0);
3172e4e21ee1SDavid van Moolenbroek
3173e4e21ee1SDavid van Moolenbroek /*
3174e4e21ee1SDavid van Moolenbroek * Test setting new values. We already have a structure node, so let's
3175e4e21ee1SDavid van Moolenbroek * start there.
3176e4e21ee1SDavid van Moolenbroek */
3177e4e21ee1SDavid van Moolenbroek test_buf(&ptr[2], 'D', size - 2, 1);
3178e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &ptr[3], size - 2) != -1) e(0);
3179e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3180e4e21ee1SDavid van Moolenbroek
3181e4e21ee1SDavid van Moolenbroek /* Did the mid-data fault cause a partial update? It better not. */
3182e4e21ee1SDavid van Moolenbroek memset(ptr, 0x4c, size);
3183e4e21ee1SDavid van Moolenbroek oldlen = size - 2;
3184e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3185e4e21ee1SDavid van Moolenbroek if (oldlen != size - 2) e(0);
3186e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'd', size - 2, 0) != 0) e(0);
3187e4e21ee1SDavid van Moolenbroek
3188e4e21ee1SDavid van Moolenbroek test_buf(&ptr[2], 'D', size - 2, 1);
3189e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &ptr[2], size - 2) != 0) e(0);
3190e4e21ee1SDavid van Moolenbroek
3191e4e21ee1SDavid van Moolenbroek memset(ptr, 0x5d, size);
3192e4e21ee1SDavid van Moolenbroek oldlen = size - 2;
3193e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3194e4e21ee1SDavid van Moolenbroek if (oldlen != size - 2) e(0);
3195e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'D', size - 2, 0) != 0) e(0);
3196e4e21ee1SDavid van Moolenbroek
3197e4e21ee1SDavid van Moolenbroek /*
3198e4e21ee1SDavid van Moolenbroek * We are going to reuse TEST_DYNAMIC for the non-root test later, so
3199e4e21ee1SDavid van Moolenbroek * create a new node for string tests.
3200e4e21ee1SDavid van Moolenbroek */
3201e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
3202e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
3203e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_OWNDATA |
3204e4e21ee1SDavid van Moolenbroek CTLFLAG_ANYWRITE | CTLFLAG_READWRITE | CTLTYPE_STRING;
3205e4e21ee1SDavid van Moolenbroek scn.sysctl_num = CTL_CREATE;
3206e4e21ee1SDavid van Moolenbroek scn.sysctl_size = size;
3207e4e21ee1SDavid van Moolenbroek scn.sysctl_data = ptr;
3208e4e21ee1SDavid van Moolenbroek test_buf(ptr, 'e', size - 1, 1);
3209e4e21ee1SDavid van Moolenbroek ptr[size - 1] = '\0';
3210e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "dynamic2", sizeof(scn.sysctl_name));
3211e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newscn);
3212e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3213e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newscn)) e(0);
3214e4e21ee1SDavid van Moolenbroek id = newscn.sysctl_num;
3215e4e21ee1SDavid van Moolenbroek if (id < 0) e(0);
3216e4e21ee1SDavid van Moolenbroek
3217e4e21ee1SDavid van Moolenbroek /*
3218e4e21ee1SDavid van Moolenbroek * Test setting a short but faulty string, ensuring that no partial
3219e4e21ee1SDavid van Moolenbroek * update on the field contents takes place.
3220e4e21ee1SDavid van Moolenbroek */
3221e4e21ee1SDavid van Moolenbroek mib[2] = id;
3222e4e21ee1SDavid van Moolenbroek memcpy(&ptr[size - 3], "XYZ", 3);
3223e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &ptr[size - 3], 4) != -1) e(0);
3224e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3225e4e21ee1SDavid van Moolenbroek
3226e4e21ee1SDavid van Moolenbroek oldlen = size;
3227e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3228e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3229e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'e', size - 1, 0) != 0) e(0);
3230e4e21ee1SDavid van Moolenbroek if (ptr[size - 1] != '\0') e(0);
3231e4e21ee1SDavid van Moolenbroek
3232e4e21ee1SDavid van Moolenbroek memcpy(&ptr[size - 3], "XYZ", 3);
3233e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &ptr[size - 3], 3) != 0) e(0);
3234e4e21ee1SDavid van Moolenbroek
3235e4e21ee1SDavid van Moolenbroek oldlen = size;
3236e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3237e4e21ee1SDavid van Moolenbroek if (oldlen != 4) e(0);
3238e4e21ee1SDavid van Moolenbroek if (strcmp(ptr, "XYZ")) e(0);
3239e4e21ee1SDavid van Moolenbroek
3240e4e21ee1SDavid van Moolenbroek test_buf(&ptr[1], 'f', size - 1, 1);
3241e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &ptr[1], size - 1) != 0) e(0);
3242e4e21ee1SDavid van Moolenbroek
3243e4e21ee1SDavid van Moolenbroek test_buf(&ptr[1], 'G', size - 1, 1);
3244e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &ptr[1], size) != -1) e(0);
3245e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3246e4e21ee1SDavid van Moolenbroek
3247e4e21ee1SDavid van Moolenbroek oldlen = size;
3248e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3249e4e21ee1SDavid van Moolenbroek if (oldlen != size) e(0);
3250e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'f', size - 1, 0) != 0) e(0);
3251e4e21ee1SDavid van Moolenbroek if (ptr[size - 1] != '\0') e(0);
3252e4e21ee1SDavid van Moolenbroek
3253e4e21ee1SDavid van Moolenbroek /*
3254e4e21ee1SDavid van Moolenbroek * Test descriptions as well. First, the MIB service does not allow
3255e4e21ee1SDavid van Moolenbroek * for overly long descriptions, although the limit is not exposed.
3256e4e21ee1SDavid van Moolenbroek * Three memory pages worth of text is way too long though.
3257e4e21ee1SDavid van Moolenbroek */
3258e4e21ee1SDavid van Moolenbroek memset(ptr, 'A', size);
3259e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, ptr, 1) != -1) e(0);
3260e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0); /* not EFAULT, should never get that far */
3261e4e21ee1SDavid van Moolenbroek
3262e4e21ee1SDavid van Moolenbroek ptr[size - 1] = '\0';
3263e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, ptr, 1) != -1) e(0);
3264e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3265e4e21ee1SDavid van Moolenbroek
3266e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, "", 0) != 0) e(0);
3267e4e21ee1SDavid van Moolenbroek
3268e4e21ee1SDavid van Moolenbroek /*
3269e4e21ee1SDavid van Moolenbroek * Second, the description routine must deal with faults occurring
3270e4e21ee1SDavid van Moolenbroek * while it is trying to find the string end.
3271e4e21ee1SDavid van Moolenbroek */
3272e4e21ee1SDavid van Moolenbroek ptr[size - 2] = 'B';
3273e4e21ee1SDavid van Moolenbroek ptr[size - 1] = 'C';
3274e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, &ptr[size - 3], 1) != -1) e(0);
3275e4e21ee1SDavid van Moolenbroek if (errno != EFAULT) e(0);
3276e4e21ee1SDavid van Moolenbroek
3277e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, "", 0) != 0) e(0);
3278e4e21ee1SDavid van Moolenbroek
3279e4e21ee1SDavid van Moolenbroek ptr[size - 1] = '\0';
3280e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, &ptr[size - 3], 1) != 0) e(0);
3281e4e21ee1SDavid van Moolenbroek
3282e4e21ee1SDavid van Moolenbroek if (describe_node(mib, 2, id, "AB", 0) != 0) e(0);
3283e4e21ee1SDavid van Moolenbroek
3284e4e21ee1SDavid van Moolenbroek /* Pass the second dynamic node ID to the unprivileged child. */
3285e4e21ee1SDavid van Moolenbroek mib[2] = TEST_ANYWRITE;
3286e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &id, sizeof(id)) != 0) e(0);
3287e4e21ee1SDavid van Moolenbroek
3288e4e21ee1SDavid van Moolenbroek (void)test_nonroot(sub87g);
3289e4e21ee1SDavid van Moolenbroek
3290e4e21ee1SDavid van Moolenbroek mib[2] = id;
3291e4e21ee1SDavid van Moolenbroek oldlen = size;
3292e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, ptr, &oldlen, NULL, 0) != 0) e(0);
3293e4e21ee1SDavid van Moolenbroek if (oldlen != pgsz) e(0);
3294e4e21ee1SDavid van Moolenbroek if (test_buf(ptr, 'h', pgsz - 1, 1) != 0) e(0);
3295e4e21ee1SDavid van Moolenbroek if (ptr[pgsz - 1] != '\0') e(0);
3296e4e21ee1SDavid van Moolenbroek
3297e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, TEST_DYNAMIC) != 0) e(0);
3298e4e21ee1SDavid van Moolenbroek if (destroy_node(mib, 2, id) != 0) e(0);
3299e4e21ee1SDavid van Moolenbroek
3300e4e21ee1SDavid van Moolenbroek munmap(ptr, size);
3301e4e21ee1SDavid van Moolenbroek }
3302e4e21ee1SDavid van Moolenbroek
3303e4e21ee1SDavid van Moolenbroek /*
3304e4e21ee1SDavid van Moolenbroek * Verify whether the given node on the given path has the given node version.
3305e4e21ee1SDavid van Moolenbroek * Return 0 if the version matches, or -1 if it does not or a failure occurred.
3306e4e21ee1SDavid van Moolenbroek */
3307e4e21ee1SDavid van Moolenbroek static int
check_version(const int * path,unsigned int pathlen,int id,uint32_t ver)3308e4e21ee1SDavid van Moolenbroek check_version(const int * path, unsigned int pathlen, int id, uint32_t ver)
3309e4e21ee1SDavid van Moolenbroek {
3310e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
3311e4e21ee1SDavid van Moolenbroek struct sysctldesc scd;
3312e4e21ee1SDavid van Moolenbroek size_t oldlen;
3313e4e21ee1SDavid van Moolenbroek int r, mib[CTL_MAXNAME];
3314e4e21ee1SDavid van Moolenbroek
3315e4e21ee1SDavid van Moolenbroek assert(pathlen < CTL_MAXNAME);
3316e4e21ee1SDavid van Moolenbroek memcpy(mib, path, sizeof(mib[0]) * pathlen);
3317e4e21ee1SDavid van Moolenbroek mib[pathlen] = CTL_DESCRIBE;
3318e4e21ee1SDavid van Moolenbroek
3319e4e21ee1SDavid van Moolenbroek /*
3320e4e21ee1SDavid van Moolenbroek * For some reason, when retrieving a particular description (as
3321e4e21ee1SDavid van Moolenbroek * opposed to setting one), the node version number is not checked.
3322e4e21ee1SDavid van Moolenbroek * In order to test this, we deliberately pass in a node version number
3323e4e21ee1SDavid van Moolenbroek * that, if checked, would eventually cause failures.
3324e4e21ee1SDavid van Moolenbroek */
3325e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
3326e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
3327e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id;
3328e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = 1;
3329e4e21ee1SDavid van Moolenbroek oldlen = sizeof(scd);
3330e4e21ee1SDavid van Moolenbroek r = sysctl(mib, pathlen + 1, &scd, &oldlen, &scn, sizeof(scn));
3331e4e21ee1SDavid van Moolenbroek if (r == -1 && errno != ENOMEM) e(0);
3332e4e21ee1SDavid van Moolenbroek
3333e4e21ee1SDavid van Moolenbroek return (scd.descr_ver == ver) ? 0 : -1;
3334e4e21ee1SDavid van Moolenbroek }
3335e4e21ee1SDavid van Moolenbroek
3336e4e21ee1SDavid van Moolenbroek /*
3337e4e21ee1SDavid van Moolenbroek * Test sysctl(2) node versioning.
3338e4e21ee1SDavid van Moolenbroek */
3339e4e21ee1SDavid van Moolenbroek static void
test87h(void)3340e4e21ee1SDavid van Moolenbroek test87h(void)
3341e4e21ee1SDavid van Moolenbroek {
3342e4e21ee1SDavid van Moolenbroek struct sysctlnode scn, oldscn;
3343e4e21ee1SDavid van Moolenbroek size_t oldlen;
3344e4e21ee1SDavid van Moolenbroek uint32_t ver[4];
3345e4e21ee1SDavid van Moolenbroek int mib[4], id[4];
3346e4e21ee1SDavid van Moolenbroek
3347e4e21ee1SDavid van Moolenbroek /*
3348e4e21ee1SDavid van Moolenbroek * The other tests have already tested sufficiently that a zero version
3349e4e21ee1SDavid van Moolenbroek * is always accepted in calls. Here, we test that node versions
3350e4e21ee1SDavid van Moolenbroek * actually change when creating and destroying nodes, and that the
3351e4e21ee1SDavid van Moolenbroek * right version test is implemented for all of the four node meta-
3352e4e21ee1SDavid van Moolenbroek * operations (query, create, destroy, describe). Why did we not do
3353e4e21ee1SDavid van Moolenbroek * this earlier, you ask? Well, versioning was implemented later on.
3354e4e21ee1SDavid van Moolenbroek */
3355e4e21ee1SDavid van Moolenbroek subtest = 7;
3356e4e21ee1SDavid van Moolenbroek
3357e4e21ee1SDavid van Moolenbroek /*
3358e4e21ee1SDavid van Moolenbroek * Test versioning with node creation.
3359e4e21ee1SDavid van Moolenbroek */
3360e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
3361e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_TEST;
3362e4e21ee1SDavid van Moolenbroek mib[2] = CTL_CREATE;
3363e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
3364e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE | CTLTYPE_NODE;
3365e4e21ee1SDavid van Moolenbroek scn.sysctl_num = CTL_CREATE;
3366e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "NodeA", sizeof(scn.sysctl_name));
3367e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
3368e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3369e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
3370e4e21ee1SDavid van Moolenbroek id[0] = oldscn.sysctl_num;
3371e4e21ee1SDavid van Moolenbroek ver[0] = oldscn.sysctl_ver;
3372e4e21ee1SDavid van Moolenbroek if (ver[0] == 0) e(0);
3373e4e21ee1SDavid van Moolenbroek
3374e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[0]) != 0) e(0);
3375e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[0]) != 0) e(0);
3376e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[0]) != 0) e(0);
3377e4e21ee1SDavid van Moolenbroek
3378e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "NodeB", sizeof(scn.sysctl_name));
3379e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
3380e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3381e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
3382e4e21ee1SDavid van Moolenbroek id[1] = oldscn.sysctl_num;
3383e4e21ee1SDavid van Moolenbroek ver[1] = oldscn.sysctl_ver;
3384e4e21ee1SDavid van Moolenbroek if (ver[1] == 0) e(0);
3385e4e21ee1SDavid van Moolenbroek if (ver[1] != NEXT_VER(ver[0])) e(0);
3386e4e21ee1SDavid van Moolenbroek
3387e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[1]) != 0) e(0);
3388e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[1]) != 0) e(0);
3389e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[0]) != 0) e(0);
3390e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[1]) != 0) e(0);
3391e4e21ee1SDavid van Moolenbroek
3392e4e21ee1SDavid van Moolenbroek /* A version that is too high should be rejected. */
3393e4e21ee1SDavid van Moolenbroek mib[2] = id[0];
3394e4e21ee1SDavid van Moolenbroek mib[3] = CTL_CREATE;
3395e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION | CTLFLAG_IMMEDIATE |
3396e4e21ee1SDavid van Moolenbroek CTLFLAG_READWRITE | CTLTYPE_INT;
3397e4e21ee1SDavid van Moolenbroek scn.sysctl_size = sizeof(int);
3398e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = NEXT_VER(ver[1]);
3399e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "ValueA", sizeof(scn.sysctl_name));
3400e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3401e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3402e4e21ee1SDavid van Moolenbroek
3403e4e21ee1SDavid van Moolenbroek /* The version of the parent node should be accepted. */
3404e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[0]; /* different from the root node version */
3405e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
3406e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3407e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
3408e4e21ee1SDavid van Moolenbroek id[2] = oldscn.sysctl_num;
3409e4e21ee1SDavid van Moolenbroek ver[2] = oldscn.sysctl_ver;
3410e4e21ee1SDavid van Moolenbroek if (ver[2] == 0) e(0);
3411e4e21ee1SDavid van Moolenbroek if (ver[2] != NEXT_VER(ver[1])) e(0);
3412e4e21ee1SDavid van Moolenbroek
3413e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[2]) != 0) e(0);
3414e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[2]) != 0) e(0);
3415e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[2]) != 0) e(0);
3416e4e21ee1SDavid van Moolenbroek if (check_version(mib, 3, id[2], ver[2]) != 0) e(0);
3417e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[1]) != 0) e(0);
3418e4e21ee1SDavid van Moolenbroek
3419e4e21ee1SDavid van Moolenbroek /* A version that is too low (old) should be rejected. */
3420e4e21ee1SDavid van Moolenbroek mib[2] = id[1];
3421e4e21ee1SDavid van Moolenbroek
3422e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[0];
3423e4e21ee1SDavid van Moolenbroek strlcpy(scn.sysctl_name, "ValueB", sizeof(scn.sysctl_name));
3424e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3425e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3426e4e21ee1SDavid van Moolenbroek
3427e4e21ee1SDavid van Moolenbroek /* The version of the root node should be accepted. */
3428e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[2]; /* different from the parent node version */
3429e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
3430e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3431e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
3432e4e21ee1SDavid van Moolenbroek id[3] = oldscn.sysctl_num;
3433e4e21ee1SDavid van Moolenbroek ver[3] = oldscn.sysctl_ver;
3434e4e21ee1SDavid van Moolenbroek if (ver[3] == 0) e(0);
3435e4e21ee1SDavid van Moolenbroek if (ver[3] != NEXT_VER(ver[2])) e(0);
3436e4e21ee1SDavid van Moolenbroek
3437e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[3]) != 0) e(0);
3438e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[3]) != 0) e(0);
3439e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[2]) != 0) e(0);
3440e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[3]) != 0) e(0);
3441e4e21ee1SDavid van Moolenbroek if (check_version(mib, 3, id[3], ver[3]) != 0) e(0);
3442e4e21ee1SDavid van Moolenbroek mib[2] = id[0];
3443e4e21ee1SDavid van Moolenbroek if (check_version(mib, 3, id[2], ver[2]) != 0) e(0);
3444e4e21ee1SDavid van Moolenbroek
3445e4e21ee1SDavid van Moolenbroek /*
3446e4e21ee1SDavid van Moolenbroek * Test versioning with node queries.
3447e4e21ee1SDavid van Moolenbroek */
3448e4e21ee1SDavid van Moolenbroek mib[3] = CTL_QUERY;
3449e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
3450e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
3451e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[0]; /* previous parent version */
3452e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3453e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3454e4e21ee1SDavid van Moolenbroek
3455e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[2]; /* parent version */
3456e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3457e4e21ee1SDavid van Moolenbroek
3458e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[2]; /* root version */
3459e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3460e4e21ee1SDavid van Moolenbroek
3461e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = NEXT_VER(ver[3]); /* nonexistent version */
3462e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3463e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3464e4e21ee1SDavid van Moolenbroek
3465e4e21ee1SDavid van Moolenbroek /*
3466e4e21ee1SDavid van Moolenbroek * Test versioning with node description.
3467e4e21ee1SDavid van Moolenbroek */
3468e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESCRIBE;
3469e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id[0];
3470e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[3]; /* root and parent, but not target version */
3471e4e21ee1SDavid van Moolenbroek scn.sysctl_desc = "Parent A";
3472e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3473e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3474e4e21ee1SDavid van Moolenbroek
3475e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[1]; /* another bad version */
3476e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3477e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3478e4e21ee1SDavid van Moolenbroek
3479e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[2]; /* target version */
3480e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3481e4e21ee1SDavid van Moolenbroek
3482e4e21ee1SDavid van Moolenbroek /* Neither querying nor description should have changed versions. */
3483e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[3]) != 0) e(0);
3484e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[3]) != 0) e(0);
3485e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[2]) != 0) e(0);
3486e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[3]) != 0) e(0);
3487e4e21ee1SDavid van Moolenbroek mib[2] = id[1];
3488e4e21ee1SDavid van Moolenbroek if (check_version(mib, 3, id[3], ver[3]) != 0) e(0);
3489e4e21ee1SDavid van Moolenbroek mib[2] = id[0];
3490e4e21ee1SDavid van Moolenbroek if (check_version(mib, 3, id[2], ver[2]) != 0) e(0);
3491e4e21ee1SDavid van Moolenbroek
3492e4e21ee1SDavid van Moolenbroek /*
3493e4e21ee1SDavid van Moolenbroek * Test versioning with node destruction.
3494e4e21ee1SDavid van Moolenbroek */
3495e4e21ee1SDavid van Moolenbroek mib[3] = CTL_DESTROY;
3496e4e21ee1SDavid van Moolenbroek memset(&scn, 0, sizeof(scn));
3497e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = SYSCTL_VERSION;
3498e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id[2];
3499e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[3]; /* root but not target version */
3500e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3501e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3502e4e21ee1SDavid van Moolenbroek
3503e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[2]; /* target (and parent) version */
3504e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3505e4e21ee1SDavid van Moolenbroek
3506e4e21ee1SDavid van Moolenbroek /* Fortunately, versions are predictable. */
3507e4e21ee1SDavid van Moolenbroek ver[0] = NEXT_VER(ver[3]);
3508e4e21ee1SDavid van Moolenbroek
3509e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[0]) != 0) e(0);
3510e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[0]) != 0) e(0);
3511e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[0]) != 0) e(0);
3512e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[3]) != 0) e(0);
3513e4e21ee1SDavid van Moolenbroek
3514e4e21ee1SDavid van Moolenbroek mib[2] = id[1];
3515e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id[3];
3516e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[0]; /* root but not target version */
3517e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3518e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3519e4e21ee1SDavid van Moolenbroek
3520e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[3]; /* target (and parent) version */
3521e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 4, NULL, NULL, &scn, sizeof(scn)) != 0) e(0);
3522e4e21ee1SDavid van Moolenbroek
3523e4e21ee1SDavid van Moolenbroek ver[1] = NEXT_VER(ver[0]);
3524e4e21ee1SDavid van Moolenbroek
3525e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[1]) != 0) e(0);
3526e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[1]) != 0) e(0);
3527e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[0], ver[0]) != 0) e(0);
3528e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[1]) != 0) e(0);
3529e4e21ee1SDavid van Moolenbroek
3530e4e21ee1SDavid van Moolenbroek mib[2] = CTL_DESTROY;
3531e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id[0];
3532e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[1]; /* root and parent, but not target version */
3533e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, NULL, NULL, &scn, sizeof(scn)) != -1) e(0);
3534e4e21ee1SDavid van Moolenbroek if (errno != EINVAL) e(0);
3535e4e21ee1SDavid van Moolenbroek
3536e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = ver[0]; /* target version */
3537e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
3538e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3539e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
3540e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_num != id[0]) e(0);
3541e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_ver != ver[0]) e(0);
3542e4e21ee1SDavid van Moolenbroek
3543e4e21ee1SDavid van Moolenbroek ver[2] = NEXT_VER(ver[1]);
3544e4e21ee1SDavid van Moolenbroek
3545e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[2]) != 0) e(0);
3546e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[2]) != 0) e(0);
3547e4e21ee1SDavid van Moolenbroek if (check_version(mib, 2, id[1], ver[1]) != 0) e(0);
3548e4e21ee1SDavid van Moolenbroek
3549e4e21ee1SDavid van Moolenbroek /* For the last destruction, just see if we get the old version. */
3550e4e21ee1SDavid van Moolenbroek scn.sysctl_num = id[1];
3551e4e21ee1SDavid van Moolenbroek scn.sysctl_ver = 0;
3552e4e21ee1SDavid van Moolenbroek oldlen = sizeof(oldscn);
3553e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &oldscn, &oldlen, &scn, sizeof(scn)) != 0) e(0);
3554e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(oldscn)) e(0);
3555e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_num != id[1]) e(0);
3556e4e21ee1SDavid van Moolenbroek if (oldscn.sysctl_ver != ver[1]) e(0);
3557e4e21ee1SDavid van Moolenbroek
3558e4e21ee1SDavid van Moolenbroek ver[3] = NEXT_VER(ver[2]);
3559e4e21ee1SDavid van Moolenbroek
3560e4e21ee1SDavid van Moolenbroek if (check_version(mib, 0, CTL_MINIX, ver[3]) != 0) e(0);
3561e4e21ee1SDavid van Moolenbroek if (check_version(mib, 1, MINIX_TEST, ver[3]) != 0) e(0);
3562e4e21ee1SDavid van Moolenbroek }
3563e4e21ee1SDavid van Moolenbroek
3564e4e21ee1SDavid van Moolenbroek /*
3565e4e21ee1SDavid van Moolenbroek * Perform pre-test initialization.
3566e4e21ee1SDavid van Moolenbroek */
3567e4e21ee1SDavid van Moolenbroek static void
test87_init(void)3568e4e21ee1SDavid van Moolenbroek test87_init(void)
3569e4e21ee1SDavid van Moolenbroek {
3570e4e21ee1SDavid van Moolenbroek size_t oldlen;
3571e4e21ee1SDavid van Moolenbroek int mib[3];
3572e4e21ee1SDavid van Moolenbroek
3573e4e21ee1SDavid van Moolenbroek subtest = 99;
3574e4e21ee1SDavid van Moolenbroek
3575e4e21ee1SDavid van Moolenbroek if ((bad_ptr = mmap(NULL, getpagesize(), PROT_READ,
3576e4e21ee1SDavid van Moolenbroek MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED) e(0);
3577e4e21ee1SDavid van Moolenbroek if (munmap(bad_ptr, getpagesize()) != 0) e(0);
3578e4e21ee1SDavid van Moolenbroek
3579e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
3580e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_MIB;
3581e4e21ee1SDavid van Moolenbroek mib[2] = MIB_NODES;
3582e4e21ee1SDavid van Moolenbroek oldlen = sizeof(nodes);
3583e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &nodes, &oldlen, NULL, 0) != 0) e(0);
3584e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(nodes)) e(0);
3585e4e21ee1SDavid van Moolenbroek
3586e4e21ee1SDavid van Moolenbroek mib[2] = MIB_OBJECTS;
3587e4e21ee1SDavid van Moolenbroek oldlen = sizeof(objects);
3588e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &objects, &oldlen, NULL, 0) != 0) e(0);
3589e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(objects)) e(0);
3590e4e21ee1SDavid van Moolenbroek }
3591e4e21ee1SDavid van Moolenbroek
3592e4e21ee1SDavid van Moolenbroek /*
3593e4e21ee1SDavid van Moolenbroek * Perform post-test checks.
3594e4e21ee1SDavid van Moolenbroek */
3595e4e21ee1SDavid van Moolenbroek static void
test87_check(void)3596e4e21ee1SDavid van Moolenbroek test87_check(void)
3597e4e21ee1SDavid van Moolenbroek {
3598e4e21ee1SDavid van Moolenbroek unsigned int newnodes, newobjects;
3599e4e21ee1SDavid van Moolenbroek size_t oldlen;
3600e4e21ee1SDavid van Moolenbroek int mib[3];
3601e4e21ee1SDavid van Moolenbroek
3602e4e21ee1SDavid van Moolenbroek subtest = 99;
3603e4e21ee1SDavid van Moolenbroek
3604e4e21ee1SDavid van Moolenbroek mib[0] = CTL_MINIX;
3605e4e21ee1SDavid van Moolenbroek mib[1] = MINIX_MIB;
3606e4e21ee1SDavid van Moolenbroek mib[2] = MIB_NODES;
3607e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newnodes);
3608e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newnodes, &oldlen, NULL, 0) != 0) e(0);
3609e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newnodes)) e(0);
3610e4e21ee1SDavid van Moolenbroek
3611e4e21ee1SDavid van Moolenbroek /*
3612e4e21ee1SDavid van Moolenbroek * Upon the first run, the total number of nodes must actually go down,
3613e4e21ee1SDavid van Moolenbroek * as we destroy number of static nodes. Upon subsequent runs, the
3614e4e21ee1SDavid van Moolenbroek * number of nodes should remain stable. Thus, we can safely test that
3615e4e21ee1SDavid van Moolenbroek * the number of nodes has not gone up as a result of the test.
3616e4e21ee1SDavid van Moolenbroek */
3617e4e21ee1SDavid van Moolenbroek if (newnodes > nodes) e(0);
3618e4e21ee1SDavid van Moolenbroek
3619e4e21ee1SDavid van Moolenbroek mib[2] = MIB_OBJECTS;
3620e4e21ee1SDavid van Moolenbroek oldlen = sizeof(newobjects);
3621e4e21ee1SDavid van Moolenbroek if (sysctl(mib, 3, &newobjects, &oldlen, NULL, 0) != 0) e(0);
3622e4e21ee1SDavid van Moolenbroek if (oldlen != sizeof(newobjects)) e(0);
3623e4e21ee1SDavid van Moolenbroek
3624e4e21ee1SDavid van Moolenbroek /*
3625e4e21ee1SDavid van Moolenbroek * The number of dynamically allocated objects should remain the same
3626e4e21ee1SDavid van Moolenbroek * across the test.
3627e4e21ee1SDavid van Moolenbroek */
3628e4e21ee1SDavid van Moolenbroek if (newobjects != objects) e(0);
3629e4e21ee1SDavid van Moolenbroek }
3630e4e21ee1SDavid van Moolenbroek
3631e4e21ee1SDavid van Moolenbroek /*
3632e4e21ee1SDavid van Moolenbroek * Test program for sysctl(2).
3633e4e21ee1SDavid van Moolenbroek */
3634e4e21ee1SDavid van Moolenbroek int
main(int argc,char ** argv)3635e4e21ee1SDavid van Moolenbroek main(int argc, char ** argv)
3636e4e21ee1SDavid van Moolenbroek {
3637e4e21ee1SDavid van Moolenbroek int i, m;
3638e4e21ee1SDavid van Moolenbroek
3639e4e21ee1SDavid van Moolenbroek start(87);
3640e4e21ee1SDavid van Moolenbroek
3641e4e21ee1SDavid van Moolenbroek if (argc == 2)
3642e4e21ee1SDavid van Moolenbroek m = atoi(argv[1]);
3643e4e21ee1SDavid van Moolenbroek else
3644e4e21ee1SDavid van Moolenbroek m = 0xFF;
3645e4e21ee1SDavid van Moolenbroek
3646e4e21ee1SDavid van Moolenbroek test87_init();
3647e4e21ee1SDavid van Moolenbroek
3648e4e21ee1SDavid van Moolenbroek for (i = 0; i < ITERATIONS; i++) {
3649e4e21ee1SDavid van Moolenbroek if (m & 0x001) test87a();
3650e4e21ee1SDavid van Moolenbroek if (m & 0x002) test87b();
3651e4e21ee1SDavid van Moolenbroek if (m & 0x004) test87c();
3652e4e21ee1SDavid van Moolenbroek if (m & 0x008) test87d();
3653e4e21ee1SDavid van Moolenbroek if (m & 0x010) test87e();
3654e4e21ee1SDavid van Moolenbroek if (m & 0x020) test87f();
3655e4e21ee1SDavid van Moolenbroek if (m & 0x040) test87g();
3656e4e21ee1SDavid van Moolenbroek if (m & 0x080) test87h();
3657e4e21ee1SDavid van Moolenbroek }
3658e4e21ee1SDavid van Moolenbroek
3659e4e21ee1SDavid van Moolenbroek test87_check();
3660e4e21ee1SDavid van Moolenbroek
3661e4e21ee1SDavid van Moolenbroek quit();
3662e4e21ee1SDavid van Moolenbroek }
3663