xref: /minix/minix/servers/mib/kern.c (revision e1cdaee1)
1 /* MIB service - kern.c - implementation of the CTL_KERN subtree */
2 
3 #include "mib.h"
4 
5 #include <sys/svrctl.h>
6 #include <minix/sysinfo.h>
7 #include <machine/partition.h>
8 #include <sys/sem.h>
9 #include <sys/shm.h>
10 
11 #include "servers/vfs/const.h"
12 #include "servers/vfs/dmap.h"
13 
14 static char hostname[MAXHOSTNAMELEN], domainname[MAXHOSTNAMELEN];
15 
16 /*
17  * Verification for CTL_KERN KERN_SECURELVL.
18  */
19 static int
20 mib_kern_securelvl(struct mib_call * call __unused, struct mib_node * node,
21 	void * ptr, size_t size __unused)
22 {
23 	int v;
24 
25 	memcpy(&v, ptr, sizeof(v));
26 
27 	/*
28 	 * Only ever allow the security level to be increased.  This is a mock
29 	 * implementation.  TODO: implement actual support for security levels.
30 	 */
31 	return (v >= node->node_int);
32 }
33 
34 /*
35  * Implementation of CTL_KERN KERN_CLOCKRATE.
36  */
37 static ssize_t
38 mib_kern_clockrate(struct mib_call * call __unused,
39 	struct mib_node * node __unused, struct mib_oldp * oldp,
40 	struct mib_newp * newp __unused)
41 {
42 	struct clockinfo clockinfo;
43 
44 	memset(&clockinfo, 0, sizeof(clockinfo));
45 
46 	clockinfo.hz = sys_hz();
47 	clockinfo.tick = 1000000 / clockinfo.hz;
48 	clockinfo.profhz = clockinfo.hz;
49 	clockinfo.stathz = clockinfo.hz;
50 
51 	/*
52 	 * Number of microseconds that can be corrected per clock tick through
53 	 * adjtime(2).  The kernel allows correction of one clock tick per
54 	 * clock tick, which means it should be the same as .tick.. I think.
55 	 * TODO: get this from the kernel itself.
56 	 */
57 	clockinfo.tickadj = clockinfo.tick;
58 
59 	return mib_copyout(oldp, 0, &clockinfo, sizeof(clockinfo));
60 }
61 
62 /*
63  * Implementation of CTL_KERN KERN_PROFILING.
64  */
65 static ssize_t
66 mib_kern_profiling(struct mib_call * call __unused,
67 	struct mib_node * node __unused, struct mib_oldp * oldp __unused,
68 	struct mib_newp * newp __unused)
69 {
70 
71 	/* As per sysctl(7).  We have a different profiling API. */
72 	return EOPNOTSUPP;
73 }
74 
75 /*
76  * Implementation of CTL_KERN KERN_HARDCLOCK_TICKS.
77  */
78 static ssize_t
79 mib_kern_hardclock_ticks(struct mib_call * call __unused,
80 	struct mib_node * node __unused, struct mib_oldp * oldp,
81 	struct mib_newp * newp __unused)
82 {
83 	int uptime;
84 
85 	/*
86 	 * The number of hardclock (hardware clock driver) ticks is what we
87 	 * call the number of monotonic clock ticks AKA the uptime clock ticks.
88 	 */
89 	uptime = (int)getticks();
90 
91 	return mib_copyout(oldp, 0, &uptime, sizeof(uptime));
92 }
93 
94 /*
95  * Implementation of CTL_KERN KERN_ROOT_DEVICE.
96  */
97 static ssize_t
98 mib_kern_root_device(struct mib_call * call __unused,
99 	struct mib_node * node __unused, struct mib_oldp * oldp,
100 	struct mib_newp * newp __unused)
101 {
102 	char name[PATH_MAX];
103 	struct sysgetenv sysgetenv;
104 
105 	sysgetenv.key = __UNCONST("rootdevname");
106 	sysgetenv.keylen = strlen(sysgetenv.key) + 1;
107 	sysgetenv.val = name;
108 	sysgetenv.vallen = sizeof(name);
109 
110 	if (svrctl(PMGETPARAM, &sysgetenv) != 0)
111 		return EINVAL;
112 
113 	name[MIN(sysgetenv.vallen, sizeof(name) - 1)] = '\0';
114 
115 	return mib_copyout(oldp, 0, name, strlen(name) + 1);
116 }
117 
118 /*
119  * Implementation of CTL_KERN KERN_CCPU.
120  */
121 static ssize_t
122 mib_kern_ccpu(struct mib_call * call __unused,
123 	struct mib_node * node __unused, struct mib_oldp * oldp,
124 	struct mib_newp * newp __unused)
125 {
126 	int ccpu;
127 
128 	ccpu = (int)cpuavg_getccpu();
129 
130 	return mib_copyout(oldp, 0, &ccpu, sizeof(ccpu));
131 }
132 
133 /*
134  * Implementation of CTL_KERN KERN_CP_TIME.
135  */
136 static ssize_t
137 mib_kern_cp_time(struct mib_call * call, struct mib_node * node __unused,
138 	struct mib_oldp * oldp, struct mib_newp * newp __unused)
139 {
140 	uint64_t ticks[MINIX_CPUSTATES], sum[MINIX_CPUSTATES];
141 	unsigned int cpu;
142 	int i, r, do_sum;
143 
144 	/*
145 	 * If a subnode is provided, it identifies the CPU number for which to
146 	 * return information.  If no subnode is provided, but a size is given
147 	 * that allows returning information for all CPUs, return information
148 	 * for all of them in an array.  If no such size is given either,
149 	 * return a summation of all CPU statistics.  Both we and the kernel
150 	 * are considering the number of configured CPUs (hw.ncpu).
151 	 */
152 	if (call->call_namelen > 1)
153 		return EINVAL;
154 
155 	if (call->call_namelen == 1) {
156 		/* Do not bother saving on this call if oldp is NULL. */
157 		if ((r = sys_getcputicks(ticks, call->call_name[0])) != OK)
158 			return r;
159 
160 		return mib_copyout(oldp, 0, ticks, sizeof(ticks));
161 	}
162 
163 	if (oldp == NULL)
164 		return sizeof(ticks); /* implying a summation request */
165 
166 	do_sum = (mib_getoldlen(oldp) == sizeof(ticks));
167 
168 	if (do_sum)
169 		memset(&sum, 0, sizeof(sum));
170 
171 	for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) {
172 		if ((r = sys_getcputicks(ticks, cpu)) != OK)
173 			return r;
174 
175 		if (do_sum) {
176 			for (i = 0; i < MINIX_CPUSTATES; i++)
177 				sum[i] += ticks[i];
178 		} else {
179 			if ((r = mib_copyout(oldp, cpu * sizeof(ticks), ticks,
180 			    sizeof(ticks))) < 0)
181 				return r;
182 		}
183 	}
184 
185 	if (do_sum)
186 		return mib_copyout(oldp, 0, sum, sizeof(sum));
187 	else
188 		return cpu * sizeof(ticks);
189 }
190 
191 /*
192  * Implementation of CTL_KERN KERN_CONSDEV.
193  */
194 static ssize_t
195 mib_kern_consdev(struct mib_call * call __unused,
196 	struct mib_node * node __unused, struct mib_oldp * oldp,
197 	struct mib_newp * newp __unused)
198 {
199 	dev_t dev;
200 
201 	dev = makedev(TTY_MAJOR, CONS_MINOR);
202 
203 	/* No support for legacy 32-bit requests. */
204 	return mib_copyout(oldp, 0, &dev, sizeof(dev));
205 }
206 
207 /*
208  * Verification for CTL_KERN KERN_FORKFSLEEP.
209  */
210 static int
211 mib_kern_forkfsleep(struct mib_call * call __unused,
212 	struct mib_node * node __unused, void * ptr, size_t size __unused)
213 {
214 	int v;
215 
216 	memcpy(&v, ptr, sizeof(v));
217 
218 	return (v >= 0 && v <= MAXSLP * 1000); /* rules from NetBSD */
219 }
220 
221 /*
222  * Implementation of CTL_KERN KERN_DRIVERS.
223  */
224 static ssize_t
225 mib_kern_drivers(struct mib_call * call __unused,
226 	struct mib_node * node __unused, struct mib_oldp * oldp,
227 	struct mib_newp * newp __unused)
228 {
229 	struct dmap dmap_tab[NR_DEVICES];
230 	struct kinfo_drivers drivers[NR_DEVICES + 1];
231 	unsigned int count;
232 	devmajor_t maj;
233 
234 	/*
235 	 * On MINIX3, we list only drivers that are actually running.
236 	 */
237 
238 	if (getsysinfo(VFS_PROC_NR, SI_DMAP_TAB, dmap_tab,
239 	    sizeof(dmap_tab)) != OK)
240 		return EINVAL;
241 
242 	count = 0;
243 
244 	/*
245 	 * Compatibility hack.  NetBSD userland expects that the name of the
246 	 * PTY driver is "pts".  Add an extra entry for this purpose if needed.
247 	 */
248 	if (dmap_tab[PTY_MAJOR].dmap_driver != NONE &&
249 	    strcmp(dmap_tab[PTY_MAJOR].dmap_label, "pts")) {
250 		if (mib_inrange(oldp, 0)) {
251 			memset(&drivers[0], 0, sizeof(drivers[0]));
252 			strlcpy(drivers[count].d_name, "pts",
253 			    sizeof(drivers[0].d_name));
254 			drivers[count].d_bmajor = -1;
255 			drivers[count].d_cmajor = PTY_MAJOR;
256 		}
257 		count++;
258 	}
259 
260 	for (maj = 0; maj < NR_DEVICES; maj++) {
261 		if (dmap_tab[maj].dmap_driver == NONE)
262 			continue;
263 
264 		if (mib_inrange(oldp, sizeof(drivers[0]) * count)) {
265 			memset(&drivers[count], 0, sizeof(drivers[0]));
266 
267 			strlcpy(drivers[count].d_name,
268 			    dmap_tab[maj].dmap_label,
269 			    sizeof(drivers[0].d_name));
270 
271 			/*
272 			 * We do not know whether the device is a block device,
273 			 * character device, or both.  In any case, a driver
274 			 * has only one major number.
275 			 */
276 			drivers[count].d_bmajor = maj;
277 			drivers[count].d_cmajor = maj;
278 		}
279 		count++;
280 	}
281 
282 	return mib_copyout(oldp, 0, drivers, count * sizeof(drivers[0]));
283 }
284 
285 /*
286  * Implementation of CTL_KERN KERN_BOOTTIME.
287  */
288 static ssize_t
289 mib_kern_boottime(struct mib_call * call __unused,
290 	struct mib_node * node __unused, struct mib_oldp * oldp,
291 	struct mib_newp * newp __unused)
292 {
293 	struct timeval tv;
294 
295 	memset(&tv, 0, sizeof(tv));
296 
297 	if (getuptime(NULL, NULL, &tv.tv_sec) != OK)
298 		return EINVAL;
299 
300 	return mib_copyout(oldp, 0, &tv, sizeof(tv));
301 }
302 
303 /*
304  * Copy over an ipc_perm structure to an ipc_perm_sysctl structure.
305  */
306 static void
307 prepare_ipc_perm(struct ipc_perm_sysctl * perms, const struct ipc_perm * perm)
308 {
309 
310 	memset(perms, 0, sizeof(*perms));
311 	perms->_key = perm->_key;
312 	perms->uid = perm->uid;
313 	perms->gid = perm->gid;
314 	perms->cuid = perm->cuid;
315 	perms->cgid = perm->cgid;
316 	perms->mode = perm->mode;
317 	perms->_seq = perm->_seq;
318 }
319 
320 /*
321  * Implementation of CTL_KERN KERN_SYSVIPC KERN_SYSVIPC_INFO.
322  */
323 static ssize_t
324 mib_kern_ipc_info(struct mib_call * call, struct mib_node * node __unused,
325 	struct mib_oldp * oldp, struct mib_newp * newp __unused)
326 {
327 	struct sem_sysctl_info semsi;
328 	struct shm_sysctl_info shmsi;
329 	struct semid_ds semds;
330 	struct shmid_ds shmds;
331 	ssize_t r, off;
332 	int i, max;
333 
334 	if (call->call_namelen != 1)
335 		return EINVAL;
336 
337 	/*
338 	 * An important security note: according to the specification, IPC_STAT
339 	 * (and therefore, logically, its SEM_STAT and SHM_STAT siblings)
340 	 * performs read access checks on the caller, meaning that users other
341 	 * than root may not obtain details about IPC objects for which they do
342 	 * not have permission.  However, NetBSD's sysctl(2) interface to
343 	 * obtain the same information, which we mimic here, does *not* perform
344 	 * such permission checks.  For that reason, neither do we; the MIB
345 	 * service is running as root, so it can freely make stat calls, and
346 	 * expose the results to all users on the system.  If this is to be
347 	 * changed in the future, we would probably be better off moving the
348 	 * processing of this sysctl(2) node into the IPC server altogether.
349 	 */
350 	off = 0;
351 
352 	switch (call->call_name[0]) {
353 	case KERN_SYSVIPC_SEM_INFO:
354 		memset(&semsi, 0, sizeof(semsi));
355 		if ((max = semctl(0, 0, IPC_INFO, &semsi.seminfo)) == -1)
356 			return -errno;
357 		/*
358 		 * As a hackish exception, the requested size may imply that
359 		 * just general information is to be returned, without throwing
360 		 * an ENOMEM error because there is no space for full output.
361 		 */
362 		if (mib_getoldlen(oldp) == sizeof(semsi.seminfo))
363 			return mib_copyout(oldp, 0, &semsi.seminfo,
364 			    sizeof(semsi.seminfo));
365 		/*
366 		 * ipcs(1) blindly expects the returned array to be of size
367 		 * seminfo.semmni, using the SEM_ALLOC mode flag to see whether
368 		 * each entry is valid.  If we return a smaller size, ipcs(1)
369 		 * will access arbitrary memory.
370 		 */
371 		if (semsi.seminfo.semmni <= 0)
372 			return EINVAL;
373 		if (oldp == NULL)
374 			return sizeof(semsi) + sizeof(semsi.semids[0]) *
375 			    (semsi.seminfo.semmni - 1);
376 		/*
377 		 * Copy out entries one by one.  For the first entry, copy out
378 		 * the entire "semsi" structure.  For subsequent entries, reuse
379 		 * the single embedded 'semids' element of "semsi", and copy
380 		 * out only that element.
381 		 */
382 		for (i = 0; i < semsi.seminfo.semmni; i++) {
383 			memset(&semsi.semids[0], 0, sizeof(semsi.semids[0]));
384 			if (i <= max && semctl(i, 0, SEM_STAT, &semds) >= 0) {
385 				prepare_ipc_perm(&semsi.semids[0].sem_perm,
386 				    &semds.sem_perm);
387 				semsi.semids[0].sem_nsems = semds.sem_nsems;
388 				semsi.semids[0].sem_otime = semds.sem_otime;
389 				semsi.semids[0].sem_ctime = semds.sem_ctime;
390 			}
391 			if (off == 0)
392 				r = mib_copyout(oldp, off, &semsi,
393 				    sizeof(semsi));
394 			else
395 				r = mib_copyout(oldp, off, &semsi.semids[0],
396 				    sizeof(semsi.semids[0]));
397 			if (r < 0)
398 				return r;
399 			off += r;
400 		}
401 		break;
402 	case KERN_SYSVIPC_SHM_INFO:
403 		memset(&shmsi, 0, sizeof(shmsi));
404 		if ((max = shmctl(0, IPC_INFO,
405 		    (struct shmid_ds *)&shmsi.shminfo)) == -1)
406 			return -errno;
407 		/*
408 		 * As a hackish exception, the requested size may imply that
409 		 * just general information is to be returned, without throwing
410 		 * an ENOMEM error because there is no space for full output.
411 		 */
412 		if (mib_getoldlen(oldp) == sizeof(shmsi.shminfo))
413 			return mib_copyout(oldp, 0, &shmsi.shminfo,
414 			    sizeof(shmsi.shminfo));
415 		/*
416 		 * ipcs(1) blindly expects the returned array to be of size
417 		 * shminfo.shmmni, using the SHMSEG_ALLOCATED (not exposed,
418 		 * 0x0800) mode flag to see whether each entry is valid.  If we
419 		 * return a smaller size, ipcs(1) will access arbitrary memory.
420 		 */
421 		if (shmsi.shminfo.shmmni <= 0)
422 			return EINVAL;
423 		if (oldp == NULL)
424 			return sizeof(shmsi) + sizeof(shmsi.shmids[0]) *
425 			    (shmsi.shminfo.shmmni - 1);
426 		/*
427 		 * Copy out entries one by one.  For the first entry, copy out
428 		 * the entire "shmsi" structure.  For subsequent entries, reuse
429 		 * the single embedded 'shmids' element of "shmsi", and copy
430 		 * out only that element.
431 		 */
432 		for (i = 0; i < (int)shmsi.shminfo.shmmni; i++) {
433 			memset(&shmsi.shmids[0], 0, sizeof(shmsi.shmids[0]));
434 			if (i <= max && shmctl(i, SHM_STAT, &shmds) == 0) {
435 				prepare_ipc_perm(&shmsi.shmids[0].shm_perm,
436 				    &shmds.shm_perm);
437 				shmsi.shmids[0].shm_perm.mode |= 0x0800;
438 				shmsi.shmids[0].shm_segsz = shmds.shm_segsz;
439 				shmsi.shmids[0].shm_lpid = shmds.shm_lpid;
440 				shmsi.shmids[0].shm_cpid = shmds.shm_cpid;
441 				shmsi.shmids[0].shm_atime = shmds.shm_atime;
442 				shmsi.shmids[0].shm_dtime = shmds.shm_dtime;
443 				shmsi.shmids[0].shm_ctime = shmds.shm_ctime;
444 				shmsi.shmids[0].shm_nattch = shmds.shm_nattch;
445 			}
446 			if (off == 0)
447 				r = mib_copyout(oldp, off, &shmsi,
448 				    sizeof(shmsi));
449 			else
450 				r = mib_copyout(oldp, off, &shmsi.shmids[0],
451 				    sizeof(shmsi.shmids[0]));
452 			if (r < 0)
453 				return r;
454 			off += r;
455 		}
456 		break;
457 	default:
458 		return EOPNOTSUPP;
459 	}
460 
461 	return off;
462 }
463 
464 /* The CTL_KERN KERN_SYSVIPC nodes. */
465 static struct mib_node mib_kern_ipc_table[] = {
466 /* 1*/	[KERN_SYSVIPC_INFO]	= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
467 				    mib_kern_ipc_info, "sysvipc_info",
468 				    "System V style IPC information"),
469 /* 2*/	[KERN_SYSVIPC_MSG]	= MIB_INT(_P | _RO, 0, "sysvmsg", "System V "
470 				    "style message support available"),
471 /* 3*/	[KERN_SYSVIPC_SEM]	= MIB_INT(_P | _RO, 1, "sysvsem", "System V "
472 				    "style semaphore support available"),
473 /* 4*/	[KERN_SYSVIPC_SHM]	= MIB_INT(_P | _RO, 1, "sysvshm", "System V "
474 				    "style shared memory support available"),
475 /* 5*/	/* KERN_SYSVIPC_SHMMAX: not yet supported */
476 /* 6*/	/* KERN_SYSVIPC_SHMMNI: not yet supported */
477 /* 7*/	/* KERN_SYSVIPC_SHMSEG: not yet supported */
478 /* 8*/	/* KERN_SYSVIPC_SHMMAXPGS: not yet supported */
479 /* 9*/	/* KERN_SYSVIPC_SHMUSEPHYS: not yet supported */
480 	/* In addition, NetBSD has a number of dynamic nodes here. */
481 };
482 
483 /* The CTL_KERN nodes. */
484 static struct mib_node mib_kern_table[] = {
485 /* 1*/	[KERN_OSTYPE]		= MIB_STRING(_P | _RO, OS_NAME, "ostype",
486 				    "Operating system type"),
487 /* 2*/	[KERN_OSRELEASE]	= MIB_STRING(_P | _RO, OS_RELEASE, "osrelease",
488 				    "Operating system release"),
489 /* 3*/	[KERN_OSREV]		= MIB_INT(_P | _RO , OS_REV, "osrevision",
490 				    "Operating system revision"),
491 /* 4*/	[KERN_VERSION]		= MIB_STRING(_P | _RO, OS_VERSION, "version",
492 				    "Kernel version"),
493 /* 5*/	[KERN_MAXVNODES]	= MIB_INT(_P | _RO, NR_VNODES, "maxvnodes",
494 				    "Maximum number of vnodes"),
495 /* 6*/	[KERN_MAXPROC]		= MIB_INT(_P | _RO, NR_PROCS, "maxproc",
496 				    "Maximum number of simultaneous "
497 				    "processes"),
498 /* 7*/	[KERN_MAXFILES]		= MIB_INT(_P | _RO, NR_VNODES, "maxfiles",
499 				    "Maximum number of open files"),
500 /* 8*/	[KERN_ARGMAX]		= MIB_INT(_P | _RO, ARG_MAX, "argmax",
501 				    "Maximum number of bytes of arguments to "
502 				    "execve(2)"),
503 /* 9*/	[KERN_SECURELVL]	= MIB_INTV(_P | _RW, -1, mib_kern_securelvl,
504 				    "securelevel", "System security level"),
505 /*10*/	[KERN_HOSTNAME]		= MIB_STRING(_P | _RW, hostname, "hostname",
506 				    "System hostname"),
507 /*11*/	[KERN_HOSTID]		= MIB_INT(_P | _RW | CTLFLAG_HEX, 0, "hostid",
508 				    "System host ID number"),
509 /*12*/	[KERN_CLOCKRATE]	= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
510 				    sizeof(struct clockinfo),
511 				    mib_kern_clockrate, "clockrate",
512 				    "Kernel clock rates"),
513 /*13*/	/* KERN_VNODE: not yet implemented */
514 /*14*/	/* KERN_PROC: not yet implemented */
515 /*15*/	/* KERN_FILE: not yet implemented */
516 /*16*/	[KERN_PROF]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
517 				    mib_kern_profiling, "profiling",
518 				    "Profiling information (not available)"),
519 /*17*/	[KERN_POSIX1]		= MIB_INT(_P | _RO, _POSIX_VERSION,
520 				    "posix1version", "Version of ISO/IEC 9945 "
521 				    "(POSIX 1003.1) with which the operating "
522 				    "system attempts to comply"),
523 /*18*/	[KERN_NGROUPS]		= MIB_INT(_P | _RO, NGROUPS_MAX, "ngroups",
524 				    "Maximum number of supplemental groups"),
525 /*19*/	[KERN_JOB_CONTROL]	= MIB_INT(_P | _RO, 0, "job_control",
526 				    "Whether job control is available"),
527 /*20*/	[KERN_SAVED_IDS]	= MIB_INT(_P | _RO, 0, "saved_ids",
528 				    "Whether POSIX saved set-group/user ID is "
529 				    "available"),
530 /*21*/	/* KERN_OBOOTTIME: obsolete */
531 /*22*/	[KERN_DOMAINNAME]	= MIB_STRING(_P | _RW, domainname,
532 				    "domainname", "YP domain name"),
533 /*23*/	[KERN_MAXPARTITIONS]	= MIB_INT(_P | _RO, NR_PARTITIONS,
534 				    "maxpartitions", "Maximum number of "
535 				    "partitions allowed per disk"),
536 /*24*/	/* KERN_RAWPARTITION: incompatible with our device node scheme */
537 /*25*/	/* KERN_NTPTIME: not yet supported */
538 /*26*/	/* KERN_TIMEX: not yet supported */
539 /*27*/	/* KERN_AUTONICETIME: not yet supported */
540 /*28*/	/* KERN_AUTONICEVAL: not yet supported */
541 /*29*/	[KERN_RTC_OFFSET]	= MIB_INT(_P | _RW, 0, "rtc_offset", "Offset "
542 				    "of real time clock from UTC in minutes"),
543 /*30*/	[KERN_ROOT_DEVICE]	= MIB_FUNC(_P | _RO | CTLTYPE_STRING, 0,
544 				    mib_kern_root_device, "root_device",
545 				    "Name of the root device"),
546 /*31*/	[KERN_MSGBUFSIZE]	= MIB_INT(_P | _RO, DIAG_BUFSIZE, "msgbufsize",
547 				    "Size of the kernel message buffer"),
548 /*32*/	[KERN_FSYNC]		= MIB_INT(_P | _RO, 1, "fsync", "Whether the "
549 				    "POSIX 1003.1b File Synchronization Option"
550 				    " is available on this system"),
551 /*33*/	/* KERN_OLDSYSVMSG: obsolete */
552 /*34*/	/* KERN_OLDSYSVSEM: obsolete */
553 /*35*/	/* KERN_OLDSYSVSHM: obsolete */
554 /*36*/	/* KERN_OLDSHORTCORENAME: obsolete */
555 /*37*/	[KERN_SYNCHRONIZED_IO]	= MIB_INT(_P | _RO, 0, "synchronized_io",
556 				    "Whether the POSIX 1003.1b Synchronized "
557 				    "I/O Option is available on this system"),
558 /*38*/	[KERN_IOV_MAX]		= MIB_INT(_P | _RO, IOV_MAX, "iov_max",
559 				    "Maximum number of iovec structures per "
560 				    "process"),
561 /*39*/	/* KERN_MBUF: not yet supported */
562 /*40*/	[KERN_MAPPED_FILES]	= MIB_INT(_P | _RO, 1, "mapped_files",
563 				    "Whether the POSIX 1003.1b Memory Mapped "
564 				    "Files Option is available on this "
565 				    "system"),
566 /*41*/	[KERN_MEMLOCK]		= MIB_INT(_P | _RO, 0, "memlock", "Whether "
567 				    "the POSIX 1003.1b Process Memory Locking "
568 				    "Option is available on this system"),
569 /*42*/	[KERN_MEMLOCK_RANGE]	= MIB_INT(_P | _RO, 0, "memlock_range",
570 				    "Whether the POSIX 1003.1b Range Memory "
571 				    "Locking Option is available on this "
572 				    "system"),
573 /*43*/	[KERN_MEMORY_PROTECTION]= MIB_INT(_P | _RO, 0, "memory_protection",
574 				    "Whether the POSIX 1003.1b Memory "
575 				    "Protection Option is available on this "
576 				    "system"),
577 /*44*/	/* KERN_LOGIN_NAME_MAX: not yet supported */
578 /*45*/	/* KERN_DEFCORENAME: obsolete */
579 /*46*/	/* KERN_LOGSIGEXIT: not yet supported */
580 /*47*/	[KERN_PROC2]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
581 				    mib_kern_proc2, "proc2",
582 				    "Machine-independent process information"),
583 /*48*/	[KERN_PROC_ARGS]	= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
584 				    mib_kern_proc_args, "proc_args",
585 				    "Process argument information"),
586 /*49*/	[KERN_FSCALE]		= MIB_INT(_P | _RO, FSCALE, "fscale",
587 				    "Kernel fixed-point scale factor"),
588 /*50*/	[KERN_CCPU]		= MIB_FUNC(_P | _RO | CTLTYPE_INT, sizeof(int),
589 				    mib_kern_ccpu, "ccpu",
590 				    "Scheduler exponential decay value"),
591 /*51*/	[KERN_CP_TIME]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
592 				    mib_kern_cp_time, "cp_time", "Clock ticks "
593 				    "spent in different CPU states"),
594 /*52*/	/* KERN_OLDSYSVIPC_INFO: obsolete */
595 /*53*/	/* KERN_MSGBUF: not yet supported */
596 /*54*/	[KERN_CONSDEV]		= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
597 				    sizeof(dev_t), mib_kern_consdev, "consdev",
598 				    "Console device"),
599 /*55*/	[KERN_MAXPTYS]		= MIB_INT(_P | _RO, NR_PTYS, "maxptys",
600 				    "Maximum number of pseudo-ttys"),
601 /*56*/	/* KERN_PIPE: not yet supported */
602 /*57*/	[KERN_MAXPHYS]		= MIB_INT(_P | _RO, 4*1024*1024, "maxphys",
603 				    "Maximum raw I/O transfer size"),
604 				    /* 4MB is the upper limit for AHCI */
605 /*58*/	/* KERN_SBMAX: not yet supported */
606 /*59*/	/* KERN_TKSTAT: not yet supported */
607 /*60*/	[KERN_MONOTONIC_CLOCK]	= MIB_INT(_P | _RO, _POSIX_MONOTONIC_CLOCK,
608 				    "monotonic_clock",
609 				    "Implementation version of the POSIX "
610 				    "1003.1b Monotonic Clock Option"),
611 /*61*/	/* KERN_URND: not yet supported */
612 /*62*/	/* KERN_LABELSECTOR: not yet supported */
613 /*63*/	/* KERN_LABELOFFSET: not yet supported */
614 /*64*/	[KERN_LWP]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
615 				    mib_kern_lwp, "lwp",
616 				    "System-wide LWP information"),
617 /*65*/	[KERN_FORKFSLEEP]	= MIB_INTV(_P | _RW, 0, mib_kern_forkfsleep,
618 				    "forkfsleep", "Milliseconds to sleep on "
619 				    "fork failure due to process limits"),
620 /*66*/	/* KERN_POSIX_THREADS: not yet supported */
621 /*67*/	/* KERN_POSIX_SEMAPHORES: not yet supported */
622 /*68*/	/* KERN_POSIX_BARRIERS: not yet supported */
623 /*69*/	/* KERN_POSIX_TIMERS: not yet supported */
624 /*70*/	/* KERN_POSIX_SPIN_LOCKS: not yet supported */
625 /*71*/	/* KERN_POSIX_READER_WRITER_LOCKS: not yet supported */
626 /*72*/	[KERN_DUMP_ON_PANIC]	= MIB_INT(_P | _RO, 0, "dump_on_panic",
627 				    "Perform a crash dump on system panic"),
628 /*73*/	/* KERN_SOMAXKVA: not yet supported */
629 /*74*/	/* KERN_ROOT_PARTITION: incompatible with our device node scheme */
630 /*75*/	[KERN_DRIVERS]		= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT, 0,
631 				    mib_kern_drivers, "drivers",
632 				    "List of all drivers with block and "
633 				    "character device numbers"),
634 /*76*/	/* KERN_BUF: not yet supported */
635 /*77*/	/* KERN_FILE2: not yet supported */
636 /*78*/	/* KERN_VERIEXEC: not yet supported */
637 /*79*/	/* KERN_CP_ID: not yet supported */
638 /*80*/	[KERN_HARDCLOCK_TICKS]	= MIB_FUNC(_P | _RO | CTLFLAG_UNSIGNED |
639 				    CTLTYPE_INT, sizeof(int),
640 				    mib_kern_hardclock_ticks,
641 				    "hardclock_ticks",
642 				    "Number of hardclock ticks"),
643 /*81*/	/* KERN_ARND: not yet supported */
644 /*82*/	[KERN_SYSVIPC]		= MIB_NODE(_P | _RO, mib_kern_ipc_table, "ipc",
645 				    "SysV IPC options"),
646 /*83*/	[KERN_BOOTTIME]		= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
647 				    sizeof(struct timeval), mib_kern_boottime,
648 				    "boottime", "System boot time"),
649 /*84*/	/* KERN_EVCNT: not yet supported */
650 };
651 
652 /*
653  * Initialize the CTL_KERN subtree.
654  */
655 void
656 mib_kern_init(struct mib_node * node)
657 {
658 
659 	MIB_INIT_ENODE(node, mib_kern_table);
660 }
661