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