1 /* MIB service - tree.c - tree access and management */
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.
12 #define IS_STATIC_ID(parent, id) ((unsigned int)(id) < (parent)->node_size)
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().
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));
25 unsigned int mib_nodes
; /* how many nodes are there in the tree? */
26 unsigned int mib_objects
; /* how many memory objects are allocated? */
27 unsigned int mib_remotes
; /* how many remote subtrees are there? */
30 * Find a node through its parent node and identifier. Return the node if it
31 * was found, and optionally store a pointer to the pointer to its dynode
32 * superstructure (for removal). If no matching node was found, return NULL.
34 static struct mib_node
*
35 mib_find(struct mib_node
* parent
, int id
, struct mib_dynode
*** prevpp
)
37 struct mib_node
*node
;
38 struct mib_dynode
**dynp
;
44 * Is there a static node with this identifier? The static nodes are
45 * all in a single array, so lookup is O(1) for these nodes. We use
46 * the node flags field to see whether the array entry is valid.
48 if (IS_STATIC_ID(parent
, id
)) {
49 node
= &parent
->node_scptr
[id
];
51 if (node
->node_flags
!= 0) {
52 /* Found a matching static node. */
60 * Is there a dynamic node with this identifier? The dynamic nodes
61 * form a linked list. This is predominantly because userland may pick
62 * the identifier number at creation time, so we cannot rely on all
63 * dynamically created nodes falling into a small identifier range.
64 * That eliminates the option of a dynamic array indexed by identifier,
65 * and a linked list is the simplest next option. Thus, dynamic node
66 * lookup is O(n). However, since the list is sorted by identifier,
67 * we may be able to stop the search early.
69 for (dynp
= &parent
->node_dcptr
; *dynp
!= NULL
;
70 dynp
= &((*dynp
)->dynode_next
)) {
71 if ((*dynp
)->dynode_id
== id
) {
72 /* Found a matching dynamic node. */
75 return &(*dynp
)->dynode_node
;
76 } else if ((*dynp
)->dynode_id
> id
)
77 break; /* no need to look further */
84 * Copy out a node to userland, using the exchange format for nodes (namely,
85 * a sysctlnode structure). Return the size of the object that is (or, if the
86 * node falls outside the requested data range, would be) copied out on
87 * success, or a negative error code on failure. The function may return 0
88 * to indicate that nothing was copied out after all (this is unused here).
91 mib_copyout_node(struct mib_call
* call
, struct mib_oldp
* oldp
, size_t off
,
92 int id
, const struct mib_node
* node
)
94 struct sysctlnode scn
;
97 if (!mib_inrange(oldp
, off
))
98 return sizeof(scn
); /* nothing to do */
100 memset(&scn
, 0, sizeof(scn
));
103 * We use CTLFLAG_PARENT, CTLFLAG_VERIFY, and CTLFLAG_REMOTE internally
104 * only. NetBSD uses the values of these flags for different purposes.
105 * Either way, do not expose them to userland.
107 scn
.sysctl_flags
= SYSCTL_VERSION
| (node
->node_flags
&
108 ~(CTLFLAG_PARENT
| CTLFLAG_VERIFY
| CTLFLAG_REMOTE
));
110 strlcpy(scn
.sysctl_name
, node
->node_name
, sizeof(scn
.sysctl_name
));
111 scn
.sysctl_ver
= node
->node_ver
;
112 scn
.sysctl_size
= node
->node_size
;
114 /* Some information is only visible if the user can access the node. */
115 visible
= (!(node
->node_flags
& CTLFLAG_PRIVATE
) || mib_authed(call
));
118 * For immediate types, store the immediate value in the resulting
119 * structure, unless the caller is not authorized to obtain the value.
121 if ((node
->node_flags
& CTLFLAG_IMMEDIATE
) && visible
) {
122 switch (SYSCTL_TYPE(node
->node_flags
)) {
124 scn
.sysctl_bdata
= node
->node_bool
;
127 scn
.sysctl_idata
= node
->node_int
;
130 scn
.sysctl_qdata
= node
->node_quad
;
134 /* Special rules apply to parent nodes. */
135 if (SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_NODE
) {
136 /* Report the node size the way NetBSD does, just in case. */
137 scn
.sysctl_size
= sizeof(scn
);
140 * If this is a remote node, use the values we have of the root
141 * of the remote subtree. If we did not have these values, we
142 * would have to call into the remote service here, which for
143 * reliability purposes is a bad idea.
145 * If this is a real parent node, report child information. In
146 * both these cases, expose child information only if the node
147 * itself is accessible by the caller.
149 * If this is a function-driven node, indicate this by setting
150 * a nonzero function address. This allows trace(1) to
151 * determine that it should not attempt to descend into this
152 * part of the tree as usual, because a) accessing subnodes may
153 * have side effects, and b) meta-identifiers may not work as
154 * expected in these parts of the tree. Do not return the real
155 * function pointer, as this would leak anti-ASR information.
157 if (node
->node_flags
& CTLFLAG_REMOTE
) {
159 scn
.sysctl_csize
= node
->node_rcsize
;
160 scn
.sysctl_clen
= node
->node_rclen
;
162 } else if (node
->node_flags
& CTLFLAG_PARENT
) {
164 scn
.sysctl_csize
= node
->node_csize
;
165 scn
.sysctl_clen
= node
->node_clen
;
168 scn
.sysctl_func
= SYSCTL_NODE_FN
;
171 /* Copy out the resulting node. */
172 return mib_copyout(oldp
, off
, &scn
, sizeof(scn
));
176 * Given a query on a non-leaf (parent) node, provide the user with an array of
177 * this node's children.
180 mib_query(struct mib_call
* call
, struct mib_node
* parent
,
181 struct mib_oldp
* oldp
, struct mib_newp
* newp
)
183 struct sysctlnode scn
;
184 struct mib_node
*node
;
185 struct mib_dynode
*dynode
;
189 /* If the user passed in version numbers, check them. */
191 if ((r
= mib_copyin(newp
, &scn
, sizeof(scn
))) != OK
)
194 if (SYSCTL_VERS(scn
.sysctl_flags
) != SYSCTL_VERSION
)
198 * If a node version number is given, it must match the version
199 * of the parent or the root.
201 if (scn
.sysctl_ver
!= 0 &&
202 scn
.sysctl_ver
!= mib_root
.node_ver
&&
203 scn
.sysctl_ver
!= parent
->node_ver
)
208 * We need not return the nodes strictly in ascending order of
209 * identifiers, as this is not expected by userland. For example,
210 * sysctlgetmibinfo(3) performs its own sorting after a query.
211 * Thus, we can go through the static and dynamic nodes separately.
215 /* First enumerate the static nodes. */
216 for (id
= 0; IS_STATIC_ID(parent
, id
); id
++) {
217 node
= &parent
->node_scptr
[id
];
219 if (node
->node_flags
== 0)
222 if ((r
= mib_copyout_node(call
, oldp
, off
, id
, node
)) < 0)
227 /* Then enumerate the dynamic nodes. */
228 for (dynode
= parent
->node_dcptr
; dynode
!= NULL
;
229 dynode
= dynode
->dynode_next
) {
230 node
= &dynode
->dynode_node
;
232 if ((r
= mib_copyout_node(call
, oldp
, off
, dynode
->dynode_id
,
242 * Check whether the given name buffer contains a valid node name string. If
243 * the name is nonempty, properly terminated, and contains only acceptable
244 * characters, return the length of the string excluding null terminator.
245 * Otherwise, return zero to indicate failure.
248 mib_check_name(const char * name
, size_t namesize
)
253 /* Names must be nonempty, null terminated, C symbol style strings. */
254 for (namelen
= 0; namelen
< namesize
; namelen
++) {
255 if ((c
= name
[namelen
]) == '\0')
257 /* A-Z, a-z, 0-9, _ only, and no digit as first character. */
258 if (!((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z') ||
259 c
== '_' || (c
>= '0' && c
<= '9' && namelen
> 0)))
262 if (namelen
== 0 || namelen
== namesize
)
269 * Scan a parent node's children, as part of new node creation. Search for
270 * either a free node identifier (if given_id < 0) or collisions with the node
271 * identifier to use (if given_id >= 0). Also check for name collisions. Upon
272 * success, return OK, with the resulting node identifier stored in 'idp' and a
273 * pointer to the pointer for the new dynamic node stored in 'prevpp'. Upon
274 * failure, return an error code. If the failure is EEXIST, 'idp' will contain
275 * the ID of the conflicting node, and 'nodep' will point to the node.
278 mib_scan(struct mib_node
* parent
, int given_id
, const char * name
, int * idp
,
279 struct mib_dynode
*** prevpp
, struct mib_node
** nodep
)
281 struct mib_dynode
**prevp
, **dynp
;
282 struct mib_node
*node
;
286 * We must verify that no entry already exists with the given name. In
287 * addition, if a nonnegative identifier is given, we should use that
288 * identifier and make sure it does not already exist. Otherwise, we
289 * must find a free identifier. Finally, we sort the dynamic nodes in
290 * ascending identifier order, so we must find the right place at which
291 * to insert the new node.
293 * For finding a free identifier, choose an ID that falls (well)
294 * outside the static range, both to avoid accidental retrieval by an
295 * application that uses a static ID, and to simplify verifying that
296 * the ID is indeed free. The sorting of dynamic nodes by identifier
297 * ensures that searching for a free identifier is O(n).
299 * At this time, we do not support some NetBSD features. We do not
300 * force success if the new node is sufficiently like an existing one.
301 * Also, we do not use global autoincrement for dynamic identifiers,
302 * although that could easily be changed.
305 /* First check the static node array, just for collisions. */
306 for (id
= 0; IS_STATIC_ID(parent
, id
); id
++) {
307 node
= &parent
->node_scptr
[id
];
308 if (node
->node_flags
== 0)
310 if (id
== given_id
|| !strcmp(name
, node
->node_name
)) {
318 * Then try to find the place to insert a new dynamic node. At the
319 * same time, check for both identifier and name collisions.
324 id
= MAX(CREATE_BASE
, parent
->node_size
);
326 for (prevp
= &parent
->node_dcptr
; *prevp
!= NULL
;
327 prevp
= &((*prevp
)->dynode_next
)) {
328 if ((*prevp
)->dynode_id
> id
)
330 if ((*prevp
)->dynode_id
== id
) {
333 *nodep
= &(*prevp
)->dynode_node
;
338 if (!strcmp(name
, (*prevp
)->dynode_node
.node_name
)) {
339 *idp
= (*prevp
)->dynode_id
;
340 *nodep
= &(*prevp
)->dynode_node
;
345 /* Finally, check the rest of the dynamic nodes for name collisions. */
346 for (dynp
= prevp
; *dynp
!= NULL
; dynp
= &((*dynp
)->dynode_next
)) {
347 assert((*dynp
)->dynode_id
> id
);
349 if (!strcmp(name
, (*dynp
)->dynode_node
.node_name
)) {
350 *idp
= (*dynp
)->dynode_id
;
351 *nodep
= &(*dynp
)->dynode_node
;
362 * Copy in a string from the user process, located at the given remote address,
363 * into the given local buffer. If no buffer is given, just compute the length
364 * of the string. On success, return OK. If 'sizep' is not NULL, it will be
365 * filled with the string size, including the null terminator. If a non-NULL
366 * buffer was given, the string will be copied into the provided buffer (also
367 * including null terminator). Return an error code on failure, which includes
368 * the case that no null terminator was found within the range of bytes that
369 * would fit in the given buffer.
372 mib_copyin_str(struct mib_newp
* __restrict newp
, vir_bytes addr
,
373 char * __restrict buf
, size_t bufsize
, size_t * __restrict sizep
)
379 assert(newp
!= NULL
);
380 assert(bufsize
<= SSIZE_MAX
);
386 * NetBSD has a kernel routine for copying in a string from userland.
387 * MINIX3 does not, since its system call interface has always relied
388 * on userland passing in string lengths. The sysctl(2) API does not
389 * provide the string length, and thus, we have to do a bit of guess
390 * work. If we copy too little at once, performance suffers. If we
391 * copy too much at once, we may trigger an unneeded page fault. Make
392 * use of page boundaries to strike a balance between those two. If we
393 * are requested to just get the string length, use the scratch buffer.
397 while (bufsize
> 0) {
398 chunk
= PAGE_SIZE
- (addr
% PAGE_SIZE
);
402 ptr
= (buf
!= NULL
) ? &buf
[len
] : scratch
;
403 if ((r
= mib_copyin_aux(newp
, addr
, ptr
, chunk
)) != OK
)
406 if ((endp
= memchr(ptr
, '\0', chunk
)) != NULL
) {
407 /* A null terminator was found - success. */
409 *sizep
= len
+ (size_t)(endp
- ptr
) + 1;
418 /* No null terminator found. */
423 * Increase the version of the root node, and copy this new version to all
424 * nodes on the path to the given node, including that node itself.
427 mib_upgrade(struct mib_node
* node
)
431 assert(node
!= NULL
);
434 * The root node determines the version of the entire tree. Do not use
435 * version number 0, as a zero version number indicates no interest in
436 * versions elsewhere.
439 ver
= mib_root
.node_ver
+ 1;
443 /* Copy the new version to all the nodes on the path. */
445 node
->node_ver
= ver
;
447 node
= node
->node_parent
;
448 } while (node
!= NULL
);
452 * Add a new dynamically allocated node into the tree, inserting it into the
453 * linked-list position of the parent tree as given by 'prevp'. Also update
454 * versions and counters accordingly. This function never fails.
457 mib_add(struct mib_dynode
* dynode
, struct mib_dynode
** prevp
)
459 struct mib_node
*parent
;
461 parent
= dynode
->dynode_node
.node_parent
;
462 assert(parent
!= NULL
);
464 /* Link the dynamic node into the list, in the right place. */
465 assert(prevp
!= NULL
);
466 dynode
->dynode_next
= *prevp
;
469 /* The parent node now has one more child. */
470 parent
->node_csize
++;
473 /* There is now one more node in the tree. */
477 * Bump the version of all nodes on the path to the new node, including
480 mib_upgrade(&dynode
->dynode_node
);
487 mib_create(struct mib_call
* call
, struct mib_node
* parent
,
488 struct mib_oldp
* oldp
, struct mib_newp
* newp
)
490 struct mib_dynode
*dynode
, **prevp
;
491 struct mib_node
*node
;
492 struct sysctlnode scn
;
493 size_t namelen
, size
;
499 /* This is a privileged operation. */
500 if (!mib_authed(call
))
504 * The parent must not be a remote node, but this is already implied by
505 * the fact that we got here at all.
507 assert(SYSCTL_TYPE(parent
->node_flags
) == CTLTYPE_NODE
);
508 assert(!(parent
->node_flags
& CTLFLAG_REMOTE
));
510 /* The parent node must not be marked as read-only. */
511 if (!(parent
->node_flags
& CTLFLAG_READWRITE
))
515 * Has the parent reached its child node limit? This check is entirely
516 * theoretical as long as we support only 32-bit virtual memory.
518 if (parent
->node_csize
== INT_MAX
)
520 assert(parent
->node_clen
<= parent
->node_csize
);
522 /* The caller must supply information on the child node to create. */
526 if ((r
= mib_copyin(newp
, &scn
, sizeof(scn
))) != OK
)
530 * We perform as many checks as possible before we start allocating
531 * memory. Then again, after allocation, copying in data may still
532 * fail. Unlike when setting values, we do not first copy data into a
533 * temporary buffer here, because we do not need to: if the copy fails,
534 * the entire create operation fails, so atomicity is not an issue.
536 if (SYSCTL_VERS(scn
.sysctl_flags
) != SYSCTL_VERSION
)
540 * If a node version number is given, it must match the version of
541 * either the parent or the root node. The given version number is
542 * *not* used for the node being created.
544 if (scn
.sysctl_ver
!= 0 && scn
.sysctl_ver
!= mib_root
.node_ver
&&
545 scn
.sysctl_ver
!= parent
->node_ver
)
549 * Validate the node flags. In addition to the NetBSD-allowed flags,
550 * we also allow UNSIGNED, and leave its interpretation to userland.
552 if (SYSCTL_FLAGS(scn
.sysctl_flags
) &
553 ~(SYSCTL_USERFLAGS
| CTLFLAG_UNSIGNED
))
556 if (!(scn
.sysctl_flags
& CTLFLAG_IMMEDIATE
)) {
558 * Without either IMMEDIATE or OWNDATA, data pointers are
559 * actually kernel addresses--a concept we do not support.
560 * Otherwise, if IMMEDIATE is not set, we are going to have to
561 * allocate extra memory for the data, so force OWNDATA to be.
562 * set. Node-type nodes have no data, though.
564 if (SYSCTL_TYPE(scn
.sysctl_flags
) != CTLTYPE_NODE
) {
565 if (!(scn
.sysctl_flags
& CTLFLAG_OWNDATA
) &&
566 scn
.sysctl_data
!= NULL
)
567 return EINVAL
; /* not meaningful on MINIX3 */
569 scn
.sysctl_flags
|= CTLFLAG_OWNDATA
;
571 } else if (scn
.sysctl_flags
& CTLFLAG_OWNDATA
)
574 /* The READWRITE flag consists of multiple bits. Sanitize. */
575 if (scn
.sysctl_flags
& CTLFLAG_READWRITE
)
576 scn
.sysctl_flags
|= CTLFLAG_READWRITE
;
578 /* Validate the node type and size, and do some additional checks. */
579 switch (SYSCTL_TYPE(scn
.sysctl_flags
)) {
581 if (scn
.sysctl_size
!= sizeof(bool))
585 if (scn
.sysctl_size
!= sizeof(int))
589 if (scn
.sysctl_size
!= sizeof(u_quad_t
))
594 * For strings, a zero length means that we are supposed to
595 * allocate a buffer size based on the given string size.
597 if (scn
.sysctl_size
== 0 && scn
.sysctl_data
!= NULL
) {
598 if ((r
= mib_copyin_str(newp
,
599 (vir_bytes
)scn
.sysctl_data
, NULL
, SSIZE_MAX
,
602 scn
.sysctl_size
= size
;
607 * We do not set an upper size on the data size, since it would
608 * still be possible to create a large number of nodes, and
609 * this is a privileged operation ayway.
611 if (scn
.sysctl_size
== 0 || scn
.sysctl_size
> SSIZE_MAX
)
613 if (scn
.sysctl_flags
& CTLFLAG_IMMEDIATE
)
618 * The zero size is an API requirement, but we also rely on the
619 * zero value internally, as the node has no static children.
621 if (scn
.sysctl_size
!= 0)
623 if (scn
.sysctl_flags
& (CTLFLAG_IMMEDIATE
| CTLFLAG_OWNDATA
))
625 if (scn
.sysctl_csize
!= 0 || scn
.sysctl_clen
!= 0 ||
626 scn
.sysctl_child
!= NULL
)
633 if (scn
.sysctl_func
!= NULL
|| scn
.sysctl_parent
!= NULL
)
636 /* Verify that the given name is valid, and get its string length. */
637 namelen
= mib_check_name(scn
.sysctl_name
, sizeof(scn
.sysctl_name
));
643 * Find a free identifier, or check for ID collisions if a specific
644 * identifier was given. At the same time, scan for name collisions,
645 * and find the location at which to insert the new node in the list.
647 r
= mib_scan(parent
, scn
.sysctl_num
, scn
.sysctl_name
, &id
, &prevp
,
652 * On collisions, if requested, copy out the existing node.
653 * This does not quite fit the general interaction model, as
654 * the service must now return a nonzero old length from a call
655 * that actually failed (in contrast to ENOMEM failures).
657 if (r
== EEXIST
&& oldp
!= NULL
) {
658 len
= mib_copyout_node(call
, oldp
, 0, id
, node
);
661 mib_setoldlen(call
, len
);
668 * All checks so far have passed. "id" now contains the new node
669 * identifier, and "prevp" points to the pointer at which to insert the
670 * new node in its parent's linked list of dynamic nodes.
672 * We can now attempt to create and initialize a new dynamic node.
673 * Allocating nodes this way may cause heavy memory fragmentation over
674 * time, but we do not expect the tree to see heavy modification at run
675 * time, and the superuser has easier ways to get the MIB service in
676 * trouble. We note that even in low-memory conditions, the MIB
677 * service is always able to provide basic functionality.
679 size
= sizeof(*dynode
) + namelen
;
680 if (!(scn
.sysctl_flags
& CTLFLAG_IMMEDIATE
))
681 size
+= scn
.sysctl_size
;
683 if ((dynode
= malloc(size
)) == NULL
)
684 return EINVAL
; /* do not return ENOMEM */
687 /* From here on, we have to free "dynode" before returning an error. */
690 memset(dynode
, 0, sizeof(*dynode
)); /* no need to zero all of "size" */
691 dynode
->dynode_id
= id
;
692 strlcpy(dynode
->dynode_name
, scn
.sysctl_name
, namelen
+ 1);
694 node
= &dynode
->dynode_node
;
695 node
->node_flags
= scn
.sysctl_flags
& ~SYSCTL_VERS_MASK
;
696 if (SYSCTL_TYPE(scn
.sysctl_flags
) == CTLTYPE_NODE
)
697 node
->node_flags
|= CTLFLAG_PARENT
;
698 node
->node_size
= scn
.sysctl_size
;
699 node
->node_parent
= parent
;
700 node
->node_name
= dynode
->dynode_name
;
702 /* Initialize the node value. */
703 if (scn
.sysctl_flags
& CTLFLAG_IMMEDIATE
) {
704 switch (SYSCTL_TYPE(scn
.sysctl_flags
)) {
706 /* Sanitize booleans. See the C99 _Bool comment. */
707 memcpy(&c
, &scn
.sysctl_bdata
, sizeof(c
));
708 node
->node_bool
= (bool)c
;
711 node
->node_int
= scn
.sysctl_idata
;
714 node
->node_quad
= scn
.sysctl_qdata
;
719 } else if (SYSCTL_TYPE(scn
.sysctl_flags
) != CTLTYPE_NODE
) {
720 node
->node_data
= dynode
->dynode_name
+ namelen
+ 1;
722 /* Did the user supply initial data? If not, use zeroes. */
723 if (scn
.sysctl_data
!= NULL
) {
725 * For strings, do not copy in more than needed. This
726 * is just a nice feature which allows initialization
727 * of large string buffers with short strings.
729 if (SYSCTL_TYPE(scn
.sysctl_flags
) == CTLTYPE_STRING
)
730 r
= mib_copyin_str(newp
,
731 (vir_bytes
)scn
.sysctl_data
,
732 node
->node_data
, scn
.sysctl_size
, NULL
);
734 r
= mib_copyin_aux(newp
,
735 (vir_bytes
)scn
.sysctl_data
,
736 node
->node_data
, scn
.sysctl_size
);
738 memset(node
->node_data
, 0, scn
.sysctl_size
);
741 * Sanitize booleans. See the C99 _Bool comment elsewhere.
742 * In this case it is not as big of a deal, as we will not be
743 * accessing the boolean value directly ourselves.
745 if (r
== OK
&& SYSCTL_TYPE(scn
.sysctl_flags
) == CTLTYPE_BOOL
) {
746 b
= (bool)*(char *)node
->node_data
;
747 memcpy(node
->node_data
, &b
, sizeof(b
));
752 * Even though it would be entirely possible to set a description right
753 * away as well, this does not seem to be supported on NetBSD at all.
756 /* Deal with earlier failures now. */
765 * At this point, actual creation can no longer fail. Add the node
766 * into the tree, and update versions and counters.
768 mib_add(dynode
, prevp
);
771 * Copy out the newly created node as resulting ("old") data. Do not
772 * undo the creation if this fails, though.
774 return mib_copyout_node(call
, oldp
, 0, id
, node
);
778 * Remove the given node from the tree. If 'prevp' is NULL, the node is a
779 * static node which should be zeroed out. If 'prevp' is not NULL, the node is
780 * a dynamic node which should be freed; 'prevp' will then point to the pointer
781 * to its dynode container. Also update versions and counters as appropriate.
782 * This function never fails.
785 mib_remove(struct mib_node
* node
, struct mib_dynode
** prevp
)
787 struct mib_dynode
*dynode
;
788 struct mib_node
*parent
;
790 parent
= node
->node_parent
;
791 assert(parent
!= NULL
);
793 /* If the description was allocated, free it. */
794 if (node
->node_flags
& CTLFLAG_OWNDESC
) {
795 free(__UNCONST(node
->node_desc
));
800 * Static nodes only use static memory, and dynamic nodes have the data
801 * area embedded in the dynode object. In neither case is data memory
802 * allocated separately, and thus, it need never be freed separately.
803 * Therefore we *must not* check CTLFLAG_OWNDATA here.
806 assert(parent
->node_csize
> 0);
807 assert(parent
->node_clen
> 0);
810 * Dynamic nodes must be freed. Freeing the dynode object also frees
811 * the node name and any associated data. Static nodes are zeroed out,
812 * and the static memory they referenced will become inaccessible.
816 *prevp
= dynode
->dynode_next
;
818 assert(node
== &dynode
->dynode_node
);
823 parent
->node_csize
--;
825 memset(node
, 0, sizeof(*node
));
831 /* Bump the version of all nodes on the path to the destroyed node. */
839 mib_destroy(struct mib_call
* call
, struct mib_node
* parent
,
840 struct mib_oldp
* oldp
, struct mib_newp
* newp
)
842 struct mib_dynode
**prevp
;
843 struct mib_node
*node
;
844 struct sysctlnode scn
;
847 /* This is a privileged operation. */
848 if (!mib_authed(call
))
851 /* The parent node must not be marked as read-only. */
852 if (!(parent
->node_flags
& CTLFLAG_READWRITE
))
855 /* The caller must specify which child node to destroy. */
859 if ((r
= mib_copyin(newp
, &scn
, sizeof(scn
))) != OK
)
862 if (SYSCTL_VERS(scn
.sysctl_flags
) != SYSCTL_VERSION
)
865 /* Locate the child node. */
866 if ((node
= mib_find(parent
, scn
.sysctl_num
, &prevp
)) == NULL
)
869 /* The node must not be marked as permanent. */
870 if (node
->node_flags
& CTLFLAG_PERMANENT
)
873 /* For node-type nodes, extra rules apply. */
874 if (SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_NODE
) {
875 /* The node must not be a mount point. */
876 if (node
->node_flags
& CTLFLAG_REMOTE
)
879 /* The node must not have an associated function. */
880 if (!(node
->node_flags
& CTLFLAG_PARENT
))
883 /* The target node must itself not have child nodes. */
884 if (node
->node_clen
!= 0)
888 /* If the user supplied a version, it must match the node version. */
889 if (scn
.sysctl_ver
!= 0 && scn
.sysctl_ver
!= node
->node_ver
)
890 return EINVAL
; /* NetBSD inconsistently throws ENOENT here */
892 /* If the user supplied a name, it must match the node name. */
893 if (scn
.sysctl_name
[0] != '\0') {
894 if (memchr(scn
.sysctl_name
, '\0',
895 sizeof(scn
.sysctl_name
)) == NULL
)
897 if (strcmp(scn
.sysctl_name
, node
->node_name
))
898 return EINVAL
; /* also ENOENT on NetBSD */
902 * Copy out the old node if requested, otherwise return the length
903 * anyway. The node will be destroyed even if this call fails,
904 * because that is how NetBSD behaves.
906 r
= mib_copyout_node(call
, oldp
, 0, scn
.sysctl_num
, node
);
909 * Remove the node from the tree. The procedure depends on whether the
910 * node is static (prevp == NULL) or dynamic (prevp != NULL). Also
911 * update versions and counters.
913 mib_remove(node
, prevp
);
919 * Copy out a node description to userland, using the exchange format for node
920 * descriptions (namely, a sysctldesc structure). Return the size of the
921 * object that is (or, if the description falls outside the requested data
922 * range, would be) copied out on success, or a negative error code on failure.
923 * The function may return 0 to indicate that nothing was copied out after all.
926 mib_copyout_desc(struct mib_call
* call
, struct mib_oldp
* oldp
, size_t off
,
927 int id
, const struct mib_node
* node
)
929 struct sysctldesc
*scd
;
933 /* Descriptions of private nodes are considered private too. */
934 if ((node
->node_flags
& CTLFLAG_PRIVATE
) && !mib_authed(call
))
937 /* The description length includes the null terminator. */
938 if (node
->node_desc
!= NULL
)
939 size
= strlen(node
->node_desc
) + 1;
943 assert(sizeof(*scd
) + size
<= sizeof(scratch
));
945 scd
= (struct sysctldesc
*)scratch
;
946 memset(scd
, 0, sizeof(*scd
));
948 scd
->descr_ver
= node
->node_ver
;
949 scd
->descr_len
= size
;
950 if (node
->node_desc
!= NULL
)
951 strlcpy(scd
->descr_str
, node
->node_desc
,
952 sizeof(scratch
) - sizeof(*scd
));
954 scd
->descr_str
[0] = '\0';
956 size
+= offsetof(struct sysctldesc
, descr_str
);
958 if ((r
= mib_copyout(oldp
, off
, scratch
, size
)) < 0)
962 * By aligning just the size, we may leave garbage between the entries
963 * copied out, which is fine because it is userland's own data.
965 return roundup2(size
, sizeof(int32_t));
969 * Retrieve node descriptions in bulk, or retrieve or assign a particular
970 * node's description.
973 mib_describe(struct mib_call
* call
, struct mib_node
* parent
,
974 struct mib_oldp
* oldp
, struct mib_newp
* newp
)
976 struct sysctlnode scn
;
977 struct mib_node
*node
;
978 struct mib_dynode
*dynode
;
982 /* If new data are given, they identify a particular target node. */
984 if ((r
= mib_copyin(newp
, &scn
, sizeof(scn
))) != OK
)
987 if (SYSCTL_VERS(scn
.sysctl_flags
) != SYSCTL_VERSION
)
990 /* Locate the child node. */
991 if ((node
= mib_find(parent
, scn
.sysctl_num
, NULL
)) == NULL
)
994 /* Descriptions of private nodes are considered private too. */
995 if ((node
->node_flags
& CTLFLAG_PRIVATE
) && !mib_authed(call
))
999 * If a description pointer was given, this is a request to
1000 * set the node's description.
1002 if (scn
.sysctl_desc
!= NULL
) {
1003 /* Such a request requires superuser privileges. */
1004 if (!mib_authed(call
))
1008 * The node must not be a mount point. Arguably this
1009 * check is not necessary, since we use the description
1010 * of the preexisting underlying node anyway.
1012 if (SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_NODE
&&
1013 (node
->node_flags
& CTLFLAG_REMOTE
))
1016 /* The node must not already have a description. */
1017 if (node
->node_desc
!= NULL
)
1020 /* The node must not be marked as permanent. */
1021 if (node
->node_flags
& CTLFLAG_PERMANENT
)
1025 * If the user supplied a version, it must match.
1026 * NetBSD performs this check only when setting
1027 * descriptions, and thus, so do we..
1029 if (scn
.sysctl_ver
!= 0 &&
1030 scn
.sysctl_ver
!= node
->node_ver
)
1034 * Copy in the description to the scratch buffer.
1035 * The length of the description must be reasonable.
1037 if ((r
= mib_copyin_str(newp
,
1038 (vir_bytes
)scn
.sysctl_desc
, scratch
, MAXDESCLEN
,
1042 /* Allocate memory and store the description. */
1043 if ((node
->node_desc
= strdup(scratch
)) == NULL
) {
1044 printf("MIB: out of memory!\n");
1046 return EINVAL
; /* do not return ENOMEM */
1050 /* The description must now be freed with the node. */
1051 node
->node_flags
|= CTLFLAG_OWNDESC
;
1055 * Either way, copy out the requested node's description, which
1056 * should indeed be the new description if one was just set.
1057 * Note that we have already performed the permission check
1058 * that could make this call return zero, so here it will not.
1060 return mib_copyout_desc(call
, oldp
, 0, scn
.sysctl_num
, node
);
1063 /* See also the considerations laid out in mib_query(). */
1066 /* First describe the static nodes. */
1067 for (id
= 0; IS_STATIC_ID(parent
, id
); id
++) {
1068 node
= &parent
->node_scptr
[id
];
1070 if (node
->node_flags
== 0)
1073 if ((r
= mib_copyout_desc(call
, oldp
, off
, id
, node
)) < 0)
1078 /* Then describe the dynamic nodes. */
1079 for (dynode
= parent
->node_dcptr
; dynode
!= NULL
;
1080 dynode
= dynode
->dynode_next
) {
1081 node
= &dynode
->dynode_node
;
1083 if ((r
= mib_copyout_desc(call
, oldp
, off
, dynode
->dynode_id
,
1093 * Return a pointer to the data associated with the given node, or NULL if the
1094 * node has no associated data. Actual calls to this function should never
1095 * result in NULL - as long as the proper rules are followed elsewhere.
1098 mib_getptr(struct mib_node
* node
)
1101 switch (SYSCTL_TYPE(node
->node_flags
)) {
1103 if (node
->node_flags
& CTLFLAG_IMMEDIATE
)
1104 return &node
->node_bool
;
1107 if (node
->node_flags
& CTLFLAG_IMMEDIATE
)
1108 return &node
->node_int
;
1111 if (node
->node_flags
& CTLFLAG_IMMEDIATE
)
1112 return &node
->node_quad
;
1114 case CTLTYPE_STRING
:
1115 case CTLTYPE_STRUCT
:
1116 if (node
->node_flags
& CTLFLAG_IMMEDIATE
)
1123 return node
->node_data
;
1127 * Read current (old) data from a regular data node, if requested. Return the
1131 mib_read(struct mib_node
* node
, struct mib_oldp
* oldp
)
1137 if ((ptr
= mib_getptr(node
)) == NULL
)
1140 if (SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_STRING
)
1141 oldlen
= strlen(node
->node_data
) + 1;
1143 oldlen
= node
->node_size
;
1145 if (oldlen
> SSIZE_MAX
)
1148 /* Copy out the current data, if requested at all. */
1149 if (oldp
!= NULL
&& (r
= mib_copyout(oldp
, 0, ptr
, oldlen
)) < 0)
1152 /* Return the current length in any case. */
1153 return (ssize_t
)oldlen
;
1157 * Write new data into a regular data node, if requested.
1160 mib_write(struct mib_call
* call
, struct mib_node
* node
,
1161 struct mib_newp
* newp
, mib_verify_ptr verify
)
1163 bool b
[(sizeof(bool) == sizeof(char)) ? 1 : -1]; /* explained below */
1169 return OK
; /* nothing to do */
1172 * When setting a new value, we cannot risk doing an in-place update:
1173 * the copy from userland may fail halfway through, in which case an
1174 * in-place update could leave the node value in a corrupted state.
1175 * Thus, we must first fetch any new data into a temporary buffer.
1177 * Given that we use intermediate data storage, we could support value
1178 * swapping, where the user provides the same buffer for new and old
1179 * data. We choose not to: NetBSD does not support it, it would make
1180 * trace(1)'s job a lot harder, and it would convolute the code here.
1182 newlen
= mib_getnewlen(newp
);
1184 if ((dst
= mib_getptr(node
)) == NULL
)
1187 switch (SYSCTL_TYPE(node
->node_flags
)) {
1191 case CTLTYPE_STRUCT
:
1192 /* Non-string types must have an exact size match. */
1193 if (newlen
!= node
->node_size
)
1196 case CTLTYPE_STRING
:
1198 * Strings must not exceed their buffer size. There is a
1199 * second check further below, because we allow userland to
1200 * give us an unterminated string. In that case we terminate
1201 * it ourselves, but then the null terminator must fit as well.
1203 if (newlen
> node
->node_size
)
1211 * If we cannot fit the data in the scratch buffer, then allocate a
1212 * temporary buffer. We add one extra byte so that we can add a null
1213 * terminator at the end of strings in case userland did not supply
1214 * one. Either way, we must free the temporary buffer later!
1216 * The alternative is to ensure that the given memory is accessible
1217 * before starting the copy, but that would break if we ever add kernel
1218 * threads or anything that allows asynchronous memory unmapping, etc.
1220 if (newlen
+ 1 > sizeof(scratch
)) {
1222 * In practice, the temporary buffer is at least an entire
1223 * memory page, which is reasonable by any standard. As a
1224 * result, we can get away with refusing to perform dynamic
1225 * allocation for unprivileged users. This limits the impact
1226 * that unprivileged users can have on our memory space.
1228 if (!mib_authed(call
))
1232 * Do not return ENOMEM on allocation failure, because ENOMEM
1233 * implies that a valid old length was returned.
1235 if ((src
= malloc(newlen
+ 1)) == NULL
) {
1236 printf("MIB: out of memory!\n");
1244 /* Copy in the data. Note that newlen may be zero. */
1245 r
= mib_copyin(newp
, src
, newlen
);
1247 if (r
== OK
&& verify
!= NULL
&& !verify(call
, node
, src
, newlen
))
1251 /* Check and, if acceptable, store the new value. */
1252 switch (SYSCTL_TYPE(node
->node_flags
)) {
1255 * Due to the nature of the C99 _Bool type, we can not
1256 * test directly whether the given boolean value is a
1257 * value that is not "true" and not "false". In the
1258 * worst case, another value could invoke undefined
1259 * behavior. We try our best to sanitize the value
1260 * without looking at it directly, which unfortunately
1261 * requires us to test for the size of the bool type.
1262 * We do that at compile time, hence the 'b' "array".
1263 * Any size other than one byte is an ABI violation.
1265 b
[0] = (bool)src
[0];
1266 memcpy(dst
, &b
[0], sizeof(b
[0]));
1270 case CTLTYPE_STRUCT
:
1271 memcpy(dst
, src
, node
->node_size
);
1273 case CTLTYPE_STRING
:
1274 if (newlen
== node
->node_size
&&
1275 src
[newlen
- 1] != '\0') {
1276 /* Our null terminator does not fit! */
1281 * We do not mind null characters in the middle. In
1282 * general, the buffer may contain garbage after the
1283 * first null terminator, but such garbage will never
1284 * end up being copied out.
1287 strlcpy(dst
, src
, node
->node_size
);
1294 if (src
!= scratch
) {
1303 * Read and/or write the value of a regular data node. A regular data node is
1304 * a leaf node. Typically, a leaf node has no associated function, in which
1305 * case this function will be used instead. In addition, this function may be
1306 * used from handler functions as part of their functionality.
1309 mib_readwrite(struct mib_call
* call
, struct mib_node
* node
,
1310 struct mib_oldp
* oldp
, struct mib_newp
* newp
, mib_verify_ptr verify
)
1315 /* Copy out old data, if requested. Always get the old data length. */
1316 if ((r
= len
= mib_read(node
, oldp
)) < 0)
1319 /* Copy in new data, if requested. */
1320 if ((r
= mib_write(call
, node
, newp
, verify
)) != OK
)
1323 /* Return the old data length. */
1328 * Dispatch a sysctl call, by looking up the target node by its MIB name and
1329 * taking the appropriate action on the resulting node, if found. Return the
1330 * old data length on success, or a negative error code on failure.
1333 mib_dispatch(struct mib_call
* call
, struct mib_oldp
* oldp
,
1334 struct mib_newp
* newp
)
1336 struct mib_node
*parent
, *node
;
1338 int id
, is_leaf
, can_restart
, has_verify
, has_func
;
1340 assert(call
->call_namelen
<= CTL_MAXNAME
);
1343 * Resolve the name by descending into the node tree, level by level,
1344 * starting at the MIB root.
1346 for (parent
= &mib_root
; call
->call_namelen
> 0; parent
= node
) {
1347 id
= call
->call_name
[0];
1349 call
->call_namelen
--;
1351 assert(SYSCTL_TYPE(parent
->node_flags
) == CTLTYPE_NODE
);
1352 assert(parent
->node_flags
& CTLFLAG_PARENT
);
1355 * Check for meta-identifiers. Regular identifiers are never
1356 * negative, although node handler functions may take subpaths
1357 * with negative identifiers that are not meta-identifiers
1358 * (e.g., see KERN_PROC2).
1362 * A meta-identifier must always be the last name
1365 if (call
->call_namelen
> 0)
1370 return mib_query(call
, parent
, oldp
, newp
);
1372 return mib_create(call
, parent
, oldp
, newp
);
1374 return mib_destroy(call
, parent
, oldp
, newp
);
1376 return mib_describe(call
, parent
, oldp
, newp
);
1384 /* Locate the child node. */
1385 if ((node
= mib_find(parent
, id
, NULL
/*prevp*/)) == NULL
)
1388 /* Check if access is permitted at this level. */
1389 if ((node
->node_flags
& CTLFLAG_PRIVATE
) && !mib_authed(call
))
1393 * Start by checking if the node is a remote node. If so, let
1394 * a remote service handle the remainder of this request.
1395 * However, as part of attempting the remote call, we may
1396 * discover that the remote service has died or that it is
1397 * unmounting the subtree. If the node was not a temporary
1398 * mountpoint, we should (and do) continue with the request
1399 * locally - if it was, it will already be deallocated and we
1400 * must be very careful not to access 'node' again!
1402 is_leaf
= (SYSCTL_TYPE(node
->node_flags
) != CTLTYPE_NODE
);
1404 if (!is_leaf
&& (node
->node_flags
& CTLFLAG_REMOTE
)) {
1405 /* Determine this before 'node' may disappear.. */
1406 can_restart
= (node
->node_flags
& CTLFLAG_PARENT
);
1408 r
= mib_remote_call(call
, node
, oldp
, newp
);
1410 if (r
!= ERESTART
|| !can_restart
)
1411 return (r
!= ERESTART
) ? r
: ENOENT
;
1413 /* Service died, subtree is unmounted, keep going. */
1414 assert(SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_NODE
);
1415 assert(!(node
->node_flags
& CTLFLAG_REMOTE
));
1419 * Is this a leaf node, and/or is this node handled by a
1420 * function? If either is true, resolution ends at this level.
1421 * In order to save a few bytes of memory per node, we use
1422 * different ways to determine whether there is a function
1423 * depending on whether the node is a leaf or not.
1426 has_verify
= (node
->node_flags
& CTLFLAG_VERIFY
);
1427 has_func
= (!has_verify
&& node
->node_func
!= NULL
);
1430 has_func
= !(node
->node_flags
& CTLFLAG_PARENT
);
1434 * The name may be longer only if the node is not a leaf. That
1435 * also applies to leaves with functions, so check this first.
1437 if (is_leaf
&& call
->call_namelen
> 0)
1441 * If resolution indeed ends here, and the user supplied new
1442 * data, check if writing is allowed. For functions, it is
1443 * arguable whether we should do this check here already.
1444 * However, for now, this approach covers all our use cases.
1446 if ((is_leaf
|| has_func
) && newp
!= NULL
) {
1447 if (!(node
->node_flags
& CTLFLAG_READWRITE
))
1451 * Unless nonprivileged users may write to this node,
1452 * ensure that the user has superuser privileges. The
1453 * ANYWRITE flag does not override the READWRITE flag.
1455 if (!(node
->node_flags
& CTLFLAG_ANYWRITE
) &&
1460 /* If this node has a handler function, let it do the work. */
1462 return node
->node_func(call
, node
, oldp
, newp
);
1464 /* For regular data leaf nodes, handle generic access. */
1466 return mib_readwrite(call
, node
, oldp
, newp
,
1467 has_verify
? node
->node_verify
: NULL
);
1469 /* No function and not a leaf? Descend further. */
1472 /* If we get here, the name refers to a node array. */
1477 * Recursively initialize the static tree at initialization time.
1480 mib_tree_recurse(struct mib_node
* parent
)
1482 struct mib_node
*node
;
1485 assert(SYSCTL_TYPE(parent
->node_flags
) == CTLTYPE_NODE
);
1486 assert(parent
->node_flags
& CTLFLAG_PARENT
);
1489 * Later on, node_csize and node_clen will also include dynamically
1490 * created nodes. This means that we cannot use node_csize to iterate
1491 * over the static nodes.
1493 parent
->node_csize
= parent
->node_size
;
1495 node
= parent
->node_scptr
;
1497 for (id
= 0; IS_STATIC_ID(parent
, id
); id
++, node
++) {
1498 if (node
->node_flags
== 0)
1503 parent
->node_clen
++;
1505 node
->node_ver
= parent
->node_ver
;
1506 node
->node_parent
= parent
;
1508 /* Recursively apply this function to all node children. */
1509 if (SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_NODE
&&
1510 (node
->node_flags
& CTLFLAG_PARENT
))
1511 mib_tree_recurse(node
);
1516 * Go through the entire static tree, recursively, initializing some values
1517 * that could not be assigned at compile time.
1523 /* Initialize some variables. */
1524 mib_nodes
= 1; /* the root node itself */
1528 * The entire tree starts with the same, nonzero node version.
1529 * The root node is the only node without a parent.
1531 mib_root
.node_ver
= 1;
1532 mib_root
.node_parent
= NULL
;
1534 /* Recursively initialize the static tree. */
1535 mib_tree_recurse(&mib_root
);
1539 * Process a subtree mount request from a remote service. Return OK on
1540 * success, with a pointer to the resulting static-node structure stored in
1541 * 'nodep'. Return a negative error code on failure.
1544 mib_mount(const int * mib
, unsigned int miblen
, unsigned int eid
, uint32_t rid
,
1545 uint32_t flags
, unsigned int csize
, unsigned int clen
,
1546 struct mib_node
** nodep
)
1548 struct mib_dynode
*dynode
, **prevp
;
1549 struct mib_node
*parent
, *node
;
1550 char name
[SYSCTL_NAMELEN
], *desc
;
1551 size_t size
, namelen
, desclen
;
1556 * Perform initial verification of the given parameters. Even stricter
1557 * checks may be performed later.
1560 * By policy, we forbid mounting top-level nodes. This is in effect
1561 * also the only security-like restriction: a service should not be
1562 * able to just take over, say, the entire "kern" subtree. There is
1563 * currently little in the way of a service taking over an important
1564 * set of second-level nodes, though.
1566 * TODO: allow mounting of predefined mount points only, for example by
1567 * having an internal node flag that permits mounting the subtree or
1568 * any node in it. As an even better alternative, allow this to be
1569 * controlled through a policy specification; unfortunately, this would
1570 * also add a substantial amount of infrastructure.
1573 MIB_DEBUG_MOUNT(("MIB: mounting failed, path too short\n"));
1579 * The flags field is highly restricted right now. Only a few flags
1580 * may be given at all, and then when using an existing node as mount
1581 * point, the flag must exactly match the existing node's flags.
1583 if (SYSCTL_VERS(flags
) != SYSCTL_VERSION
||
1584 SYSCTL_TYPE(flags
) != CTLTYPE_NODE
||
1585 (SYSCTL_FLAGS(flags
) & ~(CTLFLAG_READONLY
| CTLFLAG_READWRITE
|
1586 CTLFLAG_PERMANENT
| CTLFLAG_HIDDEN
)) != 0) {
1587 MIB_DEBUG_MOUNT(("MIB: mounting failed, invalid flags %"PRIx32
1593 if (csize
> (1U << MIB_RC_BITS
) || clen
> csize
) {
1594 MIB_DEBUG_MOUNT(("MIB: mounting failed, invalid child size or "
1595 "length (%u, %u)\n", csize
, clen
));
1601 * Look up the parent node of the mount point. This parent node must
1602 * exist - we don't want to create more than one temporary node in any
1603 * case. All the nodes leading up to and including the parent node
1604 * must be real, local, non-private, node-type nodes. The path may not
1605 * be private, because that would allow an unprivileged service to
1606 * intercept writes to privileged nodes--currently a total nonissue in
1607 * practice, but still. Note that the service may itself restrict
1608 * access to nodes in its own mounted subtree in any way it wishes.
1612 for (n
= 0; n
< miblen
- 1; n
++) {
1613 /* Meta-identifiers are obviously not allowed in the path. */
1614 if ((id
= mib
[n
]) < 0) {
1615 MIB_DEBUG_MOUNT(("MIB: mounting failed, meta-ID in "
1621 /* Locate the child node. */
1622 if ((node
= mib_find(parent
, id
, NULL
/*prevp*/)) == NULL
) {
1623 MIB_DEBUG_MOUNT(("MIB: mounting failed, path not "
1629 /* Make sure it is a regular node-type node. */
1630 if (SYSCTL_TYPE(node
->node_flags
) != CTLTYPE_NODE
||
1631 !(node
->node_flags
& CTLFLAG_PARENT
) ||
1632 (node
->node_flags
& (CTLFLAG_REMOTE
| CTLFLAG_PRIVATE
))) {
1633 MIB_DEBUG_MOUNT(("MIB: mounting failed, unacceptable "
1642 /* Now see if the mount point itself exists. */
1643 if ((id
= mib
[miblen
- 1]) < 0) {
1644 MIB_DEBUG_MOUNT(("MIB: mounting failed, meta-ID in path\n"));
1650 * If the target node exists and passes all tests, it will simply be
1651 * converted to a mount point. If the target node does not exist, we
1652 * have to allocate a temporary node as mount point.
1654 if ((node
= mib_find(parent
, id
, NULL
/*prevp*/)) != NULL
) {
1656 * We are about to mount on an existing node. As stated above,
1657 * the node flags must match the given flags exactly.
1659 if (SYSCTL_TYPE(node
->node_flags
) != CTLTYPE_NODE
||
1660 SYSCTL_FLAGS(node
->node_flags
) !=
1661 (SYSCTL_FLAGS(flags
) | CTLFLAG_PARENT
)) {
1662 MIB_DEBUG_MOUNT(("MIB: mounting failed, target node "
1663 "mismatch (%"PRIx32
", %"PRIx32
")\n",
1664 node
->node_flags
, flags
));
1670 * If the node has dynamically added children, we will not be
1671 * able to restore the node to its old state when unmounting.
1673 if (node
->node_size
!= node
->node_csize
) {
1674 MIB_DEBUG_MOUNT(("MIB: mounting failed, node has "
1675 "dynamic children\n"));
1683 * We are going to create a temporary mount point. Much of the
1684 * procedure that follows is a rather selective extract from
1685 * mib_create(). Start with a check for the impossible.
1687 if (parent
->node_csize
== INT_MAX
) {
1688 MIB_DEBUG_MOUNT(("MIB: mounting failed, parent node "
1695 * In order to create the new node, we also need the node's
1696 * name and description; those did not fit in the request
1697 * message. Ask the caller to copy these strings to us.
1702 if ((r
= mib_remote_info(eid
, rid
, name
, sizeof(name
), scratch
,
1703 MAXDESCLEN
)) != OK
) {
1704 MIB_DEBUG_MOUNT(("MIB: mounting failed, node info "
1705 "request yielded %d\n", r
));
1710 /* Make sure the name is valid. */
1711 if ((namelen
= mib_check_name(name
, sizeof(name
))) == 0) {
1712 printf("MIB: mounting failed, bad name\n");
1717 /* Just forcefully terminate the description. */
1718 scratch
[MAXDESCLEN
- 1] = '\0';
1719 desclen
= strlen(scratch
);
1722 * We know the identifier is not in use yet; make sure that the
1723 * name is not, either. As a side effect, find out where the
1724 * new node should be inserted upon success.
1726 if (mib_scan(parent
, id
, name
, &id
/*unused*/, &prevp
,
1727 &node
/*unused*/) != OK
) {
1728 MIB_DEBUG_MOUNT(("MIB: mounting failed, name "
1735 * Allocate a dynamic node. Unlike for user-created dynamic
1736 * nodes, temporary mount points also include the description
1737 * in the dynode object.
1739 size
= sizeof(*dynode
) + namelen
+ desclen
+ 1;
1741 if ((dynode
= malloc(size
)) == NULL
) {
1742 printf("MIB: out of memory!\n");
1748 /* Initialize the dynamic node. */
1749 memset(dynode
, 0, sizeof(*dynode
));
1750 dynode
->dynode_id
= id
;
1751 strlcpy(dynode
->dynode_name
, name
, namelen
+ 1);
1752 desc
= &dynode
->dynode_name
[namelen
+ 1];
1753 strlcpy(desc
, scratch
, desclen
+ 1);
1755 node
= &dynode
->dynode_node
;
1756 node
->node_flags
= flags
& ~SYSCTL_VERS_MASK
;
1757 node
->node_size
= 0;
1758 node
->node_parent
= parent
;
1759 node
->node_name
= dynode
->dynode_name
;
1760 node
->node_desc
= desc
;
1763 * Add the new dynamic node into the tree, and adjust versions
1766 mib_add(dynode
, prevp
);
1769 /* Success! Perform the actual mount, and return the target node. */
1770 node
->node_flags
|= CTLFLAG_REMOTE
;
1771 node
->node_eid
= eid
;
1772 node
->node_rcsize
= csize
;
1773 node
->node_rclen
= clen
;
1774 node
->node_rid
= rid
;
1783 * Unmount the remote subtree identified by the given node. Release the mount
1784 * point by reversing the action performed while mounting. Also bump the
1785 * version numbers on the path, so that userland knows that it is to expect a
1786 * change of contents in the subtree. This function always succeeds, and may
1787 * deallocate the given node.
1790 mib_unmount(struct mib_node
* node
)
1792 struct mib_dynode
**prevp
;
1793 struct mib_node
*child
;
1796 assert(SYSCTL_TYPE(node
->node_flags
) == CTLTYPE_NODE
);
1797 assert(node
->node_flags
& CTLFLAG_REMOTE
);
1800 * Given that the node has the CTLFLAG_REMOTE flag set, we can now tell
1801 * whether the remote subtree obscured a preexisting node or we created
1802 * a temporary mount point, by checking its CTLFLAG_PARENT flag.
1804 if (node
->node_flags
& CTLFLAG_PARENT
) {
1806 * Return the node to its former pre-mount state. Restore the
1807 * original node_clen field by recomputing it.
1809 node
->node_flags
&= ~CTLFLAG_REMOTE
;
1810 node
->node_csize
= node
->node_size
;
1811 node
->node_clen
= 0;
1813 for (id
= 0; IS_STATIC_ID(node
, id
); id
++) {
1814 child
= &node
->node_scptr
[id
];
1816 if (child
->node_flags
!= 0)
1820 node
->node_dcptr
= NULL
;
1822 /* Increase version numbers on the path to the node. */
1826 * We know that we dynamically allocated this node; find its
1827 * parent's pointer to it.
1829 for (prevp
= &node
->node_parent
->node_dcptr
; *prevp
!= NULL
;
1830 prevp
= &(*prevp
)->dynode_next
) {
1831 if (&(*prevp
)->dynode_node
== node
)
1834 assert(*prevp
!= NULL
);
1836 /* Free the node, and adjust counts and versions. */
1837 mib_remove(node
, prevp
);
1840 assert(mib_remotes
> 0);