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