178189Sbrian/*-
278189Sbrian * Copyright (c) 1982, 1986, 1989, 1993
378189Sbrian *	The Regents of the University of California.  All rights reserved.
478189Sbrian *
578189Sbrian * Redistribution and use in source and binary forms, with or without
66059Samurai * modification, are permitted provided that the following conditions
778189Sbrian * are met:
878189Sbrian * 1. Redistributions of source code must retain the above copyright
978189Sbrian *    notice, this list of conditions and the following disclaimer.
1078189Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1178189Sbrian *    notice, this list of conditions and the following disclaimer in the
1278189Sbrian *    documentation and/or other materials provided with the distribution.
1378189Sbrian * 4. Neither the name of the University nor the names of its contributors
1478189Sbrian *    may be used to endorse or promote products derived from this software
156059Samurai *    without specific prior written permission.
1678189Sbrian *
1778189Sbrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1878189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1978189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2078189Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2178189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2278189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2378189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2478189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2578189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2678189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
276059Samurai * SUCH DAMAGE.
2850479Speter *
296059Samurai *	@(#)kern_xxx.c	8.2 (Berkeley) 11/14/93
3078189Sbrian */
3143313Sbrian
3230715Sbrian#include <sys/cdefs.h>
3336285Sbrian__FBSDID("$FreeBSD$");
3436285Sbrian
3581634Sbrian#include "opt_compat.h"
3636285Sbrian
3730715Sbrian#include <sys/param.h>
38134789Sbrian#include <sys/systm.h>
3943888Sbrian#include <sys/sysproto.h>
4043888Sbrian#include <sys/kernel.h>
4193418Sbrian#include <sys/priv.h>
4236287Sbrian#include <sys/proc.h>
4337192Sbrian#include <sys/lock.h>
4430715Sbrian#include <sys/mutex.h>
4543888Sbrian#include <sys/socket.h>
4643888Sbrian#include <sys/sysctl.h>
4749976Sbrian#include <sys/utsname.h>
4830715Sbrian
4944106Sbrian#include <vm/vm_param.h>
5043888Sbrian
5136285Sbrian#if defined(COMPAT_43)
5243888Sbrian
5329840Sbrian#ifndef _SYS_SYSPROTO_H_
5446686Sbrianstruct gethostname_args {
5530715Sbrian	char	*hostname;
5630715Sbrian	u_int	len;
5730715Sbrian};
5830715Sbrian#endif
596059Samurai/* ARGSUSED */
6046686Sbrianint
6136285Sbrianogethostname(td, uap)
626059Samurai	struct thread *td;
6363484Sbrian	struct gethostname_args *uap;
646735Samurai{
6536285Sbrian	int name[2];
6636285Sbrian	size_t len = uap->len;
6736285Sbrian
6843888Sbrian	name[0] = CTL_KERN;
6936285Sbrian	name[1] = KERN_HOSTNAME;
7036285Sbrian	return (userland_sysctl(td, name, 2, uap->hostname, &len,
7181634Sbrian	    1, 0, 0, 0, 0));
7236285Sbrian}
7336285Sbrian
7436285Sbrian#ifndef _SYS_SYSPROTO_H_
7536285Sbrianstruct sethostname_args {
7636285Sbrian	char	*hostname;
7736285Sbrian	u_int	len;
7843313Sbrian};
7943313Sbrian#endif
8043313Sbrian/* ARGSUSED */
8181634Sbrianint
8281634Sbrianosethostname(td, uap)
8336285Sbrian	struct thread *td;
8436285Sbrian	register struct sethostname_args *uap;
8538174Sbrian{
8643888Sbrian	int name[2];
8736285Sbrian
8893418Sbrian	name[0] = CTL_KERN;
8936287Sbrian	name[1] = KERN_HOSTNAME;
9067910Sbrian	return (userland_sysctl(td, name, 2, 0, 0, 0, uap->hostname,
9137192Sbrian	    uap->len, 0, 0));
9255253Sbrian}
936059Samurai
9455146Sbrian#ifndef _SYS_SYSPROTO_H_
9519866Sphkstruct ogethostid_args {
966059Samurai	int	dummy;
9743693Sbrian};
986059Samurai#endif
9930715Sbrian/* ARGSUSED */
10036285Sbrianint
10143693Sbrianogethostid(td, uap)
1026059Samurai	struct thread *td;
1036059Samurai	struct ogethostid_args *uap;
1046059Samurai{
1056059Samurai	size_t len = sizeof(long);
1066059Samurai	int name[2];
10728679Sbrian
1086059Samurai	name[0] = CTL_KERN;
1096059Samurai	name[1] = KERN_HOSTID;
1106059Samurai	return (kernel_sysctl(td, name, 2, (long *)td->td_retval, &len,
11154912Sbrian	    NULL, 0, NULL, 0));
11230715Sbrian}
1136059Samurai#endif /* COMPAT_43 */
11430715Sbrian
11536285Sbrian#ifdef COMPAT_43
11637926Sbrian#ifndef _SYS_SYSPROTO_H_
11737926Sbrianstruct osethostid_args {
11837926Sbrian	long	hostid;
11937926Sbrian};
12046686Sbrian#endif
12150867Sbrian/* ARGSUSED */
1226059Samuraiint
1236059Samuraiosethostid(td, uap)
12443693Sbrian	struct thread *td;
125134789Sbrian	struct osethostid_args *uap;
12693418Sbrian{
127134789Sbrian	int name[2];
128134789Sbrian
12944123Sbrian	name[0] = CTL_KERN;
13044123Sbrian	name[1] = KERN_HOSTID;
1316059Samurai	return (kernel_sysctl(td, name, 2, NULL, NULL, &uap->hostid,
13243693Sbrian	    sizeof(uap->hostid), NULL, 0));
13343693Sbrian}
13443693Sbrian
13543693Sbrianint
13643693Sbrianoquota(td, uap)
13743693Sbrian	struct thread *td;
13893418Sbrian	struct oquota_args *uap;
13944106Sbrian{
14043693Sbrian
14143693Sbrian	return (ENOSYS);
142134789Sbrian}
14343693Sbrian
14443693Sbrian#define	KINFO_PROC		(0<<8)
14543693Sbrian#define	KINFO_RT		(1<<8)
14643693Sbrian#define	KINFO_VNODE		(2<<8)
14744106Sbrian#define	KINFO_FILE		(3<<8)
14844106Sbrian#define	KINFO_METER		(4<<8)
14944106Sbrian#define	KINFO_LOADAVG		(5<<8)
15044106Sbrian#define	KINFO_CLOCKRATE		(6<<8)
15144106Sbrian
15244106Sbrian/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
15344106Sbrian#define	KINFO_BSDI_SYSINFO	(101<<8)
15444106Sbrian
15544106Sbrian/*
15643693Sbrian * XXX this is bloat, but I hope it's better here than on the potentially
15744106Sbrian * limited kernel stack...  -Peter
15844106Sbrian */
15944106Sbrian
16044106Sbrianstatic struct {
16144106Sbrian	int	bsdi_machine;		/* "i386" on BSD/386 */
16244106Sbrian/*      ^^^ this is an offset to the string, relative to the struct start */
16344106Sbrian	char	*pad0;
16444106Sbrian	long	pad1;
16544106Sbrian	long	pad2;
16644106Sbrian	long	pad3;
16744106Sbrian	u_long	pad4;
16844106Sbrian	u_long	pad5;
16944106Sbrian	u_long	pad6;
17044106Sbrian
17144106Sbrian	int	bsdi_ostype;		/* "BSD/386" on BSD/386 */
17244106Sbrian	int	bsdi_osrelease;		/* "1.1" on BSD/386 */
17344106Sbrian	long	pad7;
17444106Sbrian	long	pad8;
17544106Sbrian	char	*pad9;
17643693Sbrian
17743693Sbrian	long	pad10;
17844106Sbrian	long	pad11;
17944106Sbrian	int	pad12;
18044106Sbrian	long	pad13;
18144106Sbrian	quad_t	pad14;
18244106Sbrian	long	pad15;
18343693Sbrian
18467910Sbrian	struct	timeval pad16;
18567910Sbrian	/* we dont set this, because BSDI's uname used gethostname() instead */
18667910Sbrian	int	bsdi_hostname;		/* hostname on BSD/386 */
18767910Sbrian
18867910Sbrian	/* the actual string data is appended here */
189134789Sbrian
19067910Sbrian} bsdi_si;
19167910Sbrian
19267910Sbrian/*
19367910Sbrian * this data is appended to the end of the bsdi_si structure during copyout.
19467910Sbrian * The "char *" offsets are relative to the base of the bsdi_si struct.
19567910Sbrian * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
19667910Sbrian * should not exceed the length of the buffer here... (or else!! :-)
19767910Sbrian */
19867910Sbrianstatic char bsdi_strings[80];	/* It had better be less than this! */
19967910Sbrian
20067910Sbrian#ifndef _SYS_SYSPROTO_H_
20167910Sbrianstruct getkerninfo_args {
20267910Sbrian	int	op;
20367910Sbrian	char	*where;
20467910Sbrian	size_t	*size;
20567910Sbrian	int	arg;
20667910Sbrian};
20767910Sbrian#endif
20867910Sbrianint
20967910Sbrianogetkerninfo(struct thread *td, struct getkerninfo_args *uap)
21067910Sbrian{
21167910Sbrian	int error, name[6];
21267910Sbrian	size_t size;
21367910Sbrian	u_int needed = 0;
21467910Sbrian
215134789Sbrian	switch (uap->op & 0xff00) {
21667910Sbrian
21767910Sbrian	case KINFO_RT:
21867910Sbrian		name[0] = CTL_NET;
21968461Sbrian		name[1] = PF_ROUTE;
22067910Sbrian		name[2] = 0;
22167910Sbrian		name[3] = (uap->op & 0xff0000) >> 16;
22298243Sbrian		name[4] = uap->op & 0xff;
223134789Sbrian		name[5] = uap->arg;
22467910Sbrian		error = userland_sysctl(td, name, 6, uap->where, uap->size,
22567910Sbrian			0, 0, 0, &size, 0);
22667910Sbrian		break;
22767910Sbrian
22867910Sbrian	case KINFO_VNODE:
22943693Sbrian		name[0] = CTL_KERN;
23043693Sbrian		name[1] = KERN_VNODE;
23143693Sbrian		error = userland_sysctl(td, name, 2, uap->where, uap->size,
23243693Sbrian			0, 0, 0, &size, 0);
23343693Sbrian		break;
23443693Sbrian
23543693Sbrian	case KINFO_PROC:
23643693Sbrian		name[0] = CTL_KERN;
23743693Sbrian		name[1] = KERN_PROC;
23843693Sbrian		name[2] = uap->op & 0xff;
23943693Sbrian		name[3] = uap->arg;
24043693Sbrian		error = userland_sysctl(td, name, 4, uap->where, uap->size,
24143693Sbrian			0, 0, 0, &size, 0);
24243693Sbrian		break;
24343693Sbrian
24443693Sbrian	case KINFO_FILE:
24543693Sbrian		name[0] = CTL_KERN;
24643693Sbrian		name[1] = KERN_FILE;
24743693Sbrian		error = userland_sysctl(td, name, 2, uap->where, uap->size,
24843693Sbrian			0, 0, 0, &size, 0);
24943693Sbrian		break;
25043693Sbrian
25143693Sbrian	case KINFO_METER:
25243693Sbrian		name[0] = CTL_VM;
25343693Sbrian		name[1] = VM_TOTAL;
25443693Sbrian		error = userland_sysctl(td, name, 2, uap->where, uap->size,
25543693Sbrian			0, 0, 0, &size, 0);
25643888Sbrian		break;
25743888Sbrian
25843888Sbrian	case KINFO_LOADAVG:
25943888Sbrian		name[0] = CTL_VM;
26043888Sbrian		name[1] = VM_LOADAVG;
26147849Sbrian		error = userland_sysctl(td, name, 2, uap->where, uap->size,
26243888Sbrian			0, 0, 0, &size, 0);
26343888Sbrian		break;
26443888Sbrian
26543888Sbrian	case KINFO_CLOCKRATE:
26643888Sbrian		name[0] = CTL_KERN;
26743888Sbrian		name[1] = KERN_CLOCKRATE;
26843888Sbrian		error = userland_sysctl(td, name, 2, uap->where, uap->size,
26943888Sbrian			0, 0, 0, &size, 0);
27043888Sbrian		break;
27143888Sbrian
27243888Sbrian	case KINFO_BSDI_SYSINFO: {
27343888Sbrian		/*
27443888Sbrian		 * this is pretty crude, but it's just enough for uname()
27543888Sbrian		 * from BSDI's 1.x libc to work.
27643888Sbrian		 *
27743888Sbrian		 * *size gives the size of the buffer before the call, and
27843888Sbrian		 * the amount of data copied after a successful call.
27943888Sbrian		 * If successful, the return value is the amount of data
28047849Sbrian		 * available, which can be larger than *size.
28143888Sbrian		 *
28243888Sbrian		 * BSDI's 2.x product apparently fails with ENOMEM if *size
28343888Sbrian		 * is too small.
28443888Sbrian		 */
28543888Sbrian
28643888Sbrian		u_int left;
28743888Sbrian		char *s;
28843888Sbrian
28943888Sbrian		bzero((char *)&bsdi_si, sizeof(bsdi_si));
29043888Sbrian		bzero(bsdi_strings, sizeof(bsdi_strings));
29143888Sbrian
29243888Sbrian		s = bsdi_strings;
29354914Sbrian
29454914Sbrian		bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
29554914Sbrian		strcpy(s, ostype);
29654914Sbrian		s += strlen(s) + 1;
29754914Sbrian
29854914Sbrian		bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
29954914Sbrian		strcpy(s, osrelease);
30054914Sbrian		s += strlen(s) + 1;
30154914Sbrian
30243888Sbrian		bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
30343888Sbrian		strcpy(s, machine);
30449976Sbrian		s += strlen(s) + 1;
30549976Sbrian
30643888Sbrian		needed = sizeof(bsdi_si) + (s - bsdi_strings);
30743888Sbrian
30849976Sbrian		if ((uap->where == NULL) || (uap->size == NULL)) {
30949976Sbrian			/* process is asking how much buffer to supply.. */
31043888Sbrian			size = needed;
31143888Sbrian			error = 0;
31243888Sbrian			break;
31343888Sbrian		}
31449976Sbrian
31549976Sbrian		if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
31664802Sbrian			break;
31755252Sbrian
31864802Sbrian		/* if too much buffer supplied, trim it down */
31943888Sbrian		if (size > needed)
32047849Sbrian			size = needed;
32143888Sbrian
32249976Sbrian		/* how much of the buffer is remaining */
32349976Sbrian		left = size;
32443888Sbrian
32543888Sbrian		if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
32643888Sbrian			break;
32743888Sbrian
32843888Sbrian		/* is there any point in continuing? */
32943888Sbrian		if (left > sizeof(bsdi_si)) {
33043888Sbrian			left -= sizeof(bsdi_si);
33143888Sbrian			error = copyout(&bsdi_strings,
33245907Sbrian					uap->where + sizeof(bsdi_si), left);
33343888Sbrian		}
33443888Sbrian		break;
33543888Sbrian	}
33643888Sbrian
33743888Sbrian	default:
33843888Sbrian		error = EOPNOTSUPP;
33943888Sbrian		break;
34043888Sbrian	}
34143888Sbrian	if (error == 0) {
34243888Sbrian		td->td_retval[0] = needed ? needed : size;
34343888Sbrian		if (uap->size) {
34443888Sbrian			error = copyout(&size, uap->size, sizeof(size));
34543888Sbrian		}
34643888Sbrian	}
34743888Sbrian	return (error);
34843888Sbrian}
34943888Sbrian#endif /* COMPAT_43 */
35043888Sbrian
35143888Sbrian#ifdef COMPAT_FREEBSD4
35243888Sbrian/*
35343888Sbrian * This is the FreeBSD-1.1 compatible uname(2) interface.  These days it is
35443888Sbrian * done in libc as a wrapper around a bunch of sysctl's.  This must maintain
35543888Sbrian * the old 1.1 binary ABI.
35643888Sbrian */
35743888Sbrian#if SYS_NMLN != 32
35843888Sbrian#error "FreeBSD-1.1 uname syscall has been broken"
35943888Sbrian#endif
36043888Sbrian#ifndef _SYS_SYSPROTO_H_
36145907Sbrianstruct uname_args {
36293418Sbrian	struct utsname  *name;
36344106Sbrian};
36444123Sbrian#endif
36543888Sbrian/* ARGSUSED */
36643888Sbrianint
36743888Sbrianfreebsd4_uname(struct thread *td, struct freebsd4_uname_args *uap)
368134789Sbrian{
36993418Sbrian	int name[2], error;
370134789Sbrian	size_t len;
37144123Sbrian	char *s, *us;
37244123Sbrian
37343888Sbrian	name[0] = CTL_KERN;
37444106Sbrian	name[1] = KERN_OSTYPE;
37543888Sbrian	len = sizeof (uap->name->sysname);
376134789Sbrian	error = userland_sysctl(td, name, 2, uap->name->sysname, &len,
37793418Sbrian		1, 0, 0, 0, 0);
378134789Sbrian	if (error)
37944123Sbrian		return (error);
38044123Sbrian	subyte( uap->name->sysname + sizeof(uap->name->sysname) - 1, 0);
38143888Sbrian
38243888Sbrian	name[1] = KERN_HOSTNAME;
38343888Sbrian	len = sizeof uap->name->nodename;
38443888Sbrian	error = userland_sysctl(td, name, 2, uap->name->nodename, &len,
38593418Sbrian		1, 0, 0, 0, 0);
38644106Sbrian	if (error)
38768461Sbrian		return (error);
38844123Sbrian	subyte( uap->name->nodename + sizeof(uap->name->nodename) - 1, 0);
38943888Sbrian
39043888Sbrian	name[1] = KERN_OSRELEASE;
39143888Sbrian	len = sizeof uap->name->release;
39243888Sbrian	error = userland_sysctl(td, name, 2, uap->name->release, &len,
39343888Sbrian		1, 0, 0, 0, 0);
39443888Sbrian	if (error)
39543888Sbrian		return (error);
396134789Sbrian	subyte( uap->name->release + sizeof(uap->name->release) - 1, 0);
397134789Sbrian
39843888Sbrian/*
39943888Sbrian	name = KERN_VERSION;
40043888Sbrian	len = sizeof uap->name->version;
40143888Sbrian	error = userland_sysctl(td, name, 2, uap->name->version, &len,
40243888Sbrian		1, 0, 0, 0, 0);
40343888Sbrian	if (error)
40443888Sbrian		return (error);
40543888Sbrian	subyte( uap->name->version + sizeof(uap->name->version) - 1, 0);
40643888Sbrian*/
40743888Sbrian
40843888Sbrian/*
40943888Sbrian * this stupid hackery to make the version field look like FreeBSD 1.1
41043888Sbrian */
41143888Sbrian	for(s = version; *s && *s != '#'; s++);
41243888Sbrian
41358028Sbrian	for(us = uap->name->version; *s && *s != ':'; s++) {
41443888Sbrian		error = subyte( us++, *s);
41543888Sbrian		if (error)
41643888Sbrian			return (error);
41743888Sbrian	}
41843888Sbrian	error = subyte( us++, 0);
41943888Sbrian	if (error)
42043888Sbrian		return (error);
421134789Sbrian
422134789Sbrian	name[0] = CTL_HW;
42343888Sbrian	name[1] = HW_MACHINE;
42443888Sbrian	len = sizeof uap->name->machine;
42543888Sbrian	error = userland_sysctl(td, name, 2, uap->name->machine, &len,
42643888Sbrian		1, 0, 0, 0, 0);
42743888Sbrian	if (error)
42843888Sbrian		return (error);
42943888Sbrian	subyte( uap->name->machine + sizeof(uap->name->machine) - 1, 0);
43043888Sbrian	return (0);
43143888Sbrian}
43243888Sbrian
43343888Sbrian#ifndef _SYS_SYSPROTO_H_
43443888Sbrianstruct getdomainname_args {
43543888Sbrian	char    *domainname;
43643888Sbrian	int     len;
43743888Sbrian};
43843888Sbrian#endif
43943888Sbrian/* ARGSUSED */
44043888Sbrianint
44143888Sbrianfreebsd4_getdomainname(struct thread *td,
44243888Sbrian    struct freebsd4_getdomainname_args *uap)
44343888Sbrian{
44443888Sbrian	int name[2];
44543888Sbrian	size_t len = uap->len;
44643888Sbrian
44743888Sbrian	name[0] = CTL_KERN;
44843888Sbrian	name[1] = KERN_NISDOMAINNAME;
44943888Sbrian	return (userland_sysctl(td, name, 2, uap->domainname, &len,
45043888Sbrian	    1, 0, 0, 0, 0));
45143888Sbrian}
45243888Sbrian
45393418Sbrian#ifndef _SYS_SYSPROTO_H_
45444106Sbrianstruct setdomainname_args {
45544106Sbrian	char    *domainname;
45644106Sbrian	int     len;
45744106Sbrian};
45844123Sbrian#endif
45944106Sbrian/* ARGSUSED */
46043888Sbrianint
46143888Sbrianfreebsd4_setdomainname(struct thread *td,
46243888Sbrian    struct freebsd4_setdomainname_args *uap)
46343888Sbrian{
46443888Sbrian	int name[2];
46543888Sbrian
46643888Sbrian	name[0] = CTL_KERN;
467134789Sbrian	name[1] = KERN_NISDOMAINNAME;
46893418Sbrian	return (userland_sysctl(td, name, 2, 0, 0, 0, uap->domainname,
469134789Sbrian	    uap->len, 0, 0));
47044123Sbrian}
47144123Sbrian#endif /* COMPAT_FREEBSD4 */
47243888Sbrian