Initial import of binutils 2.22 on the new vendor branch
[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
53 #include <vm/vm_param.h>
54
55 #include <sys/mplock2.h>
56
57 /*
58  * MPALMOSTSAFE
59  */
60 int
61 sys_ogethostname(struct gethostname_args *uap)
62 {
63         size_t len;
64         char *hostname;
65         int error, name[2];
66
67         name[0] = CTL_KERN;
68         name[1] = KERN_HOSTNAME;
69         len = MIN(uap->len, MAXHOSTNAMELEN);
70         hostname = kmalloc(MAXHOSTNAMELEN, M_TEMP, M_WAITOK);
71
72         get_mplock();
73         error = kernel_sysctl(name, 2, hostname, &len, NULL, 0, NULL);
74         rel_mplock();
75
76         if (error == 0)
77                 error = copyout(hostname, uap->hostname, len);
78
79         kfree(hostname, M_TEMP);
80         return (error);
81 }
82
83 /*
84  * MPALMOSTSAFE
85  */
86 int
87 sys_osethostname(struct sethostname_args *uap)
88 {
89         struct thread *td = curthread;
90         size_t len;
91         char *hostname;
92         int name[2];
93         int error;
94
95         name[0] = CTL_KERN;
96         name[1] = KERN_HOSTNAME;
97         error = priv_check_cred(td->td_ucred, PRIV_SETHOSTNAME, 0);
98         if (error)
99                 return (error);
100         len = MIN(uap->len, MAXHOSTNAMELEN);
101         hostname = kmalloc(MAXHOSTNAMELEN, M_TEMP, M_WAITOK);
102
103         error = copyin(uap->hostname, hostname, len);
104         if (error) {
105                 kfree(hostname, M_TEMP);
106                 return (error);
107         }
108
109         get_mplock();
110         error = kernel_sysctl(name, 2, NULL, 0, hostname, len, NULL);
111         rel_mplock();
112
113         kfree(hostname, M_TEMP);
114         return (error);
115 }
116
117 /*
118  * MPSAFE
119  */
120 int
121 sys_ogethostid(struct ogethostid_args *uap)
122 {
123         uap->sysmsg_lresult = hostid;
124         return (0);
125 }
126
127 /*
128  * MPSAFE
129  */
130 int
131 sys_osethostid(struct osethostid_args *uap)
132 {
133         struct thread *td = curthread;
134         int error;
135
136         error = priv_check(td, PRIV_ROOT);
137         if (error)
138                 return (error);
139         hostid = uap->hostid;
140         return (0);
141 }
142
143 /*
144  * MPSAFE
145  */
146 int
147 sys_oquota(struct oquota_args *uap)
148 {
149         return (ENOSYS);
150 }
151
152 #define KINFO_PROC              (0<<8)
153 #define KINFO_RT                (1<<8)
154 #define KINFO_VNODE             (2<<8)
155 #define KINFO_FILE              (3<<8)
156 #define KINFO_METER             (4<<8)
157 #define KINFO_LOADAVG           (5<<8)
158 #define KINFO_CLOCKRATE         (6<<8)
159
160 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
161 #define KINFO_BSDI_SYSINFO      (101<<8)
162
163 /*
164  * XXX this is bloat, but I hope it's better here than on the potentially
165  * limited kernel stack...  -Peter
166  */
167
168 static struct {
169         int     bsdi_machine;           /* "i386" on BSD/386 */
170 /*      ^^^ this is an offset to the string, relative to the struct start */
171         char    *pad0;
172         long    pad1;
173         long    pad2;
174         long    pad3;
175         u_long  pad4;
176         u_long  pad5;
177         u_long  pad6;
178
179         int     bsdi_ostype;            /* "BSD/386" on BSD/386 */
180         int     bsdi_osrelease;         /* "1.1" on BSD/386 */
181         long    pad7;
182         long    pad8;
183         char    *pad9;
184
185         long    pad10;
186         long    pad11;
187         int     pad12;
188         long    pad13;
189         quad_t  pad14;
190         long    pad15;
191
192         struct  timeval pad16;
193         /* we dont set this, because BSDI's uname used gethostname() instead */
194         int     bsdi_hostname;          /* hostname on BSD/386 */
195
196         /* the actual string data is appended here */
197
198 } bsdi_si;
199 /*
200  * this data is appended to the end of the bsdi_si structure during copyout.
201  * The "char *" offsets are relative to the base of the bsdi_si struct.
202  * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
203  * should not exceed the length of the buffer here... (or else!! :-)
204  */
205 static char bsdi_strings[80];   /* It had better be less than this! */
206
207 /*
208  * MPALMOSTSAFE
209  */
210 int
211 sys_ogetkerninfo(struct getkerninfo_args *uap)
212 {
213         int error, name[6];
214         size_t size;
215         u_int needed = 0;
216
217         get_mplock();
218
219         switch (uap->op & 0xff00) {
220         case KINFO_RT:
221                 name[0] = CTL_NET;
222                 name[1] = PF_ROUTE;
223                 name[2] = 0;
224                 name[3] = (uap->op & 0xff0000) >> 16;
225                 name[4] = uap->op & 0xff;
226                 name[5] = uap->arg;
227                 error = userland_sysctl(name, 6, uap->where, uap->size,
228                         0, 0, 0, &size);
229                 break;
230
231         case KINFO_VNODE:
232                 name[0] = CTL_KERN;
233                 name[1] = KERN_VNODE;
234                 error = userland_sysctl(name, 2, uap->where, uap->size,
235                         0, 0, 0, &size);
236                 break;
237
238         case KINFO_PROC:
239                 name[0] = CTL_KERN;
240                 name[1] = KERN_PROC;
241                 name[2] = uap->op & 0xff;
242                 name[3] = uap->arg;
243                 error = userland_sysctl(name, 4, uap->where, uap->size,
244                         0, 0, 0, &size);
245                 break;
246
247         case KINFO_FILE:
248                 name[0] = CTL_KERN;
249                 name[1] = KERN_FILE;
250                 error = userland_sysctl(name, 2, uap->where, uap->size,
251                         0, 0, 0, &size);
252                 break;
253
254         case KINFO_METER:
255                 name[0] = CTL_VM;
256                 name[1] = VM_METER;
257                 error = userland_sysctl(name, 2, uap->where, uap->size,
258                         0, 0, 0, &size);
259                 break;
260
261         case KINFO_LOADAVG:
262                 name[0] = CTL_VM;
263                 name[1] = VM_LOADAVG;
264                 error = userland_sysctl(name, 2, uap->where, uap->size,
265                         0, 0, 0, &size);
266                 break;
267
268         case KINFO_CLOCKRATE:
269                 name[0] = CTL_KERN;
270                 name[1] = KERN_CLOCKRATE;
271                 error = userland_sysctl(name, 2, uap->where, uap->size,
272                         0, 0, 0, &size);
273                 break;
274
275         case KINFO_BSDI_SYSINFO: {
276                 /*
277                  * this is pretty crude, but it's just enough for uname()
278                  * from BSDI's 1.x libc to work.
279                  * *size gives the size of the buffer before the call, and
280                  * the amount of data copied after a successful call.
281                  * If successful, the return value is the amount of data
282                  * available, which can be larger than *size.
283                  *
284                  * BSDI's 2.x product apparently fails with ENOMEM if
285                  * *size is too small.
286                  */
287
288                 u_int left;
289                 char *s;
290
291                 bzero((char *)&bsdi_si, sizeof(bsdi_si));
292                 bzero(bsdi_strings, sizeof(bsdi_strings));
293
294                 s = bsdi_strings;
295
296                 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
297                 strcpy(s, ostype);
298                 s += strlen(s) + 1;
299
300                 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
301                 strcpy(s, osrelease);
302                 s += strlen(s) + 1;
303
304                 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
305                 strcpy(s, machine);
306                 s += strlen(s) + 1;
307
308                 needed = sizeof(bsdi_si) + (s - bsdi_strings);
309
310                 if (uap->where == NULL || (uap->size == NULL)) {
311                         /* process is asking how much buffer to supply.. */
312                         size = needed;
313                         error = 0;
314                         break;
315                 }
316
317                 if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
318                                 break;
319
320                 /* if too much buffer supplied, trim it down */
321                 if (size > needed)
322                         size = needed;
323
324                 /* how much of the buffer is remaining */
325                 left = size;
326
327                 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
328                         break;
329
330                 /* is there any point in continuing? */
331                 if (left > sizeof(bsdi_si)) {
332                         left -= sizeof(bsdi_si);
333                         error = copyout(&bsdi_strings,
334                                         uap->where + sizeof(bsdi_si), left);
335                 }
336                 break;
337         }
338         default:
339                 error = EOPNOTSUPP;
340                 break;
341         }
342         rel_mplock();
343         if (error)
344                 return (error);
345         uap->sysmsg_iresult = (int)size;
346         if (uap->size)
347                 error = copyout(&size, uap->size, sizeof(size));
348         return (error);
349 }