xref: /minix/minix/servers/mib/tree.c (revision b89261ba)
1 /* MIB service - tree.c - tree access and management */
2 
3 #include "mib.h"
4 
5 /*
6  * Does the given identifier fall within the range of static identifiers in the
7  * given parent?  This check can be used to enumerate all static array entries
8  * in the given parent, starting from zero.  The check does not guarantee that
9  * the entry is actually for a valid node, nor does it guarantee that there is
10  * not a dynamic node with this identifier.
11  */
12 #define IS_STATIC_ID(parent, id) ((unsigned int)(id) < (parent)->node_size)
13 
14 /*
15  * Scratch buffer, used for various cases of temporary data storage.  It must
16  * be large enough to fit a sysctldesc structure followed by the longest
17  * supported description.  It must also be large enough to serve as temporary
18  * storage for data being written in the majority of cases.  Finally, it must
19  * be large enough to contain an entire page, for mib_copyin_str().
20  */
21 #define MAXDESCLEN	1024	/* from NetBSD */
22 #define SCRATCH_SIZE	MAX(PAGE_SIZE, sizeof(struct sysctldesc) + MAXDESCLEN)
23 static char scratch[SCRATCH_SIZE] __aligned(sizeof(int32_t));
24 
25 unsigned int nodes;	/* how many nodes are there in the tree? */
26 unsigned int objects;	/* how many allocated memory objects are there? */
27 
28 /*
29  * Find a node through its parent node and identifier.  Return the node if it
30  * was found, and optionally store a pointer to the pointer to its dynode
31  * superstructure (for removal).  If no matching node was found, return NULL.
32  */
33 static struct mib_node *
34 mib_find(struct mib_node * parent, int id, struct mib_dynode *** prevpp)
35 {
36 	struct mib_node *node;
37 	struct mib_dynode **dynp;
38 
39 	if (id < 0)
40 		return NULL;
41 
42 	/*
43 	 * Is there a static node with this identifier?  The static nodes are
44 	 * all in a single array, so lookup is O(1) for these nodes.  We use
45 	 * the node flags field to see whether the array entry is valid.
46 	 */
47 	if (IS_STATIC_ID(parent, id)) {
48 		node = &parent->node_scptr[id];
49 
50 		if (node->node_flags != 0) {
51 			/* Found a matching static node. */
52 			if (prevpp != NULL)
53 				*prevpp = NULL;
54 			return node;
55 		}
56 	}
57 
58 	/*
59 	 * Is there a dynamic node with this identifier?  The dynamic nodes
60 	 * form a linked list.  This is predominantly because userland may pick
61 	 * the identifier number at creation time, so we cannot rely on all
62 	 * dynamically created nodes falling into a small identifier range.
63 	 * That eliminates the option of a dynamic array indexed by identifier,
64 	 * and a linked list is the simplest next option.  Thus, dynamic node
65 	 * lookup is O(n).  However, since the list is sorted by identifier,
66 	 * we may be able to stop the search early.
67 	 */
68 	for (dynp = &parent->node_dcptr; *dynp != NULL;
69 	    dynp = &((*dynp)->dynode_next)) {
70 		if ((*dynp)->dynode_id == id) {
71 			/* Found a matching dynamic node. */
72 			if (prevpp != NULL)
73 				*prevpp = dynp;
74 			return &(*dynp)->dynode_node;
75 		} else if ((*dynp)->dynode_id > id)
76 			break; /* no need to look further */
77 	}
78 
79 	return NULL;
80 }
81 
82 /*
83  * Copy out a node to userland, using the exchange format for nodes (namely,
84  * a sysctlnode structure).  Return the size of the object that is (or, if the
85  * node falls outside the requested data range, would be) copied out on
86  * success, or a negative error code on failure.  The function may return 0
87  * to indicate that nothing was copied out after all (this is unused here).
88  */
89 static ssize_t
90 mib_copyout_node(struct mib_call * call, struct mib_oldp * oldp, size_t off,
91 	int id, const struct mib_node * node)
92 {
93 	struct sysctlnode scn;
94 	int visible;
95 
96 	if (!mib_inrange(oldp, off))
97 		return sizeof(scn); /* nothing to do */
98 
99 	memset(&scn, 0, sizeof(scn));
100 
101 	/*
102 	 * We use CTLFLAG_PARENT and CTLFLAG_VERIFY internally only.  NetBSD
103 	 * uses the values of these flags for different purposes.  Either way,
104 	 * do not expose them to userland.
105 	 */
106 	scn.sysctl_flags = SYSCTL_VERSION |
107 	    (node->node_flags & ~(CTLFLAG_PARENT | CTLFLAG_VERIFY));
108 	scn.sysctl_num = id;
109 	strlcpy(scn.sysctl_name, node->node_name, sizeof(scn.sysctl_name));
110 	scn.sysctl_ver = node->node_ver;
111 	scn.sysctl_size = node->node_size;
112 
113 	/* Some information is only visible if the user can access the node. */
114 	visible = (!(node->node_flags & CTLFLAG_PRIVATE) || mib_authed(call));
115 
116 	/*
117 	 * For immediate types, store the immediate value in the resulting
118 	 * structure, unless the caller is not authorized to obtain the value.
119 	 */
120 	if ((node->node_flags & CTLFLAG_IMMEDIATE) && visible) {
121 		switch (SYSCTL_TYPE(node->node_flags)) {
122 		case CTLTYPE_BOOL:
123 			scn.sysctl_bdata = node->node_bool;
124 			break;
125 		case CTLTYPE_INT:
126 			scn.sysctl_idata = node->node_int;
127 			break;
128 		case CTLTYPE_QUAD:
129 			scn.sysctl_qdata = node->node_quad;
130 		}
131 	}
132 
133 	/* Special rules apply to parent nodes. */
134 	if (SYSCTL_TYPE(node->node_flags) == CTLTYPE_NODE) {
135 		/* Report the node size the way NetBSD does, just in case. */
136 		scn.sysctl_size = sizeof(scn);
137 
138 		/* If this is a real parent node, report child information. */
139 		if ((node->node_flags & CTLFLAG_PARENT) && visible) {
140 			scn.sysctl_csize = node->node_csize;
141 			scn.sysctl_clen = node->node_clen;
142 		}
143 
144 		/*
145 		 * If this is a function-driven node, indicate this by setting
146 		 * a nonzero function address.  This allows trace(1) to
147 		 * determine that it should not attempt to descend into this
148 		 * part of the tree as usual, because a) accessing subnodes may
149 		 * have side effects, and b) meta-identifiers may not work as
150 		 * expected in these parts of the tree.  Do not return the real
151 		 * function pointer, as this would leak anti-ASR information.
152 		 */
153 		if (!(node->node_flags & CTLFLAG_PARENT))
154 			scn.sysctl_func = SYSCTL_NODE_FN;
155 	}
156 
157 	/* Copy out the resulting node. */
158 	return mib_copyout(oldp, off, &scn, sizeof(scn));
159 }
160 
161 /*
162  * Given a query on a non-leaf (parent) node, provide the user with an array of
163  * this node's children.
164  */
165 static ssize_t
166 mib_query(struct mib_call * call, struct mib_node * parent,
167 	struct mib_oldp * oldp, struct mib_newp * newp, struct mib_node * root)
168 {
169 	struct sysctlnode scn;
170 	struct mib_node *node;
171 	struct mib_dynode *dynode;
172 	size_t off;
173 	int r, id;
174 
175 	/* If the user passed in version numbers, check them. */
176 	if (newp != NULL) {
177 		if ((r = mib_copyin(newp, &scn, sizeof(scn))) != OK)
178 			return r;
179 
180 		if (SYSCTL_VERS(scn.sysctl_flags) != SYSCTL_VERSION)
181 			return EINVAL;
182 
183 		/*
184 		 * If a node version number is given, it must match the version
185 		 * of the parent or the root.
186 		 */
187 		if (scn.sysctl_ver != 0 && scn.sysctl_ver != root->node_ver &&
188 		    scn.sysctl_ver != parent->node_ver)
189 			return EINVAL;
190 	}
191 
192 	/*
193 	 * We need not return the nodes strictly in ascending order of
194 	 * identifiers, as this is not expected by userland.  For example,
195 	 * sysctlgetmibinfo(3) performs its own sorting after a query.
196 	 * Thus, we can go through the static and dynamic nodes separately.
197 	 */
198 	off = 0;
199 
200 	/* First enumerate the static nodes. */
201 	for (id = 0; IS_STATIC_ID(parent, id); id++) {
202 		node = &parent->node_scptr[id];
203 
204 		if (node->node_flags == 0)
205 			continue;
206 
207 		if ((r = mib_copyout_node(call, oldp, off, id, node)) < 0)
208 			return r;
209 		off += r;
210 	}
211 
212 	/* Then enumerate the dynamic nodes. */
213 	for (dynode = parent->node_dcptr; dynode != NULL;
214 	    dynode = dynode->dynode_next) {
215 		node = &dynode->dynode_node;
216 
217 		if ((r = mib_copyout_node(call, oldp, off, dynode->dynode_id,
218 		    node)) < 0)
219 			return r;
220 		off += r;
221 	}
222 
223 	return off;
224 }
225 
226 /*
227  * Scan a parent node's children, as part of new node creation.  Search for
228  * either a free node identifier (if given_id < 0) or collisions with the node
229  * identifier to use (if given_id >= 0).  Also check for name collisions.  Upon
230  * success, return OK, with the resulting node identifier stored in 'idp' and a
231  * pointer to the pointer for the new dynamic node stored in 'prevpp'.  Upon
232  * failure, return an error code.  If the failure is EEXIST, 'idp' will contain
233  * the ID of the conflicting node, and 'nodep' will point to the node.
234  */
235 static int
236 mib_scan(struct mib_node * parent, int given_id, const char * name, int * idp,
237 	struct mib_dynode *** prevpp, struct mib_node ** nodep)
238 {
239 	struct mib_dynode **prevp, **dynp;
240 	struct mib_node *node;
241 	int id;
242 
243 	/*
244 	 * We must verify that no entry already exists with the given name.  In
245 	 * addition, if a nonnegative identifier is given, we should use that
246 	 * identifier and make sure it does not already exist.  Otherwise, we
247 	 * must find a free identifier.  Finally, we sort the dynamic nodes in
248 	 * ascending identifier order, so we must find the right place at which
249 	 * to insert the new node.
250 	 *
251 	 * For finding a free identifier, choose an ID that falls (well)
252 	 * outside the static range, both to avoid accidental retrieval by an
253 	 * application that uses a static ID, and to simplify verifying that
254 	 * the ID is indeed free.  The sorting of dynamic nodes by identifier
255 	 * ensures that searching for a free identifier is O(n).
256 	 *
257 	 * At this time, we do not support some NetBSD features.  We do not
258 	 * force success if the new node is sufficiently like an existing one.
259 	 * Also, we do not use global autoincrement for dynamic identifiers,
260 	 * although that could easily be changed.
261 	 */
262 
263 	/* First check the static node array, just for collisions. */
264 	for (id = 0; IS_STATIC_ID(parent, id); id++) {
265 		node = &parent->node_scptr[id];
266 		if (node->node_flags == 0)
267 			continue;
268 		if (id == given_id || !strcmp(name, node->node_name)) {
269 			*idp = id;
270 			*nodep = node;
271 			return EEXIST;
272 		}
273 	}
274 
275 	/*
276 	 * Then try to find the place to insert a new dynamic node.  At the
277 	 * same time, check for both identifier and name collisions.
278 	 */
279 	if (given_id >= 0)
280 		id = given_id;
281 	else
282 		id = MAX(CREATE_BASE, parent->node_size);
283 
284 	for (prevp = &parent->node_dcptr; *prevp != NULL;
285 	    prevp = &((*prevp)->dynode_next)) {
286 		if ((*prevp)->dynode_id > id)
287 			break;
288 		if ((*prevp)->dynode_id == id) {
289 			if (given_id >= 0) {
290 				*idp = id;
291 				*nodep = &(*prevp)->dynode_node;
292 				return EEXIST;
293 			} else
294 				id++;
295 		}
296 		if (!strcmp(name, (*prevp)->dynode_node.node_name)) {
297 			*idp = (*prevp)->dynode_id;
298 			*nodep = &(*prevp)->dynode_node;
299 			return EEXIST;
300 		}
301 	}
302 
303 	/* Finally, check the rest of the dynamic nodes for name collisions. */
304 	for (dynp = prevp; *dynp != NULL; dynp = &((*dynp)->dynode_next)) {
305 		assert((*dynp)->dynode_id > id);
306 
307 		if (!strcmp(name, (*dynp)->dynode_node.node_name)) {
308 			*idp = (*dynp)->dynode_id;
309 			*nodep = &(*dynp)->dynode_node;
310 			return EEXIST;
311 		}
312 	}
313 
314 	*idp = id;
315 	*prevpp = prevp;
316 	return OK;
317 }
318 
319 /*
320  * Copy in a string from the user process, located at the given remote address,
321  * into the given local buffer.  If no buffer is given, just compute the length
322  * of the string.  On success, return OK.  If 'sizep' is not NULL, it will be
323  * filled with the string size, including the null terminator.  If a non-NULL
324  * buffer was given, the string will be copied into the provided buffer (also
325  * including null terminator).  Return an error code on failure, which includes
326  * the case that no null terminator was found within the range of bytes that
327  * would fit in the given buffer.
328  */
329 static int
330 mib_copyin_str(struct mib_newp * __restrict newp, vir_bytes addr,
331 	char * __restrict buf, size_t bufsize, size_t * __restrict sizep)
332 {
333 	char *ptr, *endp;
334 	size_t chunk, len;
335 	int r;
336 
337 	assert(newp != NULL);
338 	assert(bufsize <= SSIZE_MAX);
339 
340 	if (addr == 0)
341 		return EINVAL;
342 
343 	/*
344 	 * NetBSD has a kernel routine for copying in a string from userland.
345 	 * MINIX3 does not, since its system call interface has always relied
346 	 * on userland passing in string lengths.  The sysctl(2) API does not
347 	 * provide the string length, and thus, we have to do a bit of guess
348 	 * work.  If we copy too little at once, performance suffers.  If we
349 	 * copy too much at once, we may trigger an unneeded page fault.  Make
350 	 * use of page boundaries to strike a balance between those two.  If we
351 	 * are requested to just get the string length, use the scratch buffer.
352 	 */
353 	len = 0;
354 
355 	while (bufsize > 0) {
356 		chunk = PAGE_SIZE - (addr % PAGE_SIZE);
357 		if (chunk > bufsize)
358 			chunk = bufsize;
359 
360 		ptr = (buf != NULL) ? &buf[len] : scratch;
361 		if ((r = mib_copyin_aux(newp, addr, ptr, chunk)) != OK)
362 			return r;
363 
364 		if ((endp = memchr(ptr, '\0', chunk)) != NULL) {
365 			/* A null terminator was found - success. */
366 			if (sizep != NULL)
367 				*sizep = len + (size_t)(endp - ptr) + 1;
368 			return OK;
369 		}
370 
371 		addr += chunk;
372 		len += chunk;
373 		bufsize -= chunk;
374 	}
375 
376 	/* No null terminator found. */
377 	return EINVAL;
378 }
379 
380 /*
381  * Increase the version of the root node, and copy this new version to all
382  * nodes on the path to a node, as well as (optionally) that node itself.
383  */
384 static void
385 mib_upgrade(struct mib_node ** stack, int depth, struct mib_node * node)
386 {
387 	uint32_t ver;
388 
389 	/*
390 	 * The bottom of the stack is always the root node, which determines
391 	 * the version of the entire tree.  Do not use version number 0, as a
392 	 * zero version number indicates no interest in versions elsewhere.
393 	 */
394 	assert(depth > 0);
395 
396 	ver = stack[0]->node_ver + 1;
397 	if (ver == 0)
398 		ver = 1;
399 
400 	/* Copy the new version to all the nodes on the path. */
401 	while (depth-- > 0)
402 		stack[depth]->node_ver = ver;
403 
404 	if (node != NULL)
405 		node->node_ver = stack[0]->node_ver;
406 }
407 
408 /*
409  * Create a node.
410  */
411 static ssize_t
412 mib_create(struct mib_call * call, struct mib_node * parent,
413 	struct mib_oldp * oldp, struct mib_newp * newp,
414 	struct mib_node ** stack, int depth)
415 {
416 	struct mib_dynode *dynode, **prevp;
417 	struct mib_node *node;
418 	struct sysctlnode scn;
419 	size_t namelen, size;
420 	ssize_t len;
421 	bool b;
422 	char c;
423 	int r, id;
424 
425 	/* This is a privileged operation. */
426 	if (!mib_authed(call))
427 		return EPERM;
428 
429 	/* The parent node must not be marked as read-only. */
430 	if (!(parent->node_flags & CTLFLAG_READWRITE))
431 		return EPERM;
432 
433 	/*
434 	 * Has the parent reached its child node limit?  This check is entirely
435 	 * theoretical as long as we support only 32-bit virtual memory.
436 	 */
437 	if (parent->node_csize == INT_MAX)
438 		return EINVAL;
439 	assert(parent->node_clen <= parent->node_csize);
440 
441 	/* The caller must supply information on the child node to create. */
442 	if (newp == NULL)
443 		return EINVAL;
444 
445 	if ((r = mib_copyin(newp, &scn, sizeof(scn))) != OK)
446 		return r;
447 
448 	/*
449 	 * We perform as many checks as possible before we start allocating
450 	 * memory.  Then again, after allocation, copying in data may still
451 	 * fail.  Unlike when setting values, we do not first copy data into a
452 	 * temporary buffer here, because we do not need to: if the copy fails,
453 	 * the entire create operation fails, so atomicity is not an issue.
454 	 */
455 	if (SYSCTL_VERS(scn.sysctl_flags) != SYSCTL_VERSION)
456 		return EINVAL;
457 
458 	/*
459 	 * If a node version number is given, it must match the version of the
460 	 * parent or the root (which is always the bottom of the node stack).
461 	 * The given version number is *not* used for the node being created.
462 	 */
463 	assert(depth > 0);
464 
465 	if (scn.sysctl_ver != 0 && scn.sysctl_ver != stack[0]->node_ver &&
466 	    scn.sysctl_ver != parent->node_ver)
467 		return EINVAL;
468 
469 	/*
470 	 * Validate the node flags.  In addition to the NetBSD-allowed flags,
471 	 * we also allow UNSIGNED, and leave its interpretation to userland.
472 	 */
473 	if (SYSCTL_FLAGS(scn.sysctl_flags) &
474 	    ~(SYSCTL_USERFLAGS | CTLFLAG_UNSIGNED))
475 		return EINVAL;
476 
477 	if (!(scn.sysctl_flags & CTLFLAG_IMMEDIATE)) {
478 		/*
479 		 * Without either IMMEDIATE or OWNDATA, data pointers are
480 		 * actually kernel addresses--a concept we do not support.
481 		 * Otherwise, if IMMEDIATE is not set, we are going to have to
482 		 * allocate extra memory for the data, so force OWNDATA to be.
483 		 * set.  Node-type nodes have no data, though.
484 		 */
485 		if (SYSCTL_TYPE(scn.sysctl_flags) != CTLTYPE_NODE) {
486 			if (!(scn.sysctl_flags & CTLFLAG_OWNDATA) &&
487 			    scn.sysctl_data != NULL)
488 				return EINVAL; /* not meaningful on MINIX3 */
489 
490 			scn.sysctl_flags |= CTLFLAG_OWNDATA;
491 		}
492 	} else if (scn.sysctl_flags & CTLFLAG_OWNDATA)
493 		return EINVAL;
494 
495 	/* The READWRITE flag consists of multiple bits.  Sanitize. */
496 	if (scn.sysctl_flags & CTLFLAG_READWRITE)
497 		scn.sysctl_flags |= CTLFLAG_READWRITE;
498 
499 	/* Validate the node type and size, and do some additional checks. */
500 	switch (SYSCTL_TYPE(scn.sysctl_flags)) {
501 	case CTLTYPE_BOOL:
502 		if (scn.sysctl_size != sizeof(bool))
503 			return EINVAL;
504 		break;
505 	case CTLTYPE_INT:
506 		if (scn.sysctl_size != sizeof(int))
507 			return EINVAL;
508 		break;
509 	case CTLTYPE_QUAD:
510 		if (scn.sysctl_size != sizeof(u_quad_t))
511 			return EINVAL;
512 		break;
513 	case CTLTYPE_STRING:
514 		/*
515 		 * For strings, a zero length means that we are supposed to
516 		 * allocate a buffer size based on the given string size.
517 		 */
518 		if (scn.sysctl_size == 0 && scn.sysctl_data != NULL) {
519 			if ((r = mib_copyin_str(newp,
520 			    (vir_bytes)scn.sysctl_data, NULL, SSIZE_MAX,
521 			    &size)) != OK)
522 				return r;
523 			scn.sysctl_size = size;
524 		}
525 		/* FALLTHROUGH */
526 	case CTLTYPE_STRUCT:
527 		/*
528 		 * We do not set an upper size on the data size, since it would
529 		 * still be possible to create a large number of nodes, and
530 		 * this is a privileged operation ayway.
531 		 */
532 		if (scn.sysctl_size == 0 || scn.sysctl_size > SSIZE_MAX)
533 			return EINVAL;
534 		if (scn.sysctl_flags & CTLFLAG_IMMEDIATE)
535 			return EINVAL;
536 		break;
537 	case CTLTYPE_NODE:
538 		/*
539 		 * The zero size is an API requirement, but we also rely on the
540 		 * zero value internally, as the node has no static children.
541 		 */
542 		if (scn.sysctl_size != 0)
543 			return EINVAL;
544 		if (scn.sysctl_flags & (CTLFLAG_IMMEDIATE | CTLFLAG_OWNDATA))
545 			return EINVAL;
546 		if (scn.sysctl_csize != 0 || scn.sysctl_clen != 0 ||
547 		    scn.sysctl_child != NULL)
548 			return EINVAL;
549 		break;
550 	default:
551 		return EINVAL;
552 	}
553 
554 	if (scn.sysctl_func != NULL || scn.sysctl_parent != NULL)
555 		return EINVAL;
556 
557 	/* Names must be nonempty, null terminated, C symbol style strings. */
558 	for (namelen = 0; namelen < sizeof(scn.sysctl_name); namelen++) {
559 		if ((c = scn.sysctl_name[namelen]) == '\0')
560 			break;
561 		/* A-Z, a-z, 0-9, _ only, and no digit as first character. */
562 		if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
563 		    c == '_' || (c >= '0' && c <= '9' && namelen > 0)))
564 			return EINVAL;
565 	}
566 	if (namelen == 0 || namelen == sizeof(scn.sysctl_name))
567 		return EINVAL;
568 
569 	/*
570 	 * Find a free identifier, or check for ID collisions if a specific
571 	 * identifier was given.  At the same time, scan for name collisions,
572 	 * and find the location at which to insert the new node in the list.
573 	 */
574 	r = mib_scan(parent, scn.sysctl_num, scn.sysctl_name, &id, &prevp,
575 	    &node);
576 
577 	if (r != OK) {
578 		/*
579 		 * On collisions, if requested, copy out the existing node.
580 		 * This does not quite fit the general interaction model, as
581 		 * the service must now return a nonzero old length from a call
582 		 * that actually failed (in contrast to ENOMEM failures).
583 		 */
584 		if (r == EEXIST && oldp != NULL) {
585 			len = mib_copyout_node(call, oldp, 0, id, node);
586 
587 			if (len > 0)
588 				mib_setoldlen(call, len);
589 		}
590 
591 		return r;
592 	}
593 
594 	/*
595 	 * All checks so far have passed.  "id" now contains the new node
596 	 * identifier, and "prevp" points to the pointer at which to insert the
597 	 * new node in its parent's linked list of dynamic nodes.
598 	 *
599 	 * We can now attempt to create and initialize a new dynamic node.
600 	 * Allocating nodes this way may cause heavy memory fragmentation over
601 	 * time, but we do not expect the tree to see heavy modification at run
602 	 * time, and the superuser has easier ways to get the MIB service in
603 	 * trouble.  We note that even in low-memory conditions, the MIB
604 	 * service is always able to provide basic functionality.
605 	 */
606 	size = sizeof(*dynode) + namelen;
607 	if (!(scn.sysctl_flags & CTLFLAG_IMMEDIATE))
608 		size += scn.sysctl_size;
609 
610 	if ((dynode = malloc(size)) == NULL)
611 		return EINVAL; /* do not return ENOMEM */
612 	objects++;
613 
614 	/* From here on, we have to free "dynode" before returning an error. */
615 	r = OK;
616 
617 	memset(dynode, 0, sizeof(*dynode)); /* no need to zero all of "size" */
618 	dynode->dynode_id = id;
619 	strlcpy(dynode->dynode_name, scn.sysctl_name, namelen + 1);
620 
621 	node = &dynode->dynode_node;
622 	node->node_flags = scn.sysctl_flags & ~SYSCTL_VERS_MASK;
623 	if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_NODE)
624 		node->node_flags |= CTLFLAG_PARENT;
625 	node->node_size = scn.sysctl_size;
626 	node->node_name = dynode->dynode_name;
627 
628 	/* Initialize the node value. */
629 	if (scn.sysctl_flags & CTLFLAG_IMMEDIATE) {
630 		switch (SYSCTL_TYPE(scn.sysctl_flags)) {
631 		case CTLTYPE_BOOL:
632 			/* Sanitize booleans.  See the C99 _Bool comment. */
633 			memcpy(&c, &scn.sysctl_bdata, sizeof(c));
634 			node->node_bool = (bool)c;
635 			break;
636 		case CTLTYPE_INT:
637 			node->node_int = scn.sysctl_idata;
638 			break;
639 		case CTLTYPE_QUAD:
640 			node->node_quad = scn.sysctl_qdata;
641 			break;
642 		default:
643 			assert(0);
644 		}
645 	} else if (SYSCTL_TYPE(scn.sysctl_flags) != CTLTYPE_NODE) {
646 		node->node_data = dynode->dynode_name + namelen + 1;
647 
648 		/* Did the user supply initial data?  If not, use zeroes. */
649 		if (scn.sysctl_data != NULL) {
650 			/*
651 			 * For strings, do not copy in more than needed.  This
652 			 * is just a nice feature which allows initialization
653 			 * of large string buffers with short strings.
654 			 */
655 			if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_STRING)
656 				r = mib_copyin_str(newp,
657 				    (vir_bytes)scn.sysctl_data,
658 				    node->node_data, scn.sysctl_size, NULL);
659 			else
660 				r = mib_copyin_aux(newp,
661 				    (vir_bytes)scn.sysctl_data,
662 				    node->node_data, scn.sysctl_size);
663 		} else
664 			memset(node->node_data, 0, scn.sysctl_size);
665 
666 		/*
667 		 * Sanitize booleans.  See the C99 _Bool comment elsewhere.
668 		 * In this case it is not as big of a deal, as we will not be
669 		 * accessing the boolean value directly ourselves.
670 		 */
671 		if (r == OK && SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_BOOL) {
672 			b = (bool)*(char *)node->node_data;
673 			memcpy(node->node_data, &b, sizeof(b));
674 		}
675 	}
676 
677 	/*
678 	 * Even though it would be entirely possible to set a description right
679 	 * away as well, this does not seem to be supported on NetBSD at all.
680 	 */
681 
682 	/* Deal with earlier failures now. */
683 	if (r != OK) {
684 		free(dynode);
685 		objects--;
686 
687 		return r;
688 	}
689 
690 	/* At this point, actual creation can no longer fail. */
691 
692 	/* Link the dynamic node into the list, in the right place. */
693 	assert(prevp != NULL);
694 	dynode->dynode_next = *prevp;
695 	*prevp = dynode;
696 
697 	/* The parent node now has one more child. */
698 	parent->node_csize++;
699 	parent->node_clen++;
700 
701 	nodes++;
702 
703 	/*
704 	 * Bump the version of all nodes on the path to the new node, including
705 	 * the node itself.
706 	 */
707 	mib_upgrade(stack, depth, node);
708 
709 	/*
710 	 * Copy out the newly created node as resulting ("old") data.  Do not
711 	 * undo the creation if this fails, though.
712 	 */
713 	return mib_copyout_node(call, oldp, 0, id, node);
714 }
715 
716 /*
717  * Destroy a node.
718  */
719 static ssize_t
720 mib_destroy(struct mib_call * call, struct mib_node * parent,
721 	struct mib_oldp * oldp, struct mib_newp * newp,
722 	struct mib_node ** stack, int depth)
723 {
724 	struct mib_dynode *dynode, **prevp;
725 	struct mib_node *node;
726 	struct sysctlnode scn;
727 	ssize_t r;
728 
729 	/* This is a privileged operation. */
730 	if (!mib_authed(call))
731 		return EPERM;
732 
733 	/* The parent node must not be marked as read-only. */
734 	if (!(parent->node_flags & CTLFLAG_READWRITE))
735 		return EPERM;
736 
737 	/* The caller must specify which child node to destroy. */
738 	if (newp == NULL)
739 		return EINVAL;
740 
741 	if ((r = mib_copyin(newp, &scn, sizeof(scn))) != OK)
742 		return r;
743 
744 	if (SYSCTL_VERS(scn.sysctl_flags) != SYSCTL_VERSION)
745 		return EINVAL;
746 
747 	/* Locate the child node. */
748 	if ((node = mib_find(parent, scn.sysctl_num, &prevp)) == NULL)
749 		return ENOENT;
750 
751 	/* The node must not be marked as permanent. */
752 	if (node->node_flags & CTLFLAG_PERMANENT)
753 		return EPERM;
754 
755 	/* For node-type nodes, extra rules apply. */
756 	if (SYSCTL_TYPE(node->node_flags) == CTLTYPE_NODE) {
757 		/* The node must not have an associated function. */
758 		if (!(node->node_flags & CTLFLAG_PARENT))
759 			return EPERM;
760 
761 		/* The target node must itself not have child nodes. */
762 		if (node->node_clen != 0)
763 			return ENOTEMPTY;
764 	}
765 
766 	/* If the user supplied a version, it must match the node version. */
767 	if (scn.sysctl_ver != 0 && scn.sysctl_ver != node->node_ver)
768 		return EINVAL;	/* NetBSD inconsistently throws ENOENT here */
769 
770 	/* If the user supplied a name, it must match the node name. */
771 	if (scn.sysctl_name[0] != '\0') {
772 		if (memchr(scn.sysctl_name, '\0',
773 		    sizeof(scn.sysctl_name)) == NULL)
774 			return EINVAL;
775 		if (strcmp(scn.sysctl_name, node->node_name))
776 			return EINVAL;	/* also ENOENT on NetBSD */
777 	}
778 
779 	/*
780 	 * Copy out the old node if requested, otherwise return the length
781 	 * anyway.  The node will be destroyed even if this call fails,
782 	 * because that is how NetBSD behaves.
783 	 */
784 	r = mib_copyout_node(call, oldp, 0, scn.sysctl_num, node);
785 
786 	/* If the description was allocated, free it. */
787 	if (node->node_flags & CTLFLAG_OWNDESC) {
788 		free(__UNCONST(node->node_desc));
789 		objects--;
790 	}
791 
792 	/*
793 	 * Static nodes only use static memory, and dynamic nodes have the data
794 	 * area embedded in the dynode object.  In neither case is data memory
795 	 * allocated separately, and thus, it need never be freed separately.
796 	 * Therefore we *must not* check CTLFLAG_OWNDATA here.
797 	 */
798 
799 	assert(parent->node_csize > 0);
800 	assert(parent->node_clen > 0);
801 
802 	/*
803 	 * Dynamic nodes must be freed.  Freeing the dynode object also frees
804 	 * the node name and any associated data.  Static nodes are zeroed out,
805 	 * and the static memory they referenced will become inaccessible.
806 	 */
807 	if (prevp != NULL) {
808 		dynode = *prevp;
809 		*prevp = dynode->dynode_next;
810 
811 		free(dynode);
812 		objects--;
813 
814 		parent->node_csize--;
815 	} else
816 		memset(node, 0, sizeof(*node));
817 
818 	parent->node_clen--;
819 
820 	nodes--;
821 
822 	/* Bump the version of all nodes on the path to the destroyed node. */
823 	mib_upgrade(stack, depth, NULL);
824 
825 	return r;
826 }
827 
828 /*
829  * Copy out a node description to userland, using the exchange format for node
830  * descriptions (namely, a sysctldesc structure).  Return the size of the
831  * object that is (or, if the description falls outside the requested data
832  * range, would be) copied out on success, or a negative error code on failure.
833  * The function may return 0 to indicate that nothing was copied out after all.
834  */
835 static ssize_t
836 mib_copyout_desc(struct mib_call * call, struct mib_oldp * oldp, size_t off,
837 	int id, const struct mib_node * node)
838 {
839 	struct sysctldesc *scd;
840 	size_t size;
841 	int r;
842 
843 	/* Descriptions of private nodes are considered private too. */
844 	if ((node->node_flags & CTLFLAG_PRIVATE) && !mib_authed(call))
845 		return 0;
846 
847 	/* The description length includes the null terminator. */
848 	if (node->node_desc != NULL)
849 		size = strlen(node->node_desc) + 1;
850 	else
851 		size = 1;
852 
853 	assert(sizeof(*scd) + size <= sizeof(scratch));
854 
855 	scd = (struct sysctldesc *)scratch;
856 	memset(scd, 0, sizeof(*scd));
857 	scd->descr_num = id;
858 	scd->descr_ver = node->node_ver;
859 	scd->descr_len = size;
860 	if (node->node_desc != NULL)
861 		strlcpy(scd->descr_str, node->node_desc,
862 		    sizeof(scratch) - sizeof(*scd));
863 	else
864 		scd->descr_str[0] = '\0';
865 
866 	size += offsetof(struct sysctldesc, descr_str);
867 
868 	if ((r = mib_copyout(oldp, off, scratch, size)) < 0)
869 		return r;
870 
871 	/*
872 	 * By aligning just the size, we may leave garbage between the entries
873 	 * copied out, which is fine because it is userland's own data.
874 	 */
875 	return roundup2(size, sizeof(int32_t));
876 }
877 
878 /*
879  * Retrieve node descriptions in bulk, or retrieve or assign a particular
880  * node's description.
881  */
882 static ssize_t
883 mib_describe(struct mib_call * call, struct mib_node * parent,
884 	struct mib_oldp * oldp, struct mib_newp * newp)
885 {
886 	struct sysctlnode scn;
887 	struct mib_node *node;
888 	struct mib_dynode *dynode;
889 	size_t off;
890 	int r, id;
891 
892 	/* If new data are given, they identify a particular target node. */
893 	if (newp != NULL) {
894 		if ((r = mib_copyin(newp, &scn, sizeof(scn))) != OK)
895 			return r;
896 
897 		if (SYSCTL_VERS(scn.sysctl_flags) != SYSCTL_VERSION)
898 			return EINVAL;
899 
900 		/* Locate the child node. */
901 		if ((node = mib_find(parent, scn.sysctl_num, NULL)) == NULL)
902 			return ENOENT;
903 
904 		/* Descriptions of private nodes are considered private too. */
905 		if ((node->node_flags & CTLFLAG_PRIVATE) && !mib_authed(call))
906 			return EPERM;
907 
908 		/*
909 		 * If a description pointer was given, this is a request to
910 		 * set the node's description.
911 		 */
912 		if (scn.sysctl_desc != NULL) {
913 			/* Such a request requires superuser privileges. */
914 			if (!mib_authed(call))
915 				return EPERM;
916 
917 			/* The node must not already have a description. */
918 			if (node->node_desc != NULL)
919 				return EPERM;
920 
921 			/* The node must not be marked as permanent. */
922 			if (node->node_flags & CTLFLAG_PERMANENT)
923 				return EPERM;
924 
925 			/*
926 			 * If the user supplied a version, it must match.
927 			 * NetBSD performs this check only when setting
928 			 * descriptions, and thus, so do we..
929 			 */
930 			if (scn.sysctl_ver != 0 &&
931 			    scn.sysctl_ver != node->node_ver)
932 				return EINVAL;
933 
934 			/*
935 			 * Copy in the description to the scratch buffer.
936 			 * The length of the description must be reasonable.
937 			 */
938 			if ((r = mib_copyin_str(newp,
939 			    (vir_bytes)scn.sysctl_desc, scratch, MAXDESCLEN,
940 			    NULL)) != OK)
941 				return r;
942 
943 			/* Allocate memory and store the description. */
944 			if ((node->node_desc = strdup(scratch)) == NULL) {
945 				printf("MIB: out of memory!\n");
946 
947 				return EINVAL; /* do not return ENOMEM */
948 			}
949 			objects++;
950 
951 			/* The description must now be freed with the node. */
952 			node->node_flags |= CTLFLAG_OWNDESC;
953 		}
954 
955 		/*
956 		 * Either way, copy out the requested node's description, which
957 		 * should indeed be the new description if one was just set.
958 		 * Note that we have already performed the permission check
959 		 * that could make this call return zero, so here it will not.
960 		 */
961 		return mib_copyout_desc(call, oldp, 0, scn.sysctl_num, node);
962 	}
963 
964 	/* See also the considerations laid out in mib_query(). */
965 	off = 0;
966 
967 	/* First describe the static nodes. */
968 	for (id = 0; IS_STATIC_ID(parent, id); id++) {
969 		node = &parent->node_scptr[id];
970 
971 		if (node->node_flags == 0)
972 			continue;
973 
974 		if ((r = mib_copyout_desc(call, oldp, off, id, node)) < 0)
975 			return r;
976 		off += r;
977 	}
978 
979 	/* Then describe the dynamic nodes. */
980 	for (dynode = parent->node_dcptr; dynode != NULL;
981 	    dynode = dynode->dynode_next) {
982 		node = &dynode->dynode_node;
983 
984 		if ((r = mib_copyout_desc(call, oldp, off, dynode->dynode_id,
985 		    node)) < 0)
986 			return r;
987 		off += r;
988 	}
989 
990 	return off;
991 }
992 
993 /*
994  * Return a pointer to the data associated with the given node, or NULL if the
995  * node has no associated data.  Actual calls to this function should never
996  * result in NULL - as long as the proper rules are followed elsewhere.
997  */
998 static void *
999 mib_getptr(struct mib_node * node)
1000 {
1001 
1002 	switch (SYSCTL_TYPE(node->node_flags)) {
1003 	case CTLTYPE_BOOL:
1004 		if (node->node_flags & CTLFLAG_IMMEDIATE)
1005 			return &node->node_bool;
1006 		break;
1007 	case CTLTYPE_INT:
1008 		if (node->node_flags & CTLFLAG_IMMEDIATE)
1009 			return &node->node_int;
1010 		break;
1011 	case CTLTYPE_QUAD:
1012 		if (node->node_flags & CTLFLAG_IMMEDIATE)
1013 			return &node->node_quad;
1014 		break;
1015 	case CTLTYPE_STRING:
1016 	case CTLTYPE_STRUCT:
1017 		if (node->node_flags & CTLFLAG_IMMEDIATE)
1018 			return NULL;
1019 		break;
1020 	default:
1021 		return NULL;
1022 	}
1023 
1024 	return node->node_data;
1025 }
1026 
1027 /*
1028  * Read current (old) data from a regular data node, if requested.  Return the
1029  * old data length.
1030  */
1031 static ssize_t
1032 mib_read(struct mib_node * node, struct mib_oldp * oldp)
1033 {
1034 	void *ptr;
1035 	size_t oldlen;
1036 	int r;
1037 
1038 	if ((ptr = mib_getptr(node)) == NULL)
1039 		return EINVAL;
1040 
1041 	if (SYSCTL_TYPE(node->node_flags) == CTLTYPE_STRING)
1042 		oldlen = strlen(node->node_data) + 1;
1043 	else
1044 		oldlen = node->node_size;
1045 
1046 	if (oldlen > SSIZE_MAX)
1047 		return EINVAL;
1048 
1049 	/* Copy out the current data, if requested at all. */
1050 	if (oldp != NULL && (r = mib_copyout(oldp, 0, ptr, oldlen)) < 0)
1051 		return r;
1052 
1053 	/* Return the current length in any case. */
1054 	return (ssize_t)oldlen;
1055 }
1056 
1057 /*
1058  * Write new data into a regular data node, if requested.
1059  */
1060 static int
1061 mib_write(struct mib_call * call, struct mib_node * node,
1062 	struct mib_newp * newp, mib_verify_ptr verify)
1063 {
1064 	bool b[(sizeof(bool) == sizeof(char)) ? 1 : -1]; /* explained below */
1065 	char *src, *dst;
1066 	size_t newlen;
1067 	int r;
1068 
1069 	if (newp == NULL)
1070 		return OK; /* nothing to do */
1071 
1072 	/*
1073 	 * When setting a new value, we cannot risk doing an in-place update:
1074 	 * the copy from userland may fail halfway through, in which case an
1075 	 * in-place update could leave the node value in a corrupted state.
1076 	 * Thus, we must first fetch any new data into a temporary buffer.
1077 	 *
1078 	 * Given that we use intermediate data storage, we could support value
1079 	 * swapping, where the user provides the same buffer for new and old
1080 	 * data.  We choose not to: NetBSD does not support it, it would make
1081 	 * trace(1)'s job a lot harder, and it would convolute the code here.
1082 	 */
1083 	newlen = mib_getnewlen(newp);
1084 
1085 	if ((dst = mib_getptr(node)) == NULL)
1086 		return EINVAL;
1087 
1088 	switch (SYSCTL_TYPE(node->node_flags)) {
1089 	case CTLTYPE_STRING:
1090 		/*
1091 		 * Strings must not exceed their buffer size.  There is a
1092 		 * second check further below, because we allow userland to
1093 		 * give us an unterminated string.  In that case we terminate
1094 		 * it ourselves, but then the null terminator must fit as well.
1095 		 */
1096 		if (newlen > node->node_size)
1097 			return EINVAL;
1098 		break;
1099 	case CTLTYPE_BOOL:
1100 	case CTLTYPE_INT:
1101 	case CTLTYPE_QUAD:
1102 	case CTLTYPE_STRUCT:
1103 		/* Non-string types must have an exact size match. */
1104 		if (newlen != node->node_size)
1105 			return EINVAL;
1106 		break;
1107 	default:
1108 		return EINVAL;
1109 	}
1110 
1111 	/*
1112 	 * If we cannot fit the data in the small stack buffer, then allocate a
1113 	 * temporary buffer.  We add one extra byte so that we can add a null
1114 	 * terminator at the end of strings in case userland did not supply
1115 	 * one.  Either way, we must free the temporary buffer later!
1116 	 *
1117 	 * The alternative is to ensure that the given memory is accessible
1118 	 * before starting the copy, but that would break if we ever add kernel
1119 	 * threads or anything that allows asynchronous memory unmapping, etc.
1120 	 */
1121 	if (newlen + 1 > sizeof(scratch)) {
1122 		/*
1123 		 * In practice, the temporary buffer is at least an entire
1124 		 * memory page, which is reasonable by any standard.  As a
1125 		 * result, we can get away with refusing to perform dynamic
1126 		 * allocation for unprivileged users.  This limits the impact
1127 		 * that unprivileged users can have on our memory space.
1128 		 */
1129 		if (!mib_authed(call))
1130 			return EPERM;
1131 
1132 		/*
1133 		 * Do not return ENOMEM on allocation failure, because ENOMEM
1134 		 * implies that a valid old length was returned.
1135 		 */
1136 		if ((src = malloc(newlen + 1)) == NULL) {
1137 			printf("MIB: out of memory!\n");
1138 
1139 			return EINVAL;
1140 		}
1141 		objects++;
1142 	} else
1143 		src = scratch;
1144 
1145 	/* Copy in the data.  Note that newlen may be zero. */
1146 	r = mib_copyin(newp, src, newlen);
1147 
1148 	if (r == OK && verify != NULL && !verify(call, node, src, newlen))
1149 		r = EINVAL;
1150 
1151 	if (r == OK) {
1152 		/* Check and, if acceptable, store the new value. */
1153 		switch (SYSCTL_TYPE(node->node_flags)) {
1154 		case CTLTYPE_BOOL:
1155 			/*
1156 			 * Due to the nature of the C99 _Bool type, we can not
1157 			 * test directly whether the given boolean value is a
1158 			 * value that is not "true" and not "false".  In the
1159 			 * worst case, another value could invoke undefined
1160 			 * behavior.  We try our best to sanitize the value
1161 			 * without looking at it directly, which unfortunately
1162 			 * requires us to test for the size of the bool type.
1163 			 * We do that at compile time, hence the 'b' "array".
1164 			 * Any size other than one byte is an ABI violation.
1165 			 */
1166 			b[0] = (bool)src[0];
1167 			memcpy(dst, &b[0], sizeof(b[0]));
1168 			break;
1169 		case CTLTYPE_INT:
1170 		case CTLTYPE_QUAD:
1171 		case CTLTYPE_STRUCT:
1172 			memcpy(dst, src, node->node_size);
1173 			break;
1174 		case CTLTYPE_STRING:
1175 			if (newlen == node->node_size &&
1176 			    src[newlen - 1] != '\0') {
1177 				/* Our null terminator does not fit! */
1178 				r = EINVAL;
1179 				break;
1180 			}
1181 			/*
1182 			 * We do not mind null characters in the middle.  In
1183 			 * general, the buffer may contain garbage after the
1184 			 * first null terminator, but such garbage will never
1185 			 * end up being copied out.
1186 			 */
1187 			src[newlen] = '\0';
1188 			strlcpy(dst, src, node->node_size);
1189 			break;
1190 		default:
1191 			r = EINVAL;
1192 		}
1193 	}
1194 
1195 	if (src != scratch) {
1196 		free(src);
1197 		objects--;
1198 	}
1199 
1200 	return r;
1201 }
1202 
1203 /*
1204  * Read and/or write the value of a regular data node.  A regular data node is
1205  * a leaf node.  Typically, a leaf node has no associated function, in which
1206  * case this function will be used instead.  In addition, this function may be
1207  * used from handler functions as part of their functionality.
1208  */
1209 ssize_t
1210 mib_readwrite(struct mib_call * call, struct mib_node * node,
1211 	struct mib_oldp * oldp, struct mib_newp * newp, mib_verify_ptr verify)
1212 {
1213 	ssize_t len;
1214 	int r;
1215 
1216 	/* Copy out old data, if requested.  Always get the old data length. */
1217 	if ((r = len = mib_read(node, oldp)) < 0)
1218 		return r;
1219 
1220 	/* Copy in new data, if requested. */
1221 	if ((r = mib_write(call, node, newp, verify)) != OK)
1222 		return r;
1223 
1224 	/* Return the old data length. */
1225 	return len;
1226 }
1227 
1228 /*
1229  * Dispatch a sysctl call, by looking up the target node by its MIB name and
1230  * taking the appropriate action on the resulting node, if found.  Return the
1231  * old data length on success, or a negative error code on failure.
1232  */
1233 ssize_t
1234 mib_dispatch(struct mib_call * call, struct mib_node * root,
1235 	struct mib_oldp * oldp, struct mib_newp * newp)
1236 {
1237 	struct mib_node *stack[CTL_MAXNAME];
1238 	struct mib_node *parent, *node;
1239 	int id, depth, is_leaf, has_verify, has_func;
1240 
1241 	assert(call->call_namelen <= CTL_MAXNAME);
1242 
1243 	/*
1244 	 * Resolve the name by descending into the node tree, level by level,
1245 	 * starting at the MIB root.
1246 	 */
1247 	depth = 0;
1248 
1249 	for (parent = root; call->call_namelen > 0; parent = node) {
1250 		/*
1251 		 * For node creation and destruction, build a node stack, to
1252 		 * allow for up-propagation of new node version numbers.
1253 		 */
1254 		stack[depth++] = parent;
1255 
1256 		id = call->call_name[0];
1257 		call->call_name++;
1258 		call->call_namelen--;
1259 
1260 		assert(SYSCTL_TYPE(parent->node_flags) == CTLTYPE_NODE);
1261 		assert(parent->node_flags & CTLFLAG_PARENT);
1262 
1263 		/*
1264 		 * Check for meta-identifiers.  Regular identifiers are never
1265 		 * negative, although node handler functions may take subpaths
1266 		 * with negative identifiers that are not meta-identifiers
1267 		 * (e.g., see KERN_PROC2).
1268 		 */
1269 		if (id < 0) {
1270 			/*
1271 			 * A meta-identifier must always be the last name
1272 			 * component.
1273 			 */
1274 			if (call->call_namelen > 0)
1275 				return EINVAL;
1276 
1277 			switch (id) {
1278 			case CTL_QUERY:
1279 				return mib_query(call, parent, oldp, newp,
1280 				    root);
1281 			case CTL_CREATE:
1282 				return mib_create(call, parent, oldp, newp,
1283 				    stack, depth);
1284 			case CTL_DESTROY:
1285 				return mib_destroy(call, parent, oldp, newp,
1286 				    stack, depth);
1287 			case CTL_DESCRIBE:
1288 				return mib_describe(call, parent, oldp, newp);
1289 			case CTL_CREATESYM:
1290 			case CTL_MMAP:
1291 			default:
1292 				return EOPNOTSUPP;
1293 			}
1294 		}
1295 
1296 		/* Locate the child node. */
1297 		if ((node = mib_find(parent, id, NULL /*prevp*/)) == NULL)
1298 			return ENOENT;
1299 
1300 		/* Check if access is permitted at this level. */
1301 		if ((node->node_flags & CTLFLAG_PRIVATE) && !mib_authed(call))
1302 			return EPERM;
1303 
1304 		/*
1305 		 * Is this a leaf node, and/or is this node handled by a
1306 		 * function?  If either is true, resolution ends at this level.
1307 		 * In order to save a few bytes of memory per node, we use
1308 		 * different ways to determine whether there is a function
1309 		 * depending on whether the node is a leaf or not.
1310 		 */
1311 		is_leaf = (SYSCTL_TYPE(node->node_flags) != CTLTYPE_NODE);
1312 		if (is_leaf) {
1313 			has_verify = (node->node_flags & CTLFLAG_VERIFY);
1314 			has_func = (!has_verify && node->node_func != NULL);
1315 		} else {
1316 			has_verify = FALSE;
1317 			has_func = !(node->node_flags & CTLFLAG_PARENT);
1318 		}
1319 
1320 		/*
1321 		 * The name may be longer only if the node is not a leaf.  That
1322 		 * also applies to leaves with functions, so check this first.
1323 		 */
1324 		if (is_leaf && call->call_namelen > 0)
1325 			return ENOTDIR;
1326 
1327 		/*
1328 		 * If resolution indeed ends here, and the user supplied new
1329 		 * data, check if writing is allowed.  For functions, it is
1330 		 * arguable whether we should do this check here already.
1331 		 * However, for now, this approach covers all our use cases.
1332 		 */
1333 		if ((is_leaf || has_func) && newp != NULL) {
1334 			if (!(node->node_flags & CTLFLAG_READWRITE))
1335 				return EPERM;
1336 
1337 			/*
1338 			 * Unless nonprivileged users may write to this node,
1339 			 * ensure that the user has superuser privileges.  The
1340 			 * ANYWRITE flag does not override the READWRITE flag.
1341 			 */
1342 			if (!(node->node_flags & CTLFLAG_ANYWRITE) &&
1343 			    !mib_authed(call))
1344 				return EPERM;
1345 		}
1346 
1347 		/* If this node has a handler function, let it do the work. */
1348 		if (has_func)
1349 			return node->node_func(call, node, oldp, newp);
1350 
1351 		/* For regular data leaf nodes, handle generic access. */
1352 		if (is_leaf)
1353 			return mib_readwrite(call, node, oldp, newp,
1354 			    has_verify ? node->node_verify : NULL);
1355 
1356 		/* No function and not a leaf?  Descend further. */
1357 	}
1358 
1359 	/* If we get here, the name refers to a node array. */
1360 	return EISDIR;
1361 }
1362 
1363 /*
1364  * Recursively initialize the static tree at initialization time.
1365  */
1366 static void
1367 mib_tree_recurse(struct mib_node * parent)
1368 {
1369 	struct mib_node *node;
1370 	int id;
1371 
1372 	assert(SYSCTL_TYPE(parent->node_flags) == CTLTYPE_NODE);
1373 	assert(parent->node_flags & CTLFLAG_PARENT);
1374 
1375 	/*
1376 	 * Later on, node_csize and node_clen will also include dynamically
1377 	 * created nodes.  This means that we cannot use node_csize to iterate
1378 	 * over the static nodes.
1379 	 */
1380 	parent->node_csize = parent->node_size;
1381 
1382 	node = parent->node_scptr;
1383 
1384 	for (id = 0; IS_STATIC_ID(parent, id); id++, node++) {
1385 		if (node->node_flags == 0)
1386 			continue;
1387 
1388 		nodes++;
1389 
1390 		parent->node_clen++;
1391 
1392 		node->node_ver = parent->node_ver;
1393 
1394 		/* Recursively apply this function to all node children. */
1395 		if (SYSCTL_TYPE(node->node_flags) == CTLTYPE_NODE &&
1396 		    (node->node_flags & CTLFLAG_PARENT))
1397 			mib_tree_recurse(node);
1398 	}
1399 }
1400 
1401 /*
1402  * Go through the entire static tree, recursively, initializing some values
1403  * that could not be assigned at compile time.
1404  */
1405 void
1406 mib_tree_init(struct mib_node * root)
1407 {
1408 
1409 	/* Initialize some variables. */
1410 	nodes = 1; /* the root node itself */
1411 	objects = 0;
1412 
1413 	/* The entire tree starts with the same, nonzero node version. */
1414 	root->node_ver = 1;
1415 
1416 	/* Recursively initialize the static tree. */
1417 	mib_tree_recurse(root);
1418 }
1419