xref: /minix/minix/servers/mib/mib.h (revision fb9c64b2)
1 #ifndef _MINIX_MIB_MIB_H
2 #define _MINIX_MIB_MIB_H
3 
4 #include <minix/drivers.h>
5 #include <minix/sysctl.h>
6 #include <machine/vmparam.h>
7 #include <assert.h>
8 
9 #if defined(__i386__)
10 #include "kernel/arch/i386/include/archconst.h"
11 #endif
12 
13 #ifndef CONFIG_MAX_CPUS
14 #define CONFIG_MAX_CPUS 1
15 #endif
16 
17 /*
18  * The following setting toggles the existence of the minix.test subtree.  For
19  * production environments, it should probably be disabled, although it should
20  * do no harm either.  For development platforms, it should be enabled, or
21  * test87 will fail.
22  */
23 #define MINIX_TEST_SUBTREE	1	/* include the minix.test subtree? */
24 
25 /*
26  * By default, mount request failures will be silently discarded, because the
27  * requests themselves are one-way.  For service authors, a bit more output may
28  * be helpful.  Set the following defininition to "printf s" in order to
29  * include more information about mount requests and failures.
30  */
31 #define MIB_DEBUG_MOUNT(s)	/* printf s */
32 
33 struct mib_oldp;
34 struct mib_newp;
35 
36 /*
37  * This structure contains a number of less heavily used parameters for handler
38  * functions, mainly to provide extensibility while limiting argument clutter.
39  */
40 struct mib_call {
41 	endpoint_t call_endpt;		/* endpoint of the user process */
42 	const int *call_name;		/* remaining part of the name */
43 	unsigned int call_namelen;	/* length of the remaining name part */
44 	unsigned int call_flags;	/* internal call processing flags */
45 	size_t call_reslen;		/* resulting oldlen value on error */
46 };
47 
48 /* Call flags. */
49 #define MIB_FLAG_AUTH		0x01	/* user verified to be superuser */
50 #define MIB_FLAG_NOAUTH		0x02	/* user verified to be regular user */
51 
52 /*
53  * We reassign new meaning to three NetBSD node flags, because we do not use
54  * the flags in the way NetBSD does:
55  *
56  * - On NetBSD, CTLFLAG_ROOT is used to mark the root of the sysctl tree.  The
57  *   entire root node is not exposed to userland, and thus, neither is this
58  *   flag.  We do not need the flag as we do not have parent pointers.
59  * - On NetBSD, CTLFLAG_ALIAS is used to mark one node as an alias of another
60  *   node, presumably to avoid having to duplicate entire subtrees.  We can
61  *   simply have two nodes point to the same subtree instead, and thus, we do
62  *   not need to support this functionality at all.
63  * - On NetBSD, CTLFLAG_MMAP is defined for future support for memory-mapping
64  *   node data with CTL_MMAP.  It is not yet clear where or why this feature
65  *   would be used in practice.  For as long as NetBSD does not actually use
66  *   this flag *for node-type nodes*, we can reuse it for our own purposes.
67  *
68  * The meaning of our replacement flags is explained further below.  We ensure
69  * that none of these flags are ever exposed to userland.  As such, our own
70  * definitions can be changed as necessary without breaking anything.
71  */
72 #define CTLFLAG_PARENT	CTLFLAG_ROOT	/* node is a real parent node */
73 #define CTLFLAG_VERIFY	CTLFLAG_ALIAS	/* node has verification function */
74 #define CTLFLAG_REMOTE	CTLFLAG_MMAP	/* node is root of remote subtree */
75 
76 /*
77  * The following node structure definition aims to meet several goals at once:
78  *
79  * 1) it can be used for static and dynamic nodes;
80  * 2) it can be used to point to both static and dynamic child arrays at once;
81  * 3) it allows for embedded, pointed-to, and function-generated data;
82  * 4) it allows both temporary and obscuring mount points for remote subtrees;
83  * 5) its unions are compatible with magic instrumentation;
84  * 6) it is optimized for size, assuming many static and few dynamic nodes.
85  *
86  * All nodes have flags, a size, a version, a parent (except the root node), a
87  * name, and optionally a description.  The use of the rest of the fields
88  * depends on the type of the node, which is defined as part of the node's
89  * flags field.
90  *
91  * Data nodes, that is, nodes of type CTLTYPE_{BOOL,INT,QUAD,STRING,STRUCT},
92  * have associated data.  For types CTLTYPE_{BOOL,INT,QUAD}, the node may have
93  * immediate data (CTLFLAG_IMMEDIATE), in which case the value of the node is
94  * stored in the node structure itself (node_bool, node_int, node_quad).  These
95  * node types may instead also have a pointer to data.  This is always the case
96  * for types CTLTYPE_STRING and CTLTYPE_STRUCT.  In that case, node_data is a
97  * valid pointer, and CTLFLAG_IMMEDIATE is not set.  Either way, node_size is
98  * the size of the data, which for strings is the maximum string size; for
99  * other types, it defines the exact field size.  In addition, data nodes may
100  * have the CTLFLAG_VERIFY flag set, which indicates that node_valid points
101  * to a callback function that verifies whether a newly written value is valid
102  * for the node.  If this flag is not set, data nodes may have an associated
103  * function, in which case node_func is not NULL, which will be called to read
104  * and write data instead.  The function may optionally use the node's regular
105  * (size, immediate and/or pointer) data fields as it sees fit.
106  *
107  * Node-type nodes, of type CTLTYPE_NODE, behave differently.  Such nodes may
108  * have static and dynamic child nodes, or have an associated function, or be
109  * a mount point for a subtree handled by a remote process.  The exact case is
110  * defined by the combination of the CTLFLAG_PARENT and CTLFLAG_REMOTE flags,
111  * yielding four possible cases:
112  *
113  * CTLFLAG_PARENT  CTLFLAG_REMOTE  Meaning
114  *     not set         not set     The node has an associated function which
115  *                                 handles all access to the entire subtree.
116  *       set           not set     The node is the root of a real, local
117  *                                 subtree with static and/or dynamic children.
118  *     not set           set       The node is a temporarily created mount
119  *                                 point for a remote tree.  A remote service
120  *                                 handles all access to the entire subtree.
121  *                                 Unmounting the node also destroys the node.
122  *       set             set       The node is a mount point that obscures a
123  *                                 real, local subtree.  A remote service
124  *                                 handles all access to the entire subtree.
125  *                                 Unmounting makes the original node visible.
126  *
127  * If the CTLFLAG_PARENT flag is set, the node is the root of a real sutree.
128  * For such nodes, node_size is the number (not size!) of the array of static
129  * child nodes, which is pointed to by node_scptr and indexed by child
130  * identifier.  Within the static array, child nodes with zeroed flags fields
131  * are not in use.  The node_dcptr field points to a linked list of dynamic
132  * child nodes. The node_csize field is set to the size of the static array
133  * plus the number of dynamic nodes; node_clen is set to the number of valid
134  * entries in the static array plus the number of dynamic nodes.
135  *
136  * If a function is set, and thus neither CTLFLAG_PARENT and CTLFLAG_REMOTE are
137  * set, none of the aforementioned fields are used, and the node_size field is
138  * typically (but not necessarily) set to zero.
139  *
140  * A remote service can mount its own subtree into the central MIB tree.  The
141  * MIB service will then relay any requests for that subtree to the remote
142  * service.  Both the mountpoint and the root of the remote subtree must be of
143  * type CTLTYPE_NODE; thus, no individual leaf nodes may be mounted.  The mount
144  * point may either be created temporarily for the purpose of mounting (e.g.,
145  * net.inet), or it may override a preexisting node (e.g., kern.ipc).  In the
146  * first case, the parent node must exist and be a node type (net).  In the
147  * second case, the preexisting target node (the MIB service's kern.ipc) may
148  * not have an associated function and may only have static children.  While
149  * being used as a mountpoint (i.e., have CTLFLAG_REMOTE set), the local node's
150  * node_csize and node_clen fields must not be used.  Instead, the same space
151  * in the node structure is used to store information about the remote node:
152  * node_rid, node_tid, and the smaller node_rcsize and node_rclen which contain
153  * information about the root of the remote subtree.  Remote nodes are also
154  * part of a linked list for administration purposes, using the node_next
155  * field.  When a preexisting (CTLFLAG_PARENT) node is unmounted, its original
156  * node_csize and node_clen fields are recomputed.
157  *
158  * The structure uses unions for either only pointers or only non-pointers, to
159  * simplify live update support.  However, this does not mean the structure is
160  * not fully used: real node-type nodes use node_{flags,size,ver,parent,csize,
161  * clen,scptr,dcptr,name,desc}, which together add up to the full structure
162  * size.
163  */
164 struct mib_node;
165 struct mib_dynode;
166 
167 typedef ssize_t (*mib_func_ptr)(struct mib_call *, struct mib_node *,
168 	struct mib_oldp *, struct mib_newp *);
169 typedef int (*mib_verify_ptr)(struct mib_call *, struct mib_node *, void *,
170 	size_t);
171 
172 /*
173  * To save space for the maintenance of remote nodes, we split up one uint32_t
174  * field into three subfields:
175  * - node_eid ("endpoint ID"), which is an index into the table of endpoints;
176  * - node_rcsize ("child size"), the number of child slots of the remote root;
177  * - node_rclen ("child length"), the number of children of the remote root.
178  * These fields impose limits on the number of endpoints known in the MIB
179  * service, and the maximum size of the remote subtree root.
180  */
181 #define MIB_EID_BITS	5	/* up to 32 services can set remote subtrees */
182 #define MIB_RC_BITS	12	/* remote root may have up to 4096 children */
183 
184 #if MIB_EID_BITS + 2 * MIB_RC_BITS > 32
185 #error "Sum of remote ID and remote children bit fields exceeds uint32_t size"
186 #endif
187 
188 struct mib_node {
189 	uint32_t node_flags;		/* CTLTYPE_ type and CTLFLAG_ flags */
190 	size_t node_size;		/* size of associated data (bytes) */
191 	uint32_t node_ver;		/* node version */
192 	struct mib_node *node_parent;	/* pointer to parent node */
193 	union ixfer_node_val_u {
194 		struct {
195 			uint32_t nvuc_csize;	/* number of child slots */
196 			uint32_t nvuc_clen;	/* number of actual children */
197 		} nvu_child;
198 		struct {
199 			uint32_t nvur_eid:MIB_EID_BITS;	/* endpoint index */
200 			uint32_t nvur_csize:MIB_RC_BITS;/* remote ch. slots */
201 			uint32_t nvur_clen:MIB_RC_BITS;	/* remote children */
202 			uint32_t nvur_rid;	/* opaque ID of remote root */
203 		} nvu_remote;
204 		bool nvu_bool;		/* immediate boolean */
205 		int nvu_int;		/* immediate integer */
206 		u_quad_t nvu_quad;	/* immediate quad */
207 	} node_val_u;
208 	union pxfer_node_ptr_u {
209 		void *npu_data;		/* struct or string data pointer */
210 		struct mib_node	*npu_scptr;	/* static child node array */
211 	} node_ptr_u;
212 	union pxfer_node_aux_u {
213 		struct mib_dynode *nau_dcptr;	/* dynamic child node list */
214 		mib_func_ptr nau_func;		/* handler function */
215 		mib_verify_ptr nau_verify;	/* verification function */
216 		struct mib_node *nau_next;	/* next remote node in list */
217 	} node_aux_u;
218 	const char *node_name;		/* node name string */
219 	const char *node_desc;		/* node description (may be NULL) */
220 };
221 #define node_csize	node_val_u.nvu_child.nvuc_csize
222 #define node_clen	node_val_u.nvu_child.nvuc_clen
223 #define node_eid	node_val_u.nvu_remote.nvur_eid
224 #define node_rcsize	node_val_u.nvu_remote.nvur_csize
225 #define node_rclen	node_val_u.nvu_remote.nvur_clen
226 #define node_rid	node_val_u.nvu_remote.nvur_rid
227 #define node_bool	node_val_u.nvu_bool
228 #define node_int	node_val_u.nvu_int
229 #define node_quad	node_val_u.nvu_quad
230 #define node_data	node_ptr_u.npu_data
231 #define node_scptr	node_ptr_u.npu_scptr
232 #define node_dcptr	node_aux_u.nau_dcptr
233 #define node_func	node_aux_u.nau_func
234 #define node_verify	node_aux_u.nau_verify
235 #define node_next	node_aux_u.nau_next
236 
237 /*
238  * This structure is used for dynamically allocated nodes, that is, nodes
239  * created by userland at run time.  It contains not only the fields below, but
240  * also the full name and, for leaf nodes with non-immediate data, the actual
241  * data area, or, for temporary mount points for remote subtrees, the node's
242  * description.
243  */
244 struct mib_dynode {
245 	struct mib_dynode *dynode_next;	/* next in linked dynamic node list */
246 	int dynode_id;			/* identifier of this node */
247 	struct mib_node dynode_node;	/* actual node */
248 	char dynode_name[1];		/* node name data (variable size) */
249 };
250 
251 /* Static node initialization macros. */
252 #define MIB_NODE(f,t,n,d) {						\
253 	.node_flags = CTLTYPE_NODE | CTLFLAG_PARENT | f,		\
254 	.node_size = __arraycount(t),					\
255 	.node_scptr = t,						\
256 	.node_name = n,							\
257 	.node_desc = d							\
258 }
259 #define MIB_ENODE(f,n,d) { /* "E"mpty or "E"xternal */			\
260 	.node_flags = CTLTYPE_NODE | CTLFLAG_PARENT | f,		\
261 	.node_name = n,							\
262 	.node_desc = d							\
263 }
264 #define MIB_BOOL(f,b,n,d) {						\
265 	.node_flags = CTLTYPE_BOOL | CTLFLAG_IMMEDIATE | f,		\
266 	.node_size = sizeof(bool),					\
267 	.node_bool = b,							\
268 	.node_name = n,							\
269 	.node_desc = d							\
270 }
271 #define MIB_INT(f,i,n,d) {						\
272 	.node_flags = CTLTYPE_INT | CTLFLAG_IMMEDIATE | f,		\
273 	.node_size = sizeof(int),					\
274 	.node_int = i,							\
275 	.node_name = n,							\
276 	.node_desc = d							\
277 }
278 #define MIB_QUAD(f,q,n,d) {						\
279 	.node_flags = CTLTYPE_QUAD | CTLFLAG_IMMEDIATE | f,		\
280 	.node_size = sizeof(u_quad_t),					\
281 	.node_quad = q,							\
282 	.node_name = n,							\
283 	.node_desc = d							\
284 }
285 #define _MIB_DATA(f,s,p,n,d) {						\
286 	.node_flags = f,						\
287 	.node_size = s,							\
288 	.node_data = __UNCONST(p),					\
289 	.node_name = n,							\
290 	.node_desc = d							\
291 }
292 #define MIB_BOOLPTR(f,p,n,d)  _MIB_DATA(CTLTYPE_BOOL | f, sizeof(*p), p, n, d)
293 #define MIB_INTPTR(f,p,n,d)   _MIB_DATA(CTLTYPE_INT | f, sizeof(*p), p, n, d)
294 #define MIB_QUADTR(f,p,n,d)   _MIB_DATA(CTLTYPE_QUAD | f, sizeof(*p), p, n, d)
295 #define MIB_STRING(f,p,n,d)   _MIB_DATA(CTLTYPE_STRING | f, sizeof(p), p, n, d)
296 #define MIB_STRUCT(f,s,p,n,d) _MIB_DATA(CTLTYPE_STRUCT | f, s, p, n, d)
297 #define MIB_FUNC(f,s,fp,n,d) {						\
298 	.node_flags = f,						\
299 	.node_size = s,							\
300 	.node_func = fp,						\
301 	.node_name = n,							\
302 	.node_desc = d							\
303 }
304 #define MIB_INTV(f,i,vp,n,d) {						\
305 	.node_flags = CTLTYPE_INT | CTLFLAG_IMMEDIATE | 		\
306 	    CTLFLAG_VERIFY | f,						\
307 	.node_size = sizeof(int),					\
308 	.node_int = i,							\
309 	.node_verify = vp,						\
310 	.node_name = n,							\
311 	.node_desc = d							\
312 }
313 
314 /* Finalize a node initialized with MIB_ENODE. */
315 #define MIB_INIT_ENODE(n,t)						\
316 do {									\
317 	(n)->node_size = __arraycount(t);				\
318 	(n)->node_scptr = t;						\
319 } while (0)
320 
321 /* Some convenient shortcuts for highly common flags. */
322 #define _RO	CTLFLAG_READONLY
323 #define _RW	CTLFLAG_READWRITE
324 #define _P	CTLFLAG_PERMANENT
325 
326 /*
327  * If this check fails, all uses of "struct sysctlnode" and "struct sysctldesc"
328  * need to be revised, and translation between different versions of those
329  * structures may have to be added for backward compatibility.
330  */
331 #if SYSCTL_VERSION != SYSCTL_VERS_1
332 #error "NetBSD sysctl headers are ahead of our implementation"
333 #endif
334 
335 /* main.c */
336 int mib_inrange(struct mib_oldp *, size_t);
337 size_t mib_getoldlen(struct mib_oldp *);
338 ssize_t mib_copyout(struct mib_oldp *, size_t, const void * __restrict,
339 	size_t);
340 void mib_setoldlen(struct mib_call *, size_t);
341 size_t mib_getnewlen(struct mib_newp *);
342 int mib_copyin(struct mib_newp * __restrict, void * __restrict, size_t);
343 int mib_copyin_aux(struct mib_newp * __restrict, vir_bytes,
344 	void * __restrict, size_t);
345 int mib_relay_oldp(endpoint_t, struct mib_oldp * __restrict, cp_grant_id_t *,
346 	size_t * __restrict);
347 int mib_relay_newp(endpoint_t, struct mib_newp * __restrict, cp_grant_id_t *,
348 	size_t * __restrict);
349 int mib_authed(struct mib_call *);
350 extern struct mib_node mib_root;
351 
352 /* tree.c */
353 ssize_t mib_readwrite(struct mib_call *, struct mib_node *, struct mib_oldp *,
354 	struct mib_newp *, mib_verify_ptr);
355 ssize_t mib_dispatch(struct mib_call *, struct mib_oldp *, struct mib_newp *);
356 void mib_tree_init(void);
357 int mib_mount(const int *, unsigned int, unsigned int, uint32_t, uint32_t,
358 	unsigned int, unsigned int, struct mib_node **);
359 void mib_unmount(struct mib_node *);
360 extern unsigned int mib_nodes;
361 extern unsigned int mib_objects;
362 extern unsigned int mib_remotes;
363 
364 /* remote.c */
365 void mib_remote_init(void);
366 int mib_register(const message *, int);
367 int mib_deregister(const message *, int);
368 int mib_remote_info(unsigned int, uint32_t, char *, size_t, char *, size_t);
369 ssize_t mib_remote_call(struct mib_call *, struct mib_node *,
370 	struct mib_oldp *, struct mib_newp *);
371 
372 /* proc.c */
373 ssize_t mib_kern_lwp(struct mib_call *, struct mib_node *, struct mib_oldp *,
374 	struct mib_newp *);
375 ssize_t mib_kern_proc2(struct mib_call *, struct mib_node *, struct mib_oldp *,
376 	struct mib_newp *);
377 ssize_t mib_kern_proc_args(struct mib_call *, struct mib_node *,
378 	struct mib_oldp *, struct mib_newp *);
379 ssize_t mib_minix_proc_list(struct mib_call *, struct mib_node *,
380 	struct mib_oldp *, struct mib_newp *);
381 ssize_t mib_minix_proc_data(struct mib_call *, struct mib_node *,
382 	struct mib_oldp *, struct mib_newp *);
383 
384 /* subtree modules */
385 void mib_kern_init(struct mib_node *);
386 void mib_vm_init(struct mib_node *);
387 void mib_hw_init(struct mib_node *);
388 void mib_minix_init(struct mib_node *);
389 
390 #endif /* !_MINIX_MIB_MIB_H */
391