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