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