kernel - Move MP lock inward, plus misc other stuff
[dragonfly.git] / sys / emulation / 43bsd / 43bsd_hostinfo.c
1 /*
2  * 43BSD_HOSTINFO.C     - 4.3BSD compatibility host info syscalls
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. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * $DragonFly: src/sys/emulation/43bsd/43bsd_hostinfo.c,v 1.4 2006/09/05 00:55:44 dillon Exp $
36  *      from: DragonFly kern/kern_xxx.c,v 1.7
37  *      from: DragonFly kern/kern_sysctl.c,v 1.12
38  *
39  * These syscalls used to live in kern/kern_xxx.c and kern/kern_sysctl.c.
40  */
41
42 #include "opt_compat.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/sysproto.h>
47 #include <sys/kernel.h>
48 #include <sys/proc.h>
49 #include <sys/priv.h>
50 #include <sys/socket.h>
51 #include <sys/sysctl.h>
52 #include <vm/vm_param.h>
53
54 /*
55  * MPALMOSTSAFE
56  */
57 int
58 sys_ogethostname(struct gethostname_args *uap)
59 {
60         size_t len;
61         char *hostname;
62         int error, name[2];
63
64         name[0] = CTL_KERN;
65         name[1] = KERN_HOSTNAME;
66         len = MIN(uap->len, MAXHOSTNAMELEN);
67         hostname = kmalloc(MAXHOSTNAMELEN, M_TEMP, M_WAITOK);
68
69         get_mplock();
70         error = kernel_sysctl(name, 2, hostname, &len, NULL, 0, NULL);
71         rel_mplock();
72
73         if (error == 0)
74                 error = copyout(hostname, uap->hostname, len);
75
76         kfree(hostname, M_TEMP);
77         return (error);
78 }
79
80 /*
81  * MPALMOSTSAFE
82  */
83 int
84 sys_osethostname(struct sethostname_args *uap)
85 {
86         struct thread *td = curthread;
87         struct proc *p = td->td_proc;
88         size_t len;
89         char *hostname;
90         int name[2];
91         int error;
92
93         KKASSERT(p);
94         name[0] = CTL_KERN;
95         name[1] = KERN_HOSTNAME;
96         error = priv_check_cred(p->p_ucred, PRIV_SETHOSTNAME, 0);
97         if (error)
98                 return (error);
99         len = MIN(uap->len, MAXHOSTNAMELEN);
100         hostname = kmalloc(MAXHOSTNAMELEN, M_TEMP, M_WAITOK);
101
102         error = copyin(uap->hostname, hostname, len);
103         if (error) {
104                 kfree(hostname, M_TEMP);
105                 return (error);
106         }
107
108         get_mplock();
109         error = kernel_sysctl(name, 2, NULL, 0, hostname, len, NULL);
110         rel_mplock();
111
112         kfree(hostname, M_TEMP);
113         return (error);
114 }
115
116 /*
117  * MPSAFE
118  */
119 int
120 sys_ogethostid(struct ogethostid_args *uap)
121 {
122         uap->sysmsg_lresult = hostid;
123         return (0);
124 }
125
126 /*
127  * MPSAFE
128  */
129 int
130 sys_osethostid(struct osethostid_args *uap)
131 {
132         struct thread *td = curthread;
133         int error;
134
135         error = priv_check(td, PRIV_ROOT);
136         if (error)
137                 return (error);
138         hostid = uap->hostid;
139         return (0);
140 }
141
142 /*
143  * MPSAFE
144  */
145 int
146 sys_oquota(struct oquota_args *uap)
147 {
148         return (ENOSYS);
149 }
150
151 #define KINFO_PROC              (0<<8)
152 #define KINFO_RT                (1<<8)
153 #define KINFO_VNODE             (2<<8)
154 #define KINFO_FILE              (3<<8)
155 #define KINFO_METER             (4<<8)
156 #define KINFO_LOADAVG           (5<<8)
157 #define KINFO_CLOCKRATE         (6<<8)
158
159 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
160 #define KINFO_BSDI_SYSINFO      (101<<8)
161
162 /*
163  * XXX this is bloat, but I hope it's better here than on the potentially
164  * limited kernel stack...  -Peter
165  */
166
167 static struct {
168         int     bsdi_machine;           /* "i386" on BSD/386 */
169 /*      ^^^ this is an offset to the string, relative to the struct start */
170         char    *pad0;
171         long    pad1;
172         long    pad2;
173         long    pad3;
174         u_long  pad4;
175         u_long  pad5;
176         u_long  pad6;
177
178         int     bsdi_ostype;            /* "BSD/386" on BSD/386 */
179         int     bsdi_osrelease;         /* "1.1" on BSD/386 */
180         long    pad7;
181         long    pad8;
182         char    *pad9;
183
184         long    pad10;
185         long    pad11;
186         int     pad12;
187         long    pad13;
188         quad_t  pad14;
189         long    pad15;
190
191         struct  timeval pad16;
192         /* we dont set this, because BSDI's uname used gethostname() instead */
193         int     bsdi_hostname;          /* hostname on BSD/386 */
194
195         /* the actual string data is appended here */
196
197 } bsdi_si;
198 /*
199  * this data is appended to the end of the bsdi_si structure during copyout.
200  * The "char *" offsets are relative to the base of the bsdi_si struct.
201  * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
202  * should not exceed the length of the buffer here... (or else!! :-)
203  */
204 static char bsdi_strings[80];   /* It had better be less than this! */
205
206 /*
207  * MPALMOSTSAFE
208  */
209 int
210 sys_ogetkerninfo(struct getkerninfo_args *uap)
211 {
212         int error, name[6];
213         size_t size;
214         u_int needed = 0;
215
216         get_mplock();
217
218         switch (uap->op & 0xff00) {
219         case KINFO_RT:
220                 name[0] = CTL_NET;
221                 name[1] = PF_ROUTE;
222                 name[2] = 0;
223                 name[3] = (uap->op & 0xff0000) >> 16;
224                 name[4] = uap->op & 0xff;
225                 name[5] = uap->arg;
226                 error = userland_sysctl(name, 6, uap->where, uap->size,
227                         0, 0, 0, &size);
228                 break;
229
230         case KINFO_VNODE:
231                 name[0] = CTL_KERN;
232                 name[1] = KERN_VNODE;
233                 error = userland_sysctl(name, 2, uap->where, uap->size,
234                         0, 0, 0, &size);
235                 break;
236
237         case KINFO_PROC:
238                 name[0] = CTL_KERN;
239                 name[1] = KERN_PROC;
240                 name[2] = uap->op & 0xff;
241                 name[3] = uap->arg;
242                 error = userland_sysctl(name, 4, uap->where, uap->size,
243                         0, 0, 0, &size);
244                 break;
245
246         case KINFO_FILE:
247                 name[0] = CTL_KERN;
248                 name[1] = KERN_FILE;
249                 error = userland_sysctl(name, 2, uap->where, uap->size,
250                         0, 0, 0, &size);
251                 break;
252
253         case KINFO_METER:
254                 name[0] = CTL_VM;
255                 name[1] = VM_METER;
256                 error = userland_sysctl(name, 2, uap->where, uap->size,
257                         0, 0, 0, &size);
258                 break;
259
260         case KINFO_LOADAVG:
261                 name[0] = CTL_VM;
262                 name[1] = VM_LOADAVG;
263                 error = userland_sysctl(name, 2, uap->where, uap->size,
264                         0, 0, 0, &size);
265                 break;
266
267         case KINFO_CLOCKRATE:
268                 name[0] = CTL_KERN;
269                 name[1] = KERN_CLOCKRATE;
270                 error = userland_sysctl(name, 2, uap->where, uap->size,
271                         0, 0, 0, &size);
272                 break;
273
274         case KINFO_BSDI_SYSINFO: {
275                 /*
276                  * this is pretty crude, but it's just enough for uname()
277                  * from BSDI's 1.x libc to work.
278                  * *size gives the size of the buffer before the call, and
279                  * the amount of data copied after a successful call.
280                  * If successful, the return value is the amount of data
281                  * available, which can be larger than *size.
282                  *
283                  * BSDI's 2.x product apparently fails with ENOMEM if
284                  * *size is too small.
285                  */
286
287                 u_int left;
288                 char *s;
289
290                 bzero((char *)&bsdi_si, sizeof(bsdi_si));
291                 bzero(bsdi_strings, sizeof(bsdi_strings));
292
293                 s = bsdi_strings;
294
295                 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
296                 strcpy(s, ostype);
297                 s += strlen(s) + 1;
298
299                 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
300                 strcpy(s, osrelease);
301                 s += strlen(s) + 1;
302
303                 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
304                 strcpy(s, machine);
305                 s += strlen(s) + 1;
306
307                 needed = sizeof(bsdi_si) + (s - bsdi_strings);
308
309                 if (uap->where == NULL || (uap->size == NULL)) {
310                         /* process is asking how much buffer to supply.. */
311                         size = needed;
312                         error = 0;
313                         break;
314                 }
315
316                 if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
317                                 break;
318
319                 /* if too much buffer supplied, trim it down */
320                 if (size > needed)
321                         size = needed;
322
323                 /* how much of the buffer is remaining */
324                 left = size;
325
326                 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
327                         break;
328
329                 /* is there any point in continuing? */
330                 if (left > sizeof(bsdi_si)) {
331                         left -= sizeof(bsdi_si);
332                         error = copyout(&bsdi_strings,
333                                         uap->where + sizeof(bsdi_si), left);
334                 }
335                 break;
336         }
337         default:
338                 error = EOPNOTSUPP;
339                 break;
340         }
341         rel_mplock();
342         if (error)
343                 return (error);
344         uap->sysmsg_iresult = (int)size;
345         if (uap->size)
346                 error = copyout(&size, uap->size, sizeof(size));
347         return (error);
348 }