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 9 #include "servers/vfs/const.h" 10 #include "servers/vfs/dmap.h" 11 12 static char hostname[MAXHOSTNAMELEN], domainname[MAXHOSTNAMELEN]; 13 14 /* 15 * Verification for CTL_KERN KERN_SECURELVL. 16 */ 17 static int 18 mib_kern_securelvl(struct mib_call * call __unused, struct mib_node * node, 19 void * ptr, size_t size __unused) 20 { 21 int v; 22 23 memcpy(&v, ptr, sizeof(v)); 24 25 /* 26 * Only ever allow the security level to be increased. This is a mock 27 * implementation. TODO: implement actual support for security levels. 28 */ 29 return (v >= node->node_int); 30 } 31 32 /* 33 * Implementation of CTL_KERN KERN_CLOCKRATE. 34 */ 35 static ssize_t 36 mib_kern_clockrate(struct mib_call * call __unused, 37 struct mib_node * node __unused, struct mib_oldp * oldp, 38 struct mib_newp * newp __unused) 39 { 40 struct clockinfo clockinfo; 41 42 memset(&clockinfo, 0, sizeof(clockinfo)); 43 44 clockinfo.hz = sys_hz(); 45 clockinfo.tick = 1000000 / clockinfo.hz; 46 clockinfo.profhz = clockinfo.hz; 47 clockinfo.stathz = clockinfo.hz; 48 49 /* 50 * Number of microseconds that can be corrected per clock tick through 51 * adjtime(2). The kernel allows correction of one clock tick per 52 * clock tick, which means it should be the same as .tick.. I think. 53 * TODO: get this from the kernel itself. 54 */ 55 clockinfo.tickadj = clockinfo.tick; 56 57 return mib_copyout(oldp, 0, &clockinfo, sizeof(clockinfo)); 58 } 59 60 /* 61 * Implementation of CTL_KERN KERN_PROFILING. 62 */ 63 static ssize_t 64 mib_kern_profiling(struct mib_call * call __unused, 65 struct mib_node * node __unused, struct mib_oldp * oldp __unused, 66 struct mib_newp * newp __unused) 67 { 68 69 /* As per sysctl(7). We have a different profiling API. */ 70 return EOPNOTSUPP; 71 } 72 73 /* 74 * Implementation of CTL_KERN KERN_HARDCLOCK_TICKS. 75 */ 76 static ssize_t 77 mib_kern_hardclock_ticks(struct mib_call * call __unused, 78 struct mib_node * node __unused, struct mib_oldp * oldp, 79 struct mib_newp * newp __unused) 80 { 81 int uptime; 82 83 /* 84 * The number of hardclock (hardware clock driver) ticks is what we 85 * call the number of monotonic clock ticks AKA the uptime clock ticks. 86 */ 87 uptime = (int)getticks(); 88 89 return mib_copyout(oldp, 0, &uptime, sizeof(uptime)); 90 } 91 92 /* 93 * Implementation of CTL_KERN KERN_ROOT_DEVICE. 94 */ 95 static ssize_t 96 mib_kern_root_device(struct mib_call * call __unused, 97 struct mib_node * node __unused, struct mib_oldp * oldp, 98 struct mib_newp * newp __unused) 99 { 100 char name[PATH_MAX]; 101 struct sysgetenv sysgetenv; 102 103 sysgetenv.key = __UNCONST("rootdevname"); 104 sysgetenv.keylen = strlen(sysgetenv.key) + 1; 105 sysgetenv.val = name; 106 sysgetenv.vallen = sizeof(name); 107 108 if (svrctl(PMGETPARAM, &sysgetenv) != 0) 109 return EINVAL; 110 111 name[MIN(sysgetenv.vallen, sizeof(name) - 1)] = '\0'; 112 113 return mib_copyout(oldp, 0, name, strlen(name) + 1); 114 } 115 116 /* 117 * Implementation of CTL_KERN KERN_CCPU. 118 */ 119 static ssize_t 120 mib_kern_ccpu(struct mib_call * call __unused, 121 struct mib_node * node __unused, struct mib_oldp * oldp, 122 struct mib_newp * newp __unused) 123 { 124 int ccpu; 125 126 ccpu = (int)cpuavg_getccpu(); 127 128 return mib_copyout(oldp, 0, &ccpu, sizeof(ccpu)); 129 } 130 131 /* 132 * Implementation of CTL_KERN KERN_CP_TIME. 133 */ 134 static ssize_t 135 mib_kern_cp_time(struct mib_call * call, struct mib_node * node __unused, 136 struct mib_oldp * oldp, struct mib_newp * newp __unused) 137 { 138 uint64_t ticks[MINIX_CPUSTATES], sum[MINIX_CPUSTATES]; 139 unsigned int cpu; 140 int i, r, do_sum; 141 142 /* 143 * If a subnode is provided, it identifies the CPU number for which to 144 * return information. If no subnode is provided, but a size is given 145 * that allows returning information for all CPUs, return information 146 * for all of them in an array. If no such size is given either, 147 * return a summation of all CPU statistics. Both we and the kernel 148 * are considering the number of configured CPUs (hw.ncpu). 149 */ 150 if (call->call_namelen > 1) 151 return EINVAL; 152 153 if (call->call_namelen == 1) { 154 /* Do not bother saving on this call if oldp is NULL. */ 155 if ((r = sys_getcputicks(ticks, call->call_name[0])) != OK) 156 return r; 157 158 return mib_copyout(oldp, 0, ticks, sizeof(ticks)); 159 } 160 161 if (oldp == NULL) 162 return sizeof(ticks); /* implying a summation request */ 163 164 do_sum = (mib_getoldlen(oldp) == sizeof(ticks)); 165 166 if (do_sum) 167 memset(&sum, 0, sizeof(sum)); 168 169 for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) { 170 if ((r = sys_getcputicks(ticks, cpu)) != OK) 171 return r; 172 173 if (do_sum) { 174 for (i = 0; i < MINIX_CPUSTATES; i++) 175 sum[i] += ticks[i]; 176 } else { 177 if ((r = mib_copyout(oldp, cpu * sizeof(ticks), ticks, 178 sizeof(ticks))) < 0) 179 return r; 180 } 181 } 182 183 if (do_sum) 184 return mib_copyout(oldp, 0, sum, sizeof(sum)); 185 else 186 return cpu * sizeof(ticks); 187 } 188 189 /* 190 * Implementation of CTL_KERN KERN_CONSDEV. 191 */ 192 static ssize_t 193 mib_kern_consdev(struct mib_call * call __unused, 194 struct mib_node * node __unused, struct mib_oldp * oldp, 195 struct mib_newp * newp __unused) 196 { 197 dev_t dev; 198 199 dev = makedev(TTY_MAJOR, CONS_MINOR); 200 201 /* No support for legacy 32-bit requests. */ 202 return mib_copyout(oldp, 0, &dev, sizeof(dev)); 203 } 204 205 /* 206 * Verification for CTL_KERN KERN_FORKFSLEEP. 207 */ 208 static int 209 mib_kern_forkfsleep(struct mib_call * call __unused, 210 struct mib_node * node __unused, void * ptr, size_t size __unused) 211 { 212 int v; 213 214 memcpy(&v, ptr, sizeof(v)); 215 216 return (v >= 0 && v <= MAXSLP * 1000); /* rules from NetBSD */ 217 } 218 219 /* 220 * Implementation of CTL_KERN KERN_DRIVERS. 221 */ 222 static ssize_t 223 mib_kern_drivers(struct mib_call * call __unused, 224 struct mib_node * node __unused, struct mib_oldp * oldp, 225 struct mib_newp * newp __unused) 226 { 227 struct dmap dmap_tab[NR_DEVICES]; 228 struct kinfo_drivers drivers[NR_DEVICES + 1]; 229 unsigned int count; 230 devmajor_t maj; 231 232 /* 233 * On MINIX3, we list only drivers that are actually running. 234 */ 235 236 if (getsysinfo(VFS_PROC_NR, SI_DMAP_TAB, dmap_tab, 237 sizeof(dmap_tab)) != OK) 238 return EINVAL; 239 240 count = 0; 241 242 /* 243 * Compatibility hack. NetBSD userland expects that the name of the 244 * PTY driver is "pts". Add an extra entry for this purpose if needed. 245 */ 246 if (dmap_tab[PTY_MAJOR].dmap_driver != NONE && 247 strcmp(dmap_tab[PTY_MAJOR].dmap_label, "pts")) { 248 if (mib_inrange(oldp, 0)) { 249 memset(&drivers[0], 0, sizeof(drivers[0])); 250 strlcpy(drivers[count].d_name, "pts", 251 sizeof(drivers[0].d_name)); 252 drivers[count].d_bmajor = -1; 253 drivers[count].d_cmajor = PTY_MAJOR; 254 } 255 count++; 256 } 257 258 for (maj = 0; maj < NR_DEVICES; maj++) { 259 if (dmap_tab[maj].dmap_driver == NONE) 260 continue; 261 262 if (mib_inrange(oldp, sizeof(drivers[0]) * count)) { 263 memset(&drivers[count], 0, sizeof(drivers[0])); 264 265 strlcpy(drivers[count].d_name, 266 dmap_tab[maj].dmap_label, 267 sizeof(drivers[0].d_name)); 268 269 /* 270 * We do not know whether the device is a block device, 271 * character device, or both. In any case, a driver 272 * has only one major number. 273 */ 274 drivers[count].d_bmajor = maj; 275 drivers[count].d_cmajor = maj; 276 } 277 count++; 278 } 279 280 return mib_copyout(oldp, 0, drivers, count * sizeof(drivers[0])); 281 } 282 283 /* 284 * Implementation of CTL_KERN KERN_BOOTTIME. 285 */ 286 static ssize_t 287 mib_kern_boottime(struct mib_call * call __unused, 288 struct mib_node * node __unused, struct mib_oldp * oldp, 289 struct mib_newp * newp __unused) 290 { 291 struct timeval tv; 292 293 memset(&tv, 0, sizeof(tv)); 294 295 if (getuptime(NULL, NULL, &tv.tv_sec) != OK) 296 return EINVAL; 297 298 return mib_copyout(oldp, 0, &tv, sizeof(tv)); 299 } 300 301 /* 302 * Mock implementation of CTL_KERN KERN_SYSVIPC KERN_SYSVIPC_INFO. Normally, 303 * the IPC service overrides the entire "kern.ipc" subtree. Therefore, this 304 * function will only ever be called when the IPC service is *not* running. 305 */ 306 static ssize_t 307 mib_kern_ipc_info(struct mib_call * call, struct mib_node * node __unused, 308 struct mib_oldp * oldp __unused, struct mib_newp * newp __unused) 309 { 310 311 /* The caller must always specify the resouce type (sem/shm/msg). */ 312 if (call->call_namelen != 1) 313 return EINVAL; 314 315 return EOPNOTSUPP; 316 } 317 318 /* The CTL_KERN KERN_SYSVIPC nodes, when not overridden by the IPC service. */ 319 static struct mib_node mib_kern_ipc_table[] = { 320 /* 1*/ [KERN_SYSVIPC_INFO] = MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0, 321 mib_kern_ipc_info, "sysvipc_info", 322 "System V style IPC information"), 323 /* 2*/ [KERN_SYSVIPC_MSG] = MIB_INT(_P | _RO, 0, "sysvmsg", "System V " 324 "style message support available"), 325 /* 3*/ [KERN_SYSVIPC_SEM] = MIB_INT(_P | _RO, 0, "sysvsem", "System V " 326 "style semaphore support available"), 327 /* 4*/ [KERN_SYSVIPC_SHM] = MIB_INT(_P | _RO, 0, "sysvshm", "System V " 328 "style shared memory support available"), 329 }; 330 331 /* The CTL_KERN nodes. */ 332 static struct mib_node mib_kern_table[] = { 333 /* 1*/ [KERN_OSTYPE] = MIB_STRING(_P | _RO, OS_NAME, "ostype", 334 "Operating system type"), 335 /* 2*/ [KERN_OSRELEASE] = MIB_STRING(_P | _RO, OS_RELEASE, "osrelease", 336 "Operating system release"), 337 /* 3*/ [KERN_OSREV] = MIB_INT(_P | _RO , OS_REV, "osrevision", 338 "Operating system revision"), 339 /* 4*/ [KERN_VERSION] = MIB_STRING(_P | _RO, OS_VERSION, "version", 340 "Kernel version"), 341 /* 5*/ [KERN_MAXVNODES] = MIB_INT(_P | _RO, NR_VNODES, "maxvnodes", 342 "Maximum number of vnodes"), 343 /* 6*/ [KERN_MAXPROC] = MIB_INT(_P | _RO, NR_PROCS, "maxproc", 344 "Maximum number of simultaneous " 345 "processes"), 346 /* 7*/ [KERN_MAXFILES] = MIB_INT(_P | _RO, NR_VNODES, "maxfiles", 347 "Maximum number of open files"), 348 /* 8*/ [KERN_ARGMAX] = MIB_INT(_P | _RO, ARG_MAX, "argmax", 349 "Maximum number of bytes of arguments to " 350 "execve(2)"), 351 /* 9*/ [KERN_SECURELVL] = MIB_INTV(_P | _RW, -1, mib_kern_securelvl, 352 "securelevel", "System security level"), 353 /*10*/ [KERN_HOSTNAME] = MIB_STRING(_P | _RW, hostname, "hostname", 354 "System hostname"), 355 /*11*/ [KERN_HOSTID] = MIB_INT(_P | _RW | CTLFLAG_HEX, 0, "hostid", 356 "System host ID number"), 357 /*12*/ [KERN_CLOCKRATE] = MIB_FUNC(_P | _RO | CTLTYPE_STRUCT, 358 sizeof(struct clockinfo), 359 mib_kern_clockrate, "clockrate", 360 "Kernel clock rates"), 361 /*13*/ /* KERN_VNODE: not yet implemented */ 362 /*14*/ /* KERN_PROC: not yet implemented */ 363 /*15*/ /* KERN_FILE: not yet implemented */ 364 /*16*/ [KERN_PROF] = MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0, 365 mib_kern_profiling, "profiling", 366 "Profiling information (not available)"), 367 /*17*/ [KERN_POSIX1] = MIB_INT(_P | _RO, _POSIX_VERSION, 368 "posix1version", "Version of ISO/IEC 9945 " 369 "(POSIX 1003.1) with which the operating " 370 "system attempts to comply"), 371 /*18*/ [KERN_NGROUPS] = MIB_INT(_P | _RO, NGROUPS_MAX, "ngroups", 372 "Maximum number of supplemental groups"), 373 /*19*/ [KERN_JOB_CONTROL] = MIB_INT(_P | _RO, 0, "job_control", 374 "Whether job control is available"), 375 /*20*/ [KERN_SAVED_IDS] = MIB_INT(_P | _RO, 0, "saved_ids", 376 "Whether POSIX saved set-group/user ID is " 377 "available"), 378 /*21*/ /* KERN_OBOOTTIME: obsolete */ 379 /*22*/ [KERN_DOMAINNAME] = MIB_STRING(_P | _RW, domainname, 380 "domainname", "YP domain name"), 381 /*23*/ [KERN_MAXPARTITIONS] = MIB_INT(_P | _RO, NR_PARTITIONS, 382 "maxpartitions", "Maximum number of " 383 "partitions allowed per disk"), 384 /*24*/ /* KERN_RAWPARTITION: incompatible with our device node scheme */ 385 /*25*/ /* KERN_NTPTIME: not yet supported */ 386 /*26*/ /* KERN_TIMEX: not yet supported */ 387 /*27*/ /* KERN_AUTONICETIME: not yet supported */ 388 /*28*/ /* KERN_AUTONICEVAL: not yet supported */ 389 /*29*/ [KERN_RTC_OFFSET] = MIB_INT(_P | _RW, 0, "rtc_offset", "Offset " 390 "of real time clock from UTC in minutes"), 391 /*30*/ [KERN_ROOT_DEVICE] = MIB_FUNC(_P | _RO | CTLTYPE_STRING, 0, 392 mib_kern_root_device, "root_device", 393 "Name of the root device"), 394 /*31*/ [KERN_MSGBUFSIZE] = MIB_INT(_P | _RO, DIAG_BUFSIZE, "msgbufsize", 395 "Size of the kernel message buffer"), 396 /*32*/ [KERN_FSYNC] = MIB_INT(_P | _RO, 1, "fsync", "Whether the " 397 "POSIX 1003.1b File Synchronization Option" 398 " is available on this system"), 399 /*33*/ /* KERN_OLDSYSVMSG: obsolete */ 400 /*34*/ /* KERN_OLDSYSVSEM: obsolete */ 401 /*35*/ /* KERN_OLDSYSVSHM: obsolete */ 402 /*36*/ /* KERN_OLDSHORTCORENAME: obsolete */ 403 /*37*/ [KERN_SYNCHRONIZED_IO] = MIB_INT(_P | _RO, 0, "synchronized_io", 404 "Whether the POSIX 1003.1b Synchronized " 405 "I/O Option is available on this system"), 406 /*38*/ [KERN_IOV_MAX] = MIB_INT(_P | _RO, IOV_MAX, "iov_max", 407 "Maximum number of iovec structures per " 408 "process"), 409 /*39*/ /* KERN_MBUF: not yet supported */ 410 /*40*/ [KERN_MAPPED_FILES] = MIB_INT(_P | _RO, 1, "mapped_files", 411 "Whether the POSIX 1003.1b Memory Mapped " 412 "Files Option is available on this " 413 "system"), 414 /*41*/ [KERN_MEMLOCK] = MIB_INT(_P | _RO, 0, "memlock", "Whether " 415 "the POSIX 1003.1b Process Memory Locking " 416 "Option is available on this system"), 417 /*42*/ [KERN_MEMLOCK_RANGE] = MIB_INT(_P | _RO, 0, "memlock_range", 418 "Whether the POSIX 1003.1b Range Memory " 419 "Locking Option is available on this " 420 "system"), 421 /*43*/ [KERN_MEMORY_PROTECTION]= MIB_INT(_P | _RO, 0, "memory_protection", 422 "Whether the POSIX 1003.1b Memory " 423 "Protection Option is available on this " 424 "system"), 425 /*44*/ /* KERN_LOGIN_NAME_MAX: not yet supported */ 426 /*45*/ /* KERN_DEFCORENAME: obsolete */ 427 /*46*/ /* KERN_LOGSIGEXIT: not yet supported */ 428 /*47*/ [KERN_PROC2] = MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0, 429 mib_kern_proc2, "proc2", 430 "Machine-independent process information"), 431 /*48*/ [KERN_PROC_ARGS] = MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0, 432 mib_kern_proc_args, "proc_args", 433 "Process argument information"), 434 /*49*/ [KERN_FSCALE] = MIB_INT(_P | _RO, FSCALE, "fscale", 435 "Kernel fixed-point scale factor"), 436 /*50*/ [KERN_CCPU] = MIB_FUNC(_P | _RO | CTLTYPE_INT, sizeof(int), 437 mib_kern_ccpu, "ccpu", 438 "Scheduler exponential decay value"), 439 /*51*/ [KERN_CP_TIME] = MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0, 440 mib_kern_cp_time, "cp_time", "Clock ticks " 441 "spent in different CPU states"), 442 /*52*/ /* KERN_OLDSYSVIPC_INFO: obsolete */ 443 /*53*/ /* KERN_MSGBUF: not yet supported */ 444 /*54*/ [KERN_CONSDEV] = MIB_FUNC(_P | _RO | CTLTYPE_STRUCT, 445 sizeof(dev_t), mib_kern_consdev, "consdev", 446 "Console device"), 447 /*55*/ [KERN_MAXPTYS] = MIB_INT(_P | _RO, NR_PTYS, "maxptys", 448 "Maximum number of pseudo-ttys"), 449 /*56*/ /* KERN_PIPE: not yet supported */ 450 /*57*/ [KERN_MAXPHYS] = MIB_INT(_P | _RO, 4*1024*1024, "maxphys", 451 "Maximum raw I/O transfer size"), 452 /* 4MB is the upper limit for AHCI */ 453 /*58*/ /* KERN_SBMAX: not yet supported */ 454 /*59*/ /* KERN_TKSTAT: not yet supported */ 455 /*60*/ [KERN_MONOTONIC_CLOCK] = MIB_INT(_P | _RO, _POSIX_MONOTONIC_CLOCK, 456 "monotonic_clock", 457 "Implementation version of the POSIX " 458 "1003.1b Monotonic Clock Option"), 459 /*61*/ /* KERN_URND: not yet supported */ 460 /*62*/ /* KERN_LABELSECTOR: not yet supported */ 461 /*63*/ /* KERN_LABELOFFSET: not yet supported */ 462 /*64*/ [KERN_LWP] = MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0, 463 mib_kern_lwp, "lwp", 464 "System-wide LWP information"), 465 /*65*/ [KERN_FORKFSLEEP] = MIB_INTV(_P | _RW, 0, mib_kern_forkfsleep, 466 "forkfsleep", "Milliseconds to sleep on " 467 "fork failure due to process limits"), 468 /*66*/ /* KERN_POSIX_THREADS: not yet supported */ 469 /*67*/ /* KERN_POSIX_SEMAPHORES: not yet supported */ 470 /*68*/ /* KERN_POSIX_BARRIERS: not yet supported */ 471 /*69*/ /* KERN_POSIX_TIMERS: not yet supported */ 472 /*70*/ /* KERN_POSIX_SPIN_LOCKS: not yet supported */ 473 /*71*/ /* KERN_POSIX_READER_WRITER_LOCKS: not yet supported */ 474 /*72*/ [KERN_DUMP_ON_PANIC] = MIB_INT(_P | _RO, 0, "dump_on_panic", 475 "Perform a crash dump on system panic"), 476 /*73*/ /* KERN_SOMAXKVA: not yet supported */ 477 /*74*/ /* KERN_ROOT_PARTITION: incompatible with our device node scheme */ 478 /*75*/ [KERN_DRIVERS] = MIB_FUNC(_P | _RO | CTLTYPE_STRUCT, 0, 479 mib_kern_drivers, "drivers", 480 "List of all drivers with block and " 481 "character device numbers"), 482 /*76*/ /* KERN_BUF: not yet supported */ 483 /*77*/ /* KERN_FILE2: not yet supported */ 484 /*78*/ /* KERN_VERIEXEC: not yet supported */ 485 /*79*/ /* KERN_CP_ID: not yet supported */ 486 /*80*/ [KERN_HARDCLOCK_TICKS] = MIB_FUNC(_P | _RO | CTLFLAG_UNSIGNED | 487 CTLTYPE_INT, sizeof(int), 488 mib_kern_hardclock_ticks, 489 "hardclock_ticks", 490 "Number of hardclock ticks"), 491 /*81*/ /* KERN_ARND: not yet supported */ 492 /*82*/ [KERN_SYSVIPC] = MIB_NODE(_P | _RO, mib_kern_ipc_table, "ipc", 493 "SysV IPC options"), 494 /*83*/ [KERN_BOOTTIME] = MIB_FUNC(_P | _RO | CTLTYPE_STRUCT, 495 sizeof(struct timeval), mib_kern_boottime, 496 "boottime", "System boot time"), 497 /*84*/ /* KERN_EVCNT: not yet supported */ 498 }; 499 500 /* 501 * Initialize the CTL_KERN subtree. 502 */ 503 void 504 mib_kern_init(struct mib_node * node) 505 { 506 507 MIB_INIT_ENODE(node, mib_kern_table); 508 } 509