kern_xxx.c revision 331643
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1982, 1986, 1989, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	@(#)kern_xxx.c	8.2 (Berkeley) 11/14/93
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/11/sys/kern/kern_xxx.c 331643 2018-03-27 18:52:27Z dim $");
36
37#include "opt_compat.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/sysproto.h>
42#include <sys/kernel.h>
43#include <sys/priv.h>
44#include <sys/proc.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <sys/socket.h>
48#include <sys/sysctl.h>
49#include <sys/utsname.h>
50
51#include <vm/vm_param.h>
52
53#if defined(COMPAT_43)
54
55#ifndef _SYS_SYSPROTO_H_
56struct gethostname_args {
57	char	*hostname;
58	u_int	len;
59};
60#endif
61/* ARGSUSED */
62int
63ogethostname(struct thread *td, struct gethostname_args *uap)
64{
65	int name[2];
66	size_t len = uap->len;
67
68	name[0] = CTL_KERN;
69	name[1] = KERN_HOSTNAME;
70	return (userland_sysctl(td, name, 2, uap->hostname, &len,
71	    1, 0, 0, 0, 0));
72}
73
74#ifndef _SYS_SYSPROTO_H_
75struct sethostname_args {
76	char	*hostname;
77	u_int	len;
78};
79#endif
80/* ARGSUSED */
81int
82osethostname(struct thread *td, struct sethostname_args *uap)
83{
84	int name[2];
85
86	name[0] = CTL_KERN;
87	name[1] = KERN_HOSTNAME;
88	return (userland_sysctl(td, name, 2, 0, 0, 0, uap->hostname,
89	    uap->len, 0, 0));
90}
91
92#ifndef _SYS_SYSPROTO_H_
93struct ogethostid_args {
94	int	dummy;
95};
96#endif
97/* ARGSUSED */
98int
99ogethostid(struct thread *td, struct ogethostid_args *uap)
100{
101	size_t len = sizeof(long);
102	int name[2];
103
104	name[0] = CTL_KERN;
105	name[1] = KERN_HOSTID;
106	return (kernel_sysctl(td, name, 2, (long *)td->td_retval, &len,
107	    NULL, 0, NULL, 0));
108}
109#endif /* COMPAT_43 */
110
111#ifdef COMPAT_43
112#ifndef _SYS_SYSPROTO_H_
113struct osethostid_args {
114	long	hostid;
115};
116#endif
117/* ARGSUSED */
118int
119osethostid(struct thread *td, struct osethostid_args *uap)
120{
121	int name[2];
122
123	name[0] = CTL_KERN;
124	name[1] = KERN_HOSTID;
125	return (kernel_sysctl(td, name, 2, NULL, NULL, &uap->hostid,
126	    sizeof(uap->hostid), NULL, 0));
127}
128
129int
130oquota(struct thread *td, struct oquota_args *uap)
131{
132
133	return (ENOSYS);
134}
135
136#define	KINFO_PROC		(0<<8)
137#define	KINFO_RT		(1<<8)
138#define	KINFO_VNODE		(2<<8)
139#define	KINFO_FILE		(3<<8)
140#define	KINFO_METER		(4<<8)
141#define	KINFO_LOADAVG		(5<<8)
142#define	KINFO_CLOCKRATE		(6<<8)
143
144/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
145#define	KINFO_BSDI_SYSINFO	(101<<8)
146
147/*
148 * XXX this is bloat, but I hope it's better here than on the potentially
149 * limited kernel stack...  -Peter
150 */
151
152static struct {
153	int	bsdi_machine;		/* "i386" on BSD/386 */
154/*      ^^^ this is an offset to the string, relative to the struct start */
155	char	*pad0;
156	long	pad1;
157	long	pad2;
158	long	pad3;
159	u_long	pad4;
160	u_long	pad5;
161	u_long	pad6;
162
163	int	bsdi_ostype;		/* "BSD/386" on BSD/386 */
164	int	bsdi_osrelease;		/* "1.1" on BSD/386 */
165	long	pad7;
166	long	pad8;
167	char	*pad9;
168
169	long	pad10;
170	long	pad11;
171	int	pad12;
172	long	pad13;
173	quad_t	pad14;
174	long	pad15;
175
176	struct	timeval pad16;
177	/* we dont set this, because BSDI's uname used gethostname() instead */
178	int	bsdi_hostname;		/* hostname on BSD/386 */
179
180	/* the actual string data is appended here */
181
182} bsdi_si;
183
184/*
185 * this data is appended to the end of the bsdi_si structure during copyout.
186 * The "char *" offsets are relative to the base of the bsdi_si struct.
187 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
188 * should not exceed the length of the buffer here... (or else!! :-)
189 */
190static char bsdi_strings[80];	/* It had better be less than this! */
191
192#ifndef _SYS_SYSPROTO_H_
193struct getkerninfo_args {
194	int	op;
195	char	*where;
196	size_t	*size;
197	int	arg;
198};
199#endif
200int
201ogetkerninfo(struct thread *td, struct getkerninfo_args *uap)
202{
203	int error, name[6];
204	size_t size;
205	u_int needed = 0;
206
207	switch (uap->op & 0xff00) {
208
209	case KINFO_RT:
210		name[0] = CTL_NET;
211		name[1] = PF_ROUTE;
212		name[2] = 0;
213		name[3] = (uap->op & 0xff0000) >> 16;
214		name[4] = uap->op & 0xff;
215		name[5] = uap->arg;
216		error = userland_sysctl(td, name, 6, uap->where, uap->size,
217			0, 0, 0, &size, 0);
218		break;
219
220	case KINFO_VNODE:
221		name[0] = CTL_KERN;
222		name[1] = KERN_VNODE;
223		error = userland_sysctl(td, name, 2, uap->where, uap->size,
224			0, 0, 0, &size, 0);
225		break;
226
227	case KINFO_PROC:
228		name[0] = CTL_KERN;
229		name[1] = KERN_PROC;
230		name[2] = uap->op & 0xff;
231		name[3] = uap->arg;
232		error = userland_sysctl(td, name, 4, uap->where, uap->size,
233			0, 0, 0, &size, 0);
234		break;
235
236	case KINFO_FILE:
237		name[0] = CTL_KERN;
238		name[1] = KERN_FILE;
239		error = userland_sysctl(td, name, 2, uap->where, uap->size,
240			0, 0, 0, &size, 0);
241		break;
242
243	case KINFO_METER:
244		name[0] = CTL_VM;
245		name[1] = VM_TOTAL;
246		error = userland_sysctl(td, name, 2, uap->where, uap->size,
247			0, 0, 0, &size, 0);
248		break;
249
250	case KINFO_LOADAVG:
251		name[0] = CTL_VM;
252		name[1] = VM_LOADAVG;
253		error = userland_sysctl(td, name, 2, uap->where, uap->size,
254			0, 0, 0, &size, 0);
255		break;
256
257	case KINFO_CLOCKRATE:
258		name[0] = CTL_KERN;
259		name[1] = KERN_CLOCKRATE;
260		error = userland_sysctl(td, name, 2, uap->where, uap->size,
261			0, 0, 0, &size, 0);
262		break;
263
264	case KINFO_BSDI_SYSINFO: {
265		/*
266		 * this is pretty crude, but it's just enough for uname()
267		 * from BSDI's 1.x libc to work.
268		 *
269		 * *size gives the size of the buffer before the call, and
270		 * the amount of data copied after a successful call.
271		 * If successful, the return value is the amount of data
272		 * available, which can be larger than *size.
273		 *
274		 * BSDI's 2.x product apparently fails with ENOMEM if *size
275		 * is too small.
276		 */
277
278		u_int left;
279		char *s;
280
281		bzero((char *)&bsdi_si, sizeof(bsdi_si));
282		bzero(bsdi_strings, sizeof(bsdi_strings));
283
284		s = bsdi_strings;
285
286		bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
287		strcpy(s, ostype);
288		s += strlen(s) + 1;
289
290		bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
291		strcpy(s, osrelease);
292		s += strlen(s) + 1;
293
294		bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
295		strcpy(s, machine);
296		s += strlen(s) + 1;
297
298		needed = sizeof(bsdi_si) + (s - bsdi_strings);
299
300		if ((uap->where == NULL) || (uap->size == NULL)) {
301			/* process is asking how much buffer to supply.. */
302			size = needed;
303			error = 0;
304			break;
305		}
306
307		if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
308			break;
309
310		/* if too much buffer supplied, trim it down */
311		if (size > needed)
312			size = needed;
313
314		/* how much of the buffer is remaining */
315		left = size;
316
317		if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
318			break;
319
320		/* is there any point in continuing? */
321		if (left > sizeof(bsdi_si)) {
322			left -= sizeof(bsdi_si);
323			error = copyout(&bsdi_strings,
324					uap->where + sizeof(bsdi_si), left);
325		}
326		break;
327	}
328
329	default:
330		error = EOPNOTSUPP;
331		break;
332	}
333	if (error == 0) {
334		td->td_retval[0] = needed ? needed : size;
335		if (uap->size) {
336			error = copyout(&size, uap->size, sizeof(size));
337		}
338	}
339	return (error);
340}
341#endif /* COMPAT_43 */
342
343#ifdef COMPAT_FREEBSD4
344/*
345 * This is the FreeBSD-1.1 compatible uname(2) interface.  These days it is
346 * done in libc as a wrapper around a bunch of sysctl's.  This must maintain
347 * the old 1.1 binary ABI.
348 */
349#if SYS_NMLN != 32
350#error "FreeBSD-1.1 uname syscall has been broken"
351#endif
352#ifndef _SYS_SYSPROTO_H_
353struct uname_args {
354	struct utsname  *name;
355};
356#endif
357/* ARGSUSED */
358int
359freebsd4_uname(struct thread *td, struct freebsd4_uname_args *uap)
360{
361	int name[2], error;
362	size_t len;
363	char *s, *us;
364
365	name[0] = CTL_KERN;
366	name[1] = KERN_OSTYPE;
367	len = sizeof (uap->name->sysname);
368	error = userland_sysctl(td, name, 2, uap->name->sysname, &len,
369		1, 0, 0, 0, 0);
370	if (error)
371		return (error);
372	subyte( uap->name->sysname + sizeof(uap->name->sysname) - 1, 0);
373
374	name[1] = KERN_HOSTNAME;
375	len = sizeof uap->name->nodename;
376	error = userland_sysctl(td, name, 2, uap->name->nodename, &len,
377		1, 0, 0, 0, 0);
378	if (error)
379		return (error);
380	subyte( uap->name->nodename + sizeof(uap->name->nodename) - 1, 0);
381
382	name[1] = KERN_OSRELEASE;
383	len = sizeof uap->name->release;
384	error = userland_sysctl(td, name, 2, uap->name->release, &len,
385		1, 0, 0, 0, 0);
386	if (error)
387		return (error);
388	subyte( uap->name->release + sizeof(uap->name->release) - 1, 0);
389
390/*
391	name = KERN_VERSION;
392	len = sizeof uap->name->version;
393	error = userland_sysctl(td, name, 2, uap->name->version, &len,
394		1, 0, 0, 0, 0);
395	if (error)
396		return (error);
397	subyte( uap->name->version + sizeof(uap->name->version) - 1, 0);
398*/
399
400/*
401 * this stupid hackery to make the version field look like FreeBSD 1.1
402 */
403	for(s = version; *s && *s != '#'; s++);
404
405	for(us = uap->name->version; *s && *s != ':'; s++) {
406		error = subyte( us++, *s);
407		if (error)
408			return (error);
409	}
410	error = subyte( us++, 0);
411	if (error)
412		return (error);
413
414	name[0] = CTL_HW;
415	name[1] = HW_MACHINE;
416	len = sizeof uap->name->machine;
417	error = userland_sysctl(td, name, 2, uap->name->machine, &len,
418		1, 0, 0, 0, 0);
419	if (error)
420		return (error);
421	subyte( uap->name->machine + sizeof(uap->name->machine) - 1, 0);
422	return (0);
423}
424
425#ifndef _SYS_SYSPROTO_H_
426struct getdomainname_args {
427	char    *domainname;
428	int     len;
429};
430#endif
431/* ARGSUSED */
432int
433freebsd4_getdomainname(struct thread *td,
434    struct freebsd4_getdomainname_args *uap)
435{
436	int name[2];
437	size_t len = uap->len;
438
439	name[0] = CTL_KERN;
440	name[1] = KERN_NISDOMAINNAME;
441	return (userland_sysctl(td, name, 2, uap->domainname, &len,
442	    1, 0, 0, 0, 0));
443}
444
445#ifndef _SYS_SYSPROTO_H_
446struct setdomainname_args {
447	char    *domainname;
448	int     len;
449};
450#endif
451/* ARGSUSED */
452int
453freebsd4_setdomainname(struct thread *td,
454    struct freebsd4_setdomainname_args *uap)
455{
456	int name[2];
457
458	name[0] = CTL_KERN;
459	name[1] = KERN_NISDOMAINNAME;
460	return (userland_sysctl(td, name, 2, 0, 0, 0, uap->domainname,
461	    uap->len, 0, 0));
462}
463#endif /* COMPAT_FREEBSD4 */
464