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