1139804Simp/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes *
291541Srgrimes *	@(#)kern_xxx.c	8.2 (Berkeley) 11/14/93
301541Srgrimes */
311541Srgrimes
32116182Sobrien#include <sys/cdefs.h>
33116182Sobrien__FBSDID("$FreeBSD$");
34116182Sobrien
3531778Seivind#include "opt_compat.h"
3631778Seivind
371541Srgrimes#include <sys/param.h>
381541Srgrimes#include <sys/systm.h>
3912221Sbde#include <sys/sysproto.h>
401541Srgrimes#include <sys/kernel.h>
41164033Srwatson#include <sys/priv.h>
421541Srgrimes#include <sys/proc.h>
4382717Sdillon#include <sys/lock.h>
4482717Sdillon#include <sys/mutex.h>
45186570Sed#include <sys/socket.h>
461541Srgrimes#include <sys/sysctl.h>
471549Srgrimes#include <sys/utsname.h>
481541Srgrimes
49186570Sed#include <vm/vm_param.h>
508876Srgrimes
51130344Sphk#if defined(COMPAT_43)
521541Srgrimes
5312221Sbde#ifndef _SYS_SYSPROTO_H_
541541Srgrimesstruct gethostname_args {
551541Srgrimes	char	*hostname;
561541Srgrimes	u_int	len;
571541Srgrimes};
5812221Sbde#endif
591541Srgrimes/* ARGSUSED */
601549Srgrimesint
6183366Sjulianogethostname(td, uap)
6283366Sjulian	struct thread *td;
631541Srgrimes	struct gethostname_args *uap;
641541Srgrimes{
6512171Sphk	int name[2];
6638517Sdfr	size_t len = uap->len;
671541Srgrimes
6812171Sphk	name[0] = CTL_KERN;
6912171Sphk	name[1] = KERN_HOSTNAME;
70186564Sed	return (userland_sysctl(td, name, 2, uap->hostname, &len,
71186564Sed	    1, 0, 0, 0, 0));
721541Srgrimes}
731541Srgrimes
7412221Sbde#ifndef _SYS_SYSPROTO_H_
751541Srgrimesstruct sethostname_args {
761541Srgrimes	char	*hostname;
771541Srgrimes	u_int	len;
781541Srgrimes};
7912221Sbde#endif
801541Srgrimes/* ARGSUSED */
811549Srgrimesint
8283366Sjulianosethostname(td, uap)
8383366Sjulian	struct thread *td;
841541Srgrimes	register struct sethostname_args *uap;
851541Srgrimes{
8612171Sphk	int name[2];
871541Srgrimes
8812171Sphk	name[0] = CTL_KERN;
8912171Sphk	name[1] = KERN_HOSTNAME;
90186564Sed	return (userland_sysctl(td, name, 2, 0, 0, 0, uap->hostname,
91186564Sed	    uap->len, 0, 0));
921541Srgrimes}
931541Srgrimes
9412221Sbde#ifndef _SYS_SYSPROTO_H_
9512200Sbdestruct ogethostid_args {
961541Srgrimes	int	dummy;
971541Srgrimes};
9812221Sbde#endif
991541Srgrimes/* ARGSUSED */
1001549Srgrimesint
10183366Sjulianogethostid(td, uap)
10283366Sjulian	struct thread *td;
10312200Sbde	struct ogethostid_args *uap;
1041541Srgrimes{
105193066Sjamie	size_t len = sizeof(long);
106193066Sjamie	int name[2];
1071541Srgrimes
108193066Sjamie	name[0] = CTL_KERN;
109193066Sjamie	name[1] = KERN_HOSTID;
110193066Sjamie	return (kernel_sysctl(td, name, 2, (long *)td->td_retval, &len,
111193066Sjamie	    NULL, 0, NULL, 0));
1121541Srgrimes}
113130344Sphk#endif /* COMPAT_43 */
1141541Srgrimes
1151541Srgrimes#ifdef COMPAT_43
11612221Sbde#ifndef _SYS_SYSPROTO_H_
11712200Sbdestruct osethostid_args {
1181541Srgrimes	long	hostid;
1191541Srgrimes};
12012221Sbde#endif
1211541Srgrimes/* ARGSUSED */
1221549Srgrimesint
12383366Sjulianosethostid(td, uap)
12483366Sjulian	struct thread *td;
12512200Sbde	struct osethostid_args *uap;
1261541Srgrimes{
127193066Sjamie	int name[2];
1281541Srgrimes
129193066Sjamie	name[0] = CTL_KERN;
130193066Sjamie	name[1] = KERN_HOSTID;
131193066Sjamie	return (kernel_sysctl(td, name, 2, NULL, NULL, &uap->hostid,
132193066Sjamie	    sizeof(uap->hostid), NULL, 0));
1331541Srgrimes}
1341541Srgrimes
1351549Srgrimesint
13683366Sjulianoquota(td, uap)
13783366Sjulian	struct thread *td;
13812200Sbde	struct oquota_args *uap;
1391541Srgrimes{
140167232Srwatson
1411541Srgrimes	return (ENOSYS);
1421541Srgrimes}
143186570Sed
144186570Sed#define	KINFO_PROC		(0<<8)
145186570Sed#define	KINFO_RT		(1<<8)
146186570Sed#define	KINFO_VNODE		(2<<8)
147186570Sed#define	KINFO_FILE		(3<<8)
148186570Sed#define	KINFO_METER		(4<<8)
149186570Sed#define	KINFO_LOADAVG		(5<<8)
150186570Sed#define	KINFO_CLOCKRATE		(6<<8)
151186570Sed
152186570Sed/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
153186570Sed#define	KINFO_BSDI_SYSINFO	(101<<8)
154186570Sed
155186570Sed/*
156186570Sed * XXX this is bloat, but I hope it's better here than on the potentially
157186570Sed * limited kernel stack...  -Peter
158186570Sed */
159186570Sed
160186570Sedstatic struct {
161186570Sed	int	bsdi_machine;		/* "i386" on BSD/386 */
162186570Sed/*      ^^^ this is an offset to the string, relative to the struct start */
163186570Sed	char	*pad0;
164186570Sed	long	pad1;
165186570Sed	long	pad2;
166186570Sed	long	pad3;
167186570Sed	u_long	pad4;
168186570Sed	u_long	pad5;
169186570Sed	u_long	pad6;
170186570Sed
171186570Sed	int	bsdi_ostype;		/* "BSD/386" on BSD/386 */
172186570Sed	int	bsdi_osrelease;		/* "1.1" on BSD/386 */
173186570Sed	long	pad7;
174186570Sed	long	pad8;
175186570Sed	char	*pad9;
176186570Sed
177186570Sed	long	pad10;
178186570Sed	long	pad11;
179186570Sed	int	pad12;
180186570Sed	long	pad13;
181186570Sed	quad_t	pad14;
182186570Sed	long	pad15;
183186570Sed
184186570Sed	struct	timeval pad16;
185186570Sed	/* we dont set this, because BSDI's uname used gethostname() instead */
186186570Sed	int	bsdi_hostname;		/* hostname on BSD/386 */
187186570Sed
188186570Sed	/* the actual string data is appended here */
189186570Sed
190186570Sed} bsdi_si;
191186570Sed
192186570Sed/*
193186570Sed * this data is appended to the end of the bsdi_si structure during copyout.
194186570Sed * The "char *" offsets are relative to the base of the bsdi_si struct.
195186570Sed * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
196186570Sed * should not exceed the length of the buffer here... (or else!! :-)
197186570Sed */
198186570Sedstatic char bsdi_strings[80];	/* It had better be less than this! */
199186570Sed
200186570Sed#ifndef _SYS_SYSPROTO_H_
201186570Sedstruct getkerninfo_args {
202186570Sed	int	op;
203186570Sed	char	*where;
204186570Sed	size_t	*size;
205186570Sed	int	arg;
206186570Sed};
207186570Sed#endif
208186570Sedint
209186570Sedogetkerninfo(struct thread *td, struct getkerninfo_args *uap)
210186570Sed{
211186570Sed	int error, name[6];
212186570Sed	size_t size;
213186570Sed	u_int needed = 0;
214186570Sed
215186570Sed	switch (uap->op & 0xff00) {
216186570Sed
217186570Sed	case KINFO_RT:
218186570Sed		name[0] = CTL_NET;
219186570Sed		name[1] = PF_ROUTE;
220186570Sed		name[2] = 0;
221186570Sed		name[3] = (uap->op & 0xff0000) >> 16;
222186570Sed		name[4] = uap->op & 0xff;
223186570Sed		name[5] = uap->arg;
224186570Sed		error = userland_sysctl(td, name, 6, uap->where, uap->size,
225186570Sed			0, 0, 0, &size, 0);
226186570Sed		break;
227186570Sed
228186570Sed	case KINFO_VNODE:
229186570Sed		name[0] = CTL_KERN;
230186570Sed		name[1] = KERN_VNODE;
231186570Sed		error = userland_sysctl(td, name, 2, uap->where, uap->size,
232186570Sed			0, 0, 0, &size, 0);
233186570Sed		break;
234186570Sed
235186570Sed	case KINFO_PROC:
236186570Sed		name[0] = CTL_KERN;
237186570Sed		name[1] = KERN_PROC;
238186570Sed		name[2] = uap->op & 0xff;
239186570Sed		name[3] = uap->arg;
240186570Sed		error = userland_sysctl(td, name, 4, uap->where, uap->size,
241186570Sed			0, 0, 0, &size, 0);
242186570Sed		break;
243186570Sed
244186570Sed	case KINFO_FILE:
245186570Sed		name[0] = CTL_KERN;
246186570Sed		name[1] = KERN_FILE;
247186570Sed		error = userland_sysctl(td, name, 2, uap->where, uap->size,
248186570Sed			0, 0, 0, &size, 0);
249186570Sed		break;
250186570Sed
251186570Sed	case KINFO_METER:
252186570Sed		name[0] = CTL_VM;
253186570Sed		name[1] = VM_TOTAL;
254186570Sed		error = userland_sysctl(td, name, 2, uap->where, uap->size,
255186570Sed			0, 0, 0, &size, 0);
256186570Sed		break;
257186570Sed
258186570Sed	case KINFO_LOADAVG:
259186570Sed		name[0] = CTL_VM;
260186570Sed		name[1] = VM_LOADAVG;
261186570Sed		error = userland_sysctl(td, name, 2, uap->where, uap->size,
262186570Sed			0, 0, 0, &size, 0);
263186570Sed		break;
264186570Sed
265186570Sed	case KINFO_CLOCKRATE:
266186570Sed		name[0] = CTL_KERN;
267186570Sed		name[1] = KERN_CLOCKRATE;
268186570Sed		error = userland_sysctl(td, name, 2, uap->where, uap->size,
269186570Sed			0, 0, 0, &size, 0);
270186570Sed		break;
271186570Sed
272186570Sed	case KINFO_BSDI_SYSINFO: {
273186570Sed		/*
274186570Sed		 * this is pretty crude, but it's just enough for uname()
275186570Sed		 * from BSDI's 1.x libc to work.
276186570Sed		 *
277186570Sed		 * *size gives the size of the buffer before the call, and
278186570Sed		 * the amount of data copied after a successful call.
279186570Sed		 * If successful, the return value is the amount of data
280186570Sed		 * available, which can be larger than *size.
281186570Sed		 *
282186570Sed		 * BSDI's 2.x product apparently fails with ENOMEM if *size
283186570Sed		 * is too small.
284186570Sed		 */
285186570Sed
286186570Sed		u_int left;
287186570Sed		char *s;
288186570Sed
289186570Sed		bzero((char *)&bsdi_si, sizeof(bsdi_si));
290186570Sed		bzero(bsdi_strings, sizeof(bsdi_strings));
291186570Sed
292186570Sed		s = bsdi_strings;
293186570Sed
294186570Sed		bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
295186570Sed		strcpy(s, ostype);
296186570Sed		s += strlen(s) + 1;
297186570Sed
298186570Sed		bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
299186570Sed		strcpy(s, osrelease);
300186570Sed		s += strlen(s) + 1;
301186570Sed
302186570Sed		bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
303186570Sed		strcpy(s, machine);
304186570Sed		s += strlen(s) + 1;
305186570Sed
306186570Sed		needed = sizeof(bsdi_si) + (s - bsdi_strings);
307186570Sed
308186570Sed		if ((uap->where == NULL) || (uap->size == NULL)) {
309186570Sed			/* process is asking how much buffer to supply.. */
310186570Sed			size = needed;
311186570Sed			error = 0;
312186570Sed			break;
313186570Sed		}
314186570Sed
315186570Sed		if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
316186570Sed			break;
317186570Sed
318186570Sed		/* if too much buffer supplied, trim it down */
319186570Sed		if (size > needed)
320186570Sed			size = needed;
321186570Sed
322186570Sed		/* how much of the buffer is remaining */
323186570Sed		left = size;
324186570Sed
325186570Sed		if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
326186570Sed			break;
327186570Sed
328186570Sed		/* is there any point in continuing? */
329186570Sed		if (left > sizeof(bsdi_si)) {
330186570Sed			left -= sizeof(bsdi_si);
331186570Sed			error = copyout(&bsdi_strings,
332186570Sed					uap->where + sizeof(bsdi_si), left);
333186570Sed		}
334186570Sed		break;
335186570Sed	}
336186570Sed
337186570Sed	default:
338186570Sed		error = EOPNOTSUPP;
339186570Sed		break;
340186570Sed	}
341186570Sed	if (error == 0) {
342186570Sed		td->td_retval[0] = needed ? needed : size;
343186570Sed		if (uap->size) {
344186570Sed			error = copyout(&size, uap->size, sizeof(size));
345186570Sed		}
346186570Sed	}
347186570Sed	return (error);
348186570Sed}
3491541Srgrimes#endif /* COMPAT_43 */
3501549Srgrimes
351184789Sed#ifdef COMPAT_FREEBSD4
35274729Speter/*
353184789Sed * This is the FreeBSD-1.1 compatible uname(2) interface.  These days it is
354167232Srwatson * done in libc as a wrapper around a bunch of sysctl's.  This must maintain
355167232Srwatson * the old 1.1 binary ABI.
35674729Speter */
35774729Speter#if SYS_NMLN != 32
35874729Speter#error "FreeBSD-1.1 uname syscall has been broken"
35974729Speter#endif
36012221Sbde#ifndef _SYS_SYSPROTO_H_
3611549Srgrimesstruct uname_args {
362180039Sjulian	struct utsname  *name;
3631549Srgrimes};
36412221Sbde#endif
3651549Srgrimes/* ARGSUSED */
3661549Srgrimesint
367184789Sedfreebsd4_uname(struct thread *td, struct freebsd4_uname_args *uap)
3681549Srgrimes{
36982717Sdillon	int name[2], error;
37038517Sdfr	size_t len;
3711549Srgrimes	char *s, *us;
3721549Srgrimes
37312171Sphk	name[0] = CTL_KERN;
37412171Sphk	name[1] = KERN_OSTYPE;
37582717Sdillon	len = sizeof (uap->name->sysname);
37683366Sjulian	error = userland_sysctl(td, name, 2, uap->name->sysname, &len,
377136404Speter		1, 0, 0, 0, 0);
37882717Sdillon	if (error)
379186564Sed		return (error);
3801549Srgrimes	subyte( uap->name->sysname + sizeof(uap->name->sysname) - 1, 0);
3811549Srgrimes
38212171Sphk	name[1] = KERN_HOSTNAME;
3831549Srgrimes	len = sizeof uap->name->nodename;
38483366Sjulian	error = userland_sysctl(td, name, 2, uap->name->nodename, &len,
385136404Speter		1, 0, 0, 0, 0);
38682717Sdillon	if (error)
387186564Sed		return (error);
3881549Srgrimes	subyte( uap->name->nodename + sizeof(uap->name->nodename) - 1, 0);
3891549Srgrimes
39012171Sphk	name[1] = KERN_OSRELEASE;
3911549Srgrimes	len = sizeof uap->name->release;
39283366Sjulian	error = userland_sysctl(td, name, 2, uap->name->release, &len,
393136404Speter		1, 0, 0, 0, 0);
39482717Sdillon	if (error)
395186564Sed		return (error);
3961549Srgrimes	subyte( uap->name->release + sizeof(uap->name->release) - 1, 0);
3971549Srgrimes
3981549Srgrimes/*
3991549Srgrimes	name = KERN_VERSION;
4001549Srgrimes	len = sizeof uap->name->version;
40183366Sjulian	error = userland_sysctl(td, name, 2, uap->name->version, &len,
402136404Speter		1, 0, 0, 0, 0);
40382717Sdillon	if (error)
404186564Sed		return (error);
4051549Srgrimes	subyte( uap->name->version + sizeof(uap->name->version) - 1, 0);
4061549Srgrimes*/
4071549Srgrimes
4081549Srgrimes/*
4091549Srgrimes * this stupid hackery to make the version field look like FreeBSD 1.1
4101549Srgrimes */
4111549Srgrimes	for(s = version; *s && *s != '#'; s++);
4121549Srgrimes
4131549Srgrimes	for(us = uap->name->version; *s && *s != ':'; s++) {
41482717Sdillon		error = subyte( us++, *s);
41582717Sdillon		if (error)
416186564Sed			return (error);
4171549Srgrimes	}
41882717Sdillon	error = subyte( us++, 0);
41982717Sdillon	if (error)
420186564Sed		return (error);
4211549Srgrimes
42238517Sdfr	name[0] = CTL_HW;
42312171Sphk	name[1] = HW_MACHINE;
4241549Srgrimes	len = sizeof uap->name->machine;
42583366Sjulian	error = userland_sysctl(td, name, 2, uap->name->machine, &len,
426136404Speter		1, 0, 0, 0, 0);
42782717Sdillon	if (error)
428186564Sed		return (error);
4291549Srgrimes	subyte( uap->name->machine + sizeof(uap->name->machine) - 1, 0);
430186564Sed	return (0);
4311549Srgrimes}
4321549Srgrimes
43312221Sbde#ifndef _SYS_SYSPROTO_H_
4341549Srgrimesstruct getdomainname_args {
435180039Sjulian	char    *domainname;
436180039Sjulian	int     len;
4371549Srgrimes};
43812222Sbde#endif
4391549Srgrimes/* ARGSUSED */
4401549Srgrimesint
441184789Sedfreebsd4_getdomainname(struct thread *td,
442184789Sed    struct freebsd4_getdomainname_args *uap)
4431549Srgrimes{
444184789Sed	int name[2];
445184789Sed	size_t len = uap->len;
44682717Sdillon
447184789Sed	name[0] = CTL_KERN;
448184789Sed	name[1] = KERN_NISDOMAINNAME;
449186564Sed	return (userland_sysctl(td, name, 2, uap->domainname, &len,
450186564Sed	    1, 0, 0, 0, 0));
4511549Srgrimes}
4521549Srgrimes
45312221Sbde#ifndef _SYS_SYSPROTO_H_
4541549Srgrimesstruct setdomainname_args {
455180039Sjulian	char    *domainname;
456180039Sjulian	int     len;
4571549Srgrimes};
45812221Sbde#endif
4591549Srgrimes/* ARGSUSED */
4601549Srgrimesint
461184789Sedfreebsd4_setdomainname(struct thread *td,
462184789Sed    struct freebsd4_setdomainname_args *uap)
4631549Srgrimes{
464184789Sed	int name[2];
4651549Srgrimes
466184789Sed	name[0] = CTL_KERN;
467184789Sed	name[1] = KERN_NISDOMAINNAME;
468186564Sed	return (userland_sysctl(td, name, 2, 0, 0, 0, uap->domainname,
469186564Sed	    uap->len, 0, 0));
4701549Srgrimes}
471184789Sed#endif /* COMPAT_FREEBSD4 */
472