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 * 3. 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
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/sysproto.h>
35 #include <sys/kernel.h>
36 #include <sys/priv.h>
37 #include <sys/proc.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/socket.h>
41 #include <sys/sysctl.h>
42 #include <sys/utsname.h>
43
44 #include <vm/vm_param.h>
45
46 #if defined(COMPAT_43)
47
48 int
ogethostname(struct thread * td,struct ogethostname_args * uap)49 ogethostname(struct thread *td, struct ogethostname_args *uap)
50 {
51 int name[2];
52 size_t len = uap->len;
53
54 name[0] = CTL_KERN;
55 name[1] = KERN_HOSTNAME;
56 return (userland_sysctl(td, name, 2, uap->hostname, &len,
57 1, 0, 0, 0, 0));
58 }
59
60 int
osethostname(struct thread * td,struct osethostname_args * uap)61 osethostname(struct thread *td, struct osethostname_args *uap)
62 {
63 int name[2];
64
65 name[0] = CTL_KERN;
66 name[1] = KERN_HOSTNAME;
67 return (userland_sysctl(td, name, 2, 0, 0, 0, uap->hostname,
68 uap->len, 0, 0));
69 }
70
71 #ifndef _SYS_SYSPROTO_H_
72 struct ogethostid_args {
73 int dummy;
74 };
75 #endif
76 /* ARGSUSED */
77 int
ogethostid(struct thread * td,struct ogethostid_args * uap)78 ogethostid(struct thread *td, struct ogethostid_args *uap)
79 {
80 size_t len = sizeof(long);
81 int name[2];
82
83 name[0] = CTL_KERN;
84 name[1] = KERN_HOSTID;
85 return (kernel_sysctl(td, name, 2, (long *)td->td_retval, &len,
86 NULL, 0, NULL, 0));
87 }
88
89 int
osethostid(struct thread * td,struct osethostid_args * uap)90 osethostid(struct thread *td, struct osethostid_args *uap)
91 {
92 int name[2];
93
94 name[0] = CTL_KERN;
95 name[1] = KERN_HOSTID;
96 return (kernel_sysctl(td, name, 2, NULL, NULL, &uap->hostid,
97 sizeof(uap->hostid), NULL, 0));
98 }
99
100 int
oquota(struct thread * td,struct oquota_args * uap)101 oquota(struct thread *td, struct oquota_args *uap)
102 {
103
104 return (ENOSYS);
105 }
106
107 #define KINFO_PROC (0<<8)
108 #define KINFO_RT (1<<8)
109 /* UNUSED, was KINFO_VNODE (2<<8) */
110 #define KINFO_FILE (3<<8)
111 #define KINFO_METER (4<<8)
112 #define KINFO_LOADAVG (5<<8)
113 #define KINFO_CLOCKRATE (6<<8)
114
115 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
116 #define KINFO_BSDI_SYSINFO (101<<8)
117
118 /*
119 * XXX this is bloat, but I hope it's better here than on the potentially
120 * limited kernel stack... -Peter
121 */
122
123 static struct {
124 int bsdi_machine; /* "i386" on BSD/386 */
125 /* ^^^ this is an offset to the string, relative to the struct start */
126 char *pad0;
127 long pad1;
128 long pad2;
129 long pad3;
130 u_long pad4;
131 u_long pad5;
132 u_long pad6;
133
134 int bsdi_ostype; /* "BSD/386" on BSD/386 */
135 int bsdi_osrelease; /* "1.1" on BSD/386 */
136 long pad7;
137 long pad8;
138 char *pad9;
139
140 long pad10;
141 long pad11;
142 int pad12;
143 long pad13;
144 quad_t pad14;
145 long pad15;
146
147 struct timeval pad16;
148 /* we dont set this, because BSDI's uname used gethostname() instead */
149 int bsdi_hostname; /* hostname on BSD/386 */
150
151 /* the actual string data is appended here */
152
153 } bsdi_si;
154
155 /*
156 * this data is appended to the end of the bsdi_si structure during copyout.
157 * The "char *" offsets are relative to the base of the bsdi_si struct.
158 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
159 * should not exceed the length of the buffer here... (or else!! :-)
160 */
161 static char bsdi_strings[80]; /* It had better be less than this! */
162
163 int
ogetkerninfo(struct thread * td,struct ogetkerninfo_args * uap)164 ogetkerninfo(struct thread *td, struct ogetkerninfo_args *uap)
165 {
166 int error, name[6];
167 size_t size;
168 u_int needed = 0;
169
170 switch (uap->op & 0xff00) {
171 case KINFO_RT:
172 name[0] = CTL_NET;
173 name[1] = PF_ROUTE;
174 name[2] = 0;
175 name[3] = (uap->op & 0xff0000) >> 16;
176 name[4] = uap->op & 0xff;
177 name[5] = uap->arg;
178 error = userland_sysctl(td, name, 6, uap->where, uap->size,
179 0, 0, 0, &size, 0);
180 break;
181
182 case KINFO_PROC:
183 name[0] = CTL_KERN;
184 name[1] = KERN_PROC;
185 name[2] = uap->op & 0xff;
186 name[3] = uap->arg;
187 error = userland_sysctl(td, name, 4, uap->where, uap->size,
188 0, 0, 0, &size, 0);
189 break;
190
191 case KINFO_FILE:
192 name[0] = CTL_KERN;
193 name[1] = KERN_FILE;
194 error = userland_sysctl(td, name, 2, uap->where, uap->size,
195 0, 0, 0, &size, 0);
196 break;
197
198 case KINFO_METER:
199 name[0] = CTL_VM;
200 name[1] = VM_TOTAL;
201 error = userland_sysctl(td, name, 2, uap->where, uap->size,
202 0, 0, 0, &size, 0);
203 break;
204
205 case KINFO_LOADAVG:
206 name[0] = CTL_VM;
207 name[1] = VM_LOADAVG;
208 error = userland_sysctl(td, name, 2, uap->where, uap->size,
209 0, 0, 0, &size, 0);
210 break;
211
212 case KINFO_CLOCKRATE:
213 name[0] = CTL_KERN;
214 name[1] = KERN_CLOCKRATE;
215 error = userland_sysctl(td, name, 2, uap->where, uap->size,
216 0, 0, 0, &size, 0);
217 break;
218
219 case KINFO_BSDI_SYSINFO: {
220 /*
221 * this is pretty crude, but it's just enough for uname()
222 * from BSDI's 1.x libc to work.
223 *
224 * *size gives the size of the buffer before the call, and
225 * the amount of data copied after a successful call.
226 * If successful, the return value is the amount of data
227 * available, which can be larger than *size.
228 *
229 * BSDI's 2.x product apparently fails with ENOMEM if *size
230 * is too small.
231 */
232
233 u_int left;
234 char *s;
235
236 bzero((char *)&bsdi_si, sizeof(bsdi_si));
237 bzero(bsdi_strings, sizeof(bsdi_strings));
238
239 s = bsdi_strings;
240
241 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
242 strcpy(s, ostype);
243 s += strlen(s) + 1;
244
245 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
246 strcpy(s, osrelease);
247 s += strlen(s) + 1;
248
249 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
250 strcpy(s, machine);
251 s += strlen(s) + 1;
252
253 needed = sizeof(bsdi_si) + (s - bsdi_strings);
254
255 if ((uap->where == NULL) || (uap->size == NULL)) {
256 /* process is asking how much buffer to supply.. */
257 size = needed;
258 error = 0;
259 break;
260 }
261
262 if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
263 break;
264
265 /* if too much buffer supplied, trim it down */
266 if (size > needed)
267 size = needed;
268
269 /* how much of the buffer is remaining */
270 left = size;
271
272 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
273 break;
274
275 /* is there any point in continuing? */
276 if (left > sizeof(bsdi_si)) {
277 left -= sizeof(bsdi_si);
278 error = copyout(&bsdi_strings,
279 uap->where + sizeof(bsdi_si), left);
280 }
281 break;
282 }
283
284 default:
285 error = EOPNOTSUPP;
286 break;
287 }
288 if (error == 0) {
289 td->td_retval[0] = needed ? needed : size;
290 if (uap->size) {
291 error = copyout(&size, uap->size, sizeof(size));
292 }
293 }
294 return (error);
295 }
296 #endif /* COMPAT_43 */
297
298 #ifdef COMPAT_FREEBSD4
299 /*
300 * This is the FreeBSD-1.1 compatible uname(2) interface. These days it is
301 * done in libc as a wrapper around a bunch of sysctl's. This must maintain
302 * the old 1.1 binary ABI.
303 */
304 #if SYS_NMLN != 32
305 #error "FreeBSD-1.1 uname syscall has been broken"
306 #endif
307 #ifndef _SYS_SYSPROTO_H_
308 struct uname_args {
309 struct utsname *name;
310 };
311 #endif
312 /* ARGSUSED */
313 int
freebsd4_uname(struct thread * td,struct freebsd4_uname_args * uap)314 freebsd4_uname(struct thread *td, struct freebsd4_uname_args *uap)
315 {
316 int name[2], error;
317 size_t len;
318 const char *s;
319 char *us;
320
321 name[0] = CTL_KERN;
322 name[1] = KERN_OSTYPE;
323 len = sizeof (uap->name->sysname);
324 error = userland_sysctl(td, name, 2, uap->name->sysname, &len,
325 1, 0, 0, 0, 0);
326 if (error)
327 return (error);
328 error = subyte(uap->name->sysname + sizeof(uap->name->sysname) - 1, 0);
329 if (error)
330 return (EFAULT);
331
332 name[1] = KERN_HOSTNAME;
333 len = sizeof uap->name->nodename;
334 error = userland_sysctl(td, name, 2, uap->name->nodename, &len,
335 1, 0, 0, 0, 0);
336 if (error)
337 return (error);
338 error = subyte(uap->name->nodename + sizeof(uap->name->nodename) - 1, 0);
339 if (error)
340 return (EFAULT);
341
342 name[1] = KERN_OSRELEASE;
343 len = sizeof uap->name->release;
344 error = userland_sysctl(td, name, 2, uap->name->release, &len,
345 1, 0, 0, 0, 0);
346 if (error)
347 return (error);
348 error = subyte(uap->name->release + sizeof(uap->name->release) - 1, 0);
349 if (error)
350 return (EFAULT);
351
352 /*
353 name = KERN_VERSION;
354 len = sizeof uap->name->version;
355 error = userland_sysctl(td, name, 2, uap->name->version, &len,
356 1, 0, 0, 0, 0);
357 if (error)
358 return (error);
359 subyte( uap->name->version + sizeof(uap->name->version) - 1, 0);
360 */
361
362 /*
363 * this stupid hackery to make the version field look like FreeBSD 1.1
364 */
365 for(s = version; *s && *s != '#'; s++);
366
367 for(us = uap->name->version; *s && *s != ':'; s++) {
368 if (subyte(us++, *s) != 0)
369 return (EFAULT);
370 }
371 if (subyte(us++, 0) != 0)
372 return (EFAULT);
373
374 name[0] = CTL_HW;
375 name[1] = HW_MACHINE;
376 len = sizeof uap->name->machine;
377 error = userland_sysctl(td, name, 2, uap->name->machine, &len,
378 1, 0, 0, 0, 0);
379 if (error)
380 return (error);
381 error = subyte(uap->name->machine + sizeof(uap->name->machine) - 1, 0);
382 if (error)
383 return (EFAULT);
384 return (0);
385 }
386
387 #ifndef _SYS_SYSPROTO_H_
388 struct getdomainname_args {
389 char *domainname;
390 int len;
391 };
392 #endif
393 /* ARGSUSED */
394 int
freebsd4_getdomainname(struct thread * td,struct freebsd4_getdomainname_args * uap)395 freebsd4_getdomainname(struct thread *td,
396 struct freebsd4_getdomainname_args *uap)
397 {
398 int name[2];
399 size_t len = uap->len;
400
401 name[0] = CTL_KERN;
402 name[1] = KERN_NISDOMAINNAME;
403 return (userland_sysctl(td, name, 2, uap->domainname, &len,
404 1, 0, 0, 0, 0));
405 }
406
407 #ifndef _SYS_SYSPROTO_H_
408 struct setdomainname_args {
409 char *domainname;
410 int len;
411 };
412 #endif
413 /* ARGSUSED */
414 int
freebsd4_setdomainname(struct thread * td,struct freebsd4_setdomainname_args * uap)415 freebsd4_setdomainname(struct thread *td,
416 struct freebsd4_setdomainname_args *uap)
417 {
418 int name[2];
419
420 name[0] = CTL_KERN;
421 name[1] = KERN_NISDOMAINNAME;
422 return (userland_sysctl(td, name, 2, 0, 0, 0, uap->domainname,
423 uap->len, 0, 0));
424 }
425 #endif /* COMPAT_FREEBSD4 */
426