* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Mike Karels at Berkeley Software Design, Inc.
* %sccs.include.redist.c%
* @(#)kern_sysctl.c 8.8 (Berkeley) %G%
#include <sys/syscallargs.h>
extern sysctlfn vm_sysctl
;
extern sysctlfn vfs_sysctl
;
extern sysctlfn net_sysctl
;
extern sysctlfn cpu_sysctl
;
static struct sysctl_lock
{
register struct __sysctl_args
/* {
syscallarg(u_int) namelen;
syscallarg(size_t *) oldlenp;
syscallarg(size_t) newlen;
size_t savelen
, oldlen
= 0;
if (SCARG(uap
, new) != NULL
&&
(error
= suser(p
->p_ucred
, &p
->p_acflag
)))
* all top-level sysctl names are non-terminal
if (SCARG(uap
, namelen
) > CTL_MAXNAME
|| SCARG(uap
, namelen
) < 2)
copyin(SCARG(uap
, name
), &name
, SCARG(uap
, namelen
) * sizeof(int)))
if (name
[2] == KERN_VNODE
) /* XXX */
if (SCARG(uap
, oldlenp
) &&
(error
= copyin(SCARG(uap
, oldlenp
), &oldlen
, sizeof(oldlen
))))
if (SCARG(uap
, old
) != NULL
) {
if (!useracc(SCARG(uap
, old
), oldlen
, B_WRITE
))
while (memlock
.sl_lock
) {
sleep((caddr_t
)&memlock
, PRIBIO
+1);
vslock(SCARG(uap
, old
), oldlen
);
error
= (*fn
)(name
+ 1, SCARG(uap
, namelen
) - 1, SCARG(uap
, old
),
&oldlen
, SCARG(uap
, new), SCARG(uap
, newlen
), p
);
if (SCARG(uap
, old
) != NULL
) {
vsunlock(SCARG(uap
, old
), savelen
, B_WRITE
);
wakeup((caddr_t
)&memlock
);
error
= copyout(&oldlen
, SCARG(uap
, oldlenp
), sizeof(oldlen
));
* Attributes stored in the kernel.
char hostname
[MAXHOSTNAMELEN
];
* kernel related system variables.
kern_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
int error
, level
, inthostid
;
extern char ostype
[], osrelease
[], version
[];
/* all sysctl names at this level are terminal */
if (namelen
!= 1 && !(name
[0] == KERN_PROC
|| name
[0] == KERN_PROF
))
return (ENOTDIR
); /* overloaded */
return (sysctl_rdstring(oldp
, oldlenp
, newp
, ostype
));
return (sysctl_rdstring(oldp
, oldlenp
, newp
, osrelease
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, BSD
));
return (sysctl_rdstring(oldp
, oldlenp
, newp
, version
));
return(sysctl_int(oldp
, oldlenp
, newp
, newlen
, &desiredvnodes
));
return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxproc
));
return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxfiles
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, ARG_MAX
));
if ((error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &level
)) ||
if (level
< securelevel
&& p
->p_pid
!= 1)
error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
hostname
, sizeof(hostname
));
inthostid
= hostid
; /* XXX assumes sizeof long <= sizeof int */
error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &inthostid
);
return (sysctl_clockrate(oldp
, oldlenp
));
return (sysctl_rdstruct(oldp
, oldlenp
, newp
, &boottime
,
sizeof(struct timeval
)));
return (sysctl_vnode(oldp
, oldlenp
));
return (sysctl_doproc(name
+ 1, namelen
- 1, oldp
, oldlenp
));
return (sysctl_file(oldp
, oldlenp
));
return (sysctl_doprof(name
+ 1, namelen
- 1, oldp
, oldlenp
,
return (sysctl_rdint(oldp
, oldlenp
, newp
, _POSIX_VERSION
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, NGROUPS_MAX
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 0));
* hardware related system variables.
hw_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
extern char machine
[], cpu_model
[];
/* all sysctl names at this level are terminal */
return (ENOTDIR
); /* overloaded */
return (sysctl_rdstring(oldp
, oldlenp
, newp
, machine
));
return (sysctl_rdstring(oldp
, oldlenp
, newp
, cpu_model
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 1)); /* XXX */
return (sysctl_rdint(oldp
, oldlenp
, newp
, BYTE_ORDER
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, ctob(physmem
)));
return (sysctl_rdint(oldp
, oldlenp
, newp
,
ctob(physmem
- cnt
.v_wire_count
)));
return (sysctl_rdint(oldp
, oldlenp
, newp
, PAGE_SIZE
));
* Debugging related system variables.
struct ctldebug debug0
, debug1
, debug2
, debug3
, debug4
;
struct ctldebug debug5
, debug6
, debug7
, debug8
, debug9
;
struct ctldebug debug10
, debug11
, debug12
, debug13
, debug14
;
struct ctldebug debug15
, debug16
, debug17
, debug18
, debug19
;
static struct ctldebug
*debugvars
[CTL_DEBUG_MAXID
] = {
&debug0
, &debug1
, &debug2
, &debug3
, &debug4
,
&debug5
, &debug6
, &debug7
, &debug8
, &debug9
,
&debug10
, &debug11
, &debug12
, &debug13
, &debug14
,
&debug15
, &debug16
, &debug17
, &debug18
, &debug19
,
debug_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
/* all sysctl names at this level are name and field */
return (ENOTDIR
); /* overloaded */
cdp
= debugvars
[name
[0]];
if (name
[0] >= CTL_DEBUG_MAXID
|| cdp
->debugname
== 0)
return (sysctl_rdstring(oldp
, oldlenp
, newp
, cdp
->debugname
));
return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, cdp
->debugvar
));
* Validate parameters and get old / set new parameters
* for an integer-valued sysctl function.
sysctl_int(oldp
, oldlenp
, newp
, newlen
, valp
)
if (oldp
&& *oldlenp
< sizeof(int))
if (newp
&& newlen
!= sizeof(int))
error
= copyout(valp
, oldp
, sizeof(int));
error
= copyin(newp
, valp
, sizeof(int));
* As above, but read-only.
sysctl_rdint(oldp
, oldlenp
, newp
, val
)
if (oldp
&& *oldlenp
< sizeof(int))
error
= copyout((caddr_t
)&val
, oldp
, sizeof(int));
* Validate parameters and get old / set new parameters
* for a string-valued sysctl function.
sysctl_string(oldp
, oldlenp
, newp
, newlen
, str
, maxlen
)
if (oldp
&& *oldlenp
< len
)
if (newp
&& newlen
>= maxlen
)
error
= copyout(str
, oldp
, len
);
if (error
== 0 && newp
) {
error
= copyin(newp
, str
, newlen
);
* As above, but read-only.
sysctl_rdstring(oldp
, oldlenp
, newp
, str
)
if (oldp
&& *oldlenp
< len
)
error
= copyout(str
, oldp
, len
);
* Validate parameters and get old / set new parameters
* for a structure oriented sysctl function.
sysctl_struct(oldp
, oldlenp
, newp
, newlen
, sp
, len
)
if (oldp
&& *oldlenp
< len
)
if (newp
&& newlen
> len
)
error
= copyout(sp
, oldp
, len
);
error
= copyin(newp
, sp
, len
);
* Validate parameters and get old parameters
* for a structure oriented sysctl function.
sysctl_rdstruct(oldp
, oldlenp
, newp
, sp
, len
)
if (oldp
&& *oldlenp
< len
)
error
= copyout(sp
, oldp
, len
);
sysctl_file(where
, sizep
)
* overestimate by 10 files
*sizep
= sizeof(filehead
) + (nfiles
+ 10) * sizeof(struct file
);
if (buflen
< sizeof(filehead
)) {
if (error
= copyout((caddr_t
)&filehead
, where
, sizeof(filehead
)))
buflen
-= sizeof(filehead
);
where
+= sizeof(filehead
);
* followed by an array of file structures
for (fp
= filehead
.lh_first
; fp
!= 0; fp
= fp
->f_list
.le_next
) {
if (buflen
< sizeof(struct file
)) {
if (error
= copyout((caddr_t
)fp
, where
, sizeof (struct file
)))
buflen
-= sizeof(struct file
);
where
+= sizeof(struct file
);
* try over estimating by 5 procs
#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
sysctl_doproc(name
, namelen
, where
, sizep
)
register struct kinfo_proc
*dp
= (struct kinfo_proc
*)where
;
int buflen
= where
!= NULL
? *sizep
: 0;
if (namelen
!= 2 && !(namelen
== 1 && name
[0] == KERN_PROC_ALL
))
for (; p
!= 0; p
= p
->p_list
.le_next
) {
* Skip embryonic processes.
* TODO - make more efficient (see notes below).
/* could do this with just a lookup */
if (p
->p_pid
!= (pid_t
)name
[1])
/* could do this by traversing pgrp */
if (p
->p_pgrp
->pg_id
!= (pid_t
)name
[1])
if ((p
->p_flag
& P_CONTROLT
) == 0 ||
p
->p_session
->s_ttyp
== NULL
||
p
->p_session
->s_ttyp
->t_dev
!= (dev_t
)name
[1])
if (p
->p_ucred
->cr_uid
!= (uid_t
)name
[1])
if (p
->p_cred
->p_ruid
!= (uid_t
)name
[1])
if (buflen
>= sizeof(struct kinfo_proc
)) {
if (error
= copyout((caddr_t
)p
, &dp
->kp_proc
,
if (error
= copyout((caddr_t
)&eproc
, &dp
->kp_eproc
,
buflen
-= sizeof(struct kinfo_proc
);
needed
+= sizeof(struct kinfo_proc
);
*sizep
= (caddr_t
)dp
- where
;
* Fill in an eproc structure for the specified process.
register struct eproc
*ep
;
ep
->e_sess
= p
->p_pgrp
->pg_session
;
ep
->e_pcred
= *p
->p_cred
;
ep
->e_ucred
= *p
->p_ucred
;
if (p
->p_stat
== SIDL
|| p
->p_stat
== SZOMB
) {
/* ep->e_vm.vm_pmap = XXX; */
register struct vmspace
*vm
= p
->p_vmspace
;
#ifdef pmap_resident_count
ep
->e_vm
.vm_rssize
= pmap_resident_count(&vm
->vm_pmap
); /*XXX*/
ep
->e_vm
.vm_rssize
= vm
->vm_rssize
;
ep
->e_vm
.vm_tsize
= vm
->vm_tsize
;
ep
->e_vm
.vm_dsize
= vm
->vm_dsize
;
ep
->e_vm
.vm_ssize
= vm
->vm_ssize
;
ep
->e_vm
.vm_pmap
= vm
->vm_pmap
;
ep
->e_ppid
= p
->p_pptr
->p_pid
;
ep
->e_pgid
= p
->p_pgrp
->pg_id
;
ep
->e_jobc
= p
->p_pgrp
->pg_jobc
;
if ((p
->p_flag
& P_CONTROLT
) &&
(tp
= ep
->e_sess
->s_ttyp
)) {
ep
->e_tpgid
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: NO_PID
;
ep
->e_tsess
= tp
->t_session
;
ep
->e_flag
= ep
->e_sess
->s_ttyvp
? EPROC_CTTY
: 0;
ep
->e_flag
|= EPROC_SLEADER
;
strncpy(ep
->e_wmesg
, p
->p_wmesg
, WMESGLEN
);
ep
->e_xsize
= ep
->e_xrssize
= 0;
ep
->e_xccount
= ep
->e_xswrss
= 0;
#define KINFO_PROC (0<<8)
#define KINFO_VNODE (2<<8)
#define KINFO_FILE (3<<8)
#define KINFO_METER (4<<8)
#define KINFO_LOADAVG (5<<8)
#define KINFO_CLOCKRATE (6<<8)
compat_43_getkerninfo(p
, uap
, retval
)
register struct compat_43_getkerninfo_args
/* {
syscallarg(char *) where;
if (SCARG(uap
, size
) && (error
= copyin((caddr_t
)SCARG(uap
, size
),
(caddr_t
)&size
, sizeof(size
))))
switch (SCARG(uap
, op
) & 0xff00) {
name
[2] = (SCARG(uap
, op
) & 0xff0000) >> 16;
name
[3] = SCARG(uap
, op
) & 0xff;
name
[4] = SCARG(uap
, arg
);
net_sysctl(name
, 5, SCARG(uap
, where
), &size
, NULL
, 0, p
);
kern_sysctl(name
, 1, SCARG(uap
, where
), &size
, NULL
, 0, p
);
name
[1] = SCARG(uap
, op
) & 0xff;
name
[2] = SCARG(uap
, arg
);
kern_sysctl(name
, 3, SCARG(uap
, where
), &size
, NULL
, 0, p
);
kern_sysctl(name
, 1, SCARG(uap
, where
), &size
, NULL
, 0, p
);
vm_sysctl(name
, 1, SCARG(uap
, where
), &size
, NULL
, 0, p
);
vm_sysctl(name
, 1, SCARG(uap
, where
), &size
, NULL
, 0, p
);
name
[0] = KERN_CLOCKRATE
;
kern_sysctl(name
, 1, SCARG(uap
, where
), &size
, NULL
, 0, p
);
error
= copyout((caddr_t
)&size
, (caddr_t
)SCARG(uap
, size
),