freebsd32_misc.c revision 197049
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3100384Speter * All rights reserved.
4100384Speter *
5100384Speter * Redistribution and use in source and binary forms, with or without
6100384Speter * modification, are permitted provided that the following conditions
7100384Speter * are met:
8100384Speter * 1. Redistributions of source code must retain the above copyright
9100384Speter *    notice, this list of conditions and the following disclaimer.
10100384Speter * 2. Redistributions in binary form must reproduce the above copyright
11100384Speter *    notice, this list of conditions and the following disclaimer in the
12100384Speter *    documentation and/or other materials provided with the distribution.
13100384Speter *
14100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100384Speter * SUCH DAMAGE.
25100384Speter */
26100384Speter
27118031Sobrien#include <sys/cdefs.h>
28118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 197049 2009-09-09 20:59:01Z kib $");
29118031Sobrien
30104738Speter#include "opt_compat.h"
31191673Sjamie#include "opt_inet.h"
32191673Sjamie#include "opt_inet6.h"
33104738Speter
34100384Speter#include <sys/param.h>
35100384Speter#include <sys/bus.h>
36162954Sphk#include <sys/clock.h>
37100384Speter#include <sys/exec.h>
38100384Speter#include <sys/fcntl.h>
39100384Speter#include <sys/filedesc.h>
40100384Speter#include <sys/imgact.h>
41185435Sbz#include <sys/jail.h>
42100384Speter#include <sys/kernel.h>
43161343Sjkim#include <sys/limits.h>
44100384Speter#include <sys/lock.h>
45100384Speter#include <sys/malloc.h>
46100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
47151909Sps#include <sys/mbuf.h>
48100384Speter#include <sys/mman.h>
49100384Speter#include <sys/module.h>
50100384Speter#include <sys/mount.h>
51100384Speter#include <sys/mutex.h>
52183044Sobrien#include <sys/namei.h>
53100384Speter#include <sys/proc.h>
54100384Speter#include <sys/reboot.h>
55100384Speter#include <sys/resource.h>
56100384Speter#include <sys/resourcevar.h>
57100384Speter#include <sys/selinfo.h>
58146950Sps#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
59100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
60100384Speter#include <sys/signal.h>
61100384Speter#include <sys/signalvar.h>
62100384Speter#include <sys/socket.h>
63100384Speter#include <sys/socketvar.h>
64100384Speter#include <sys/stat.h>
65150883Sjhb#include <sys/syscall.h>
66113859Sjhb#include <sys/syscallsubr.h>
67100384Speter#include <sys/sysctl.h>
68100384Speter#include <sys/sysent.h>
69100384Speter#include <sys/sysproto.h>
70183044Sobrien#include <sys/systm.h>
71162551Sdavidxu#include <sys/thr.h>
72100384Speter#include <sys/unistd.h>
73162551Sdavidxu#include <sys/ucontext.h>
74100384Speter#include <sys/vnode.h>
75127140Sjhb#include <sys/wait.h>
76157285Sps#include <sys/ipc.h>
77174381Sjhb#include <sys/msg.h>
78174381Sjhb#include <sys/sem.h>
79157285Sps#include <sys/shm.h>
80100384Speter
81191673Sjamie#ifdef INET
82191673Sjamie#include <netinet/in.h>
83191673Sjamie#endif
84191673Sjamie
85100384Speter#include <vm/vm.h>
86100384Speter#include <vm/vm_kern.h>
87100384Speter#include <vm/vm_param.h>
88100384Speter#include <vm/pmap.h>
89100384Speter#include <vm/vm_map.h>
90100384Speter#include <vm/vm_object.h>
91100384Speter#include <vm/vm_extern.h>
92100384Speter
93151582Sps#include <machine/cpu.h>
94151582Sps
95183188Sobrien#include <security/audit/audit.h>
96183188Sobrien
97119333Speter#include <compat/freebsd32/freebsd32_util.h>
98119333Speter#include <compat/freebsd32/freebsd32.h>
99174380Sjhb#include <compat/freebsd32/freebsd32_ipc.h>
100163018Sdavidxu#include <compat/freebsd32/freebsd32_signal.h>
101119333Speter#include <compat/freebsd32/freebsd32_proto.h>
102100384Speter
103121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
104121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
105174377SjhbCTASSERT(sizeof(struct itimerval32) == 16);
106121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
107121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
108174377SjhbCTASSERT(sizeof(struct sigaltstack32) == 12);
109174377SjhbCTASSERT(sizeof(struct kevent32) == 20);
110174377SjhbCTASSERT(sizeof(struct iovec32) == 8);
111174377SjhbCTASSERT(sizeof(struct msghdr32) == 28);
112174377SjhbCTASSERT(sizeof(struct stat32) == 96);
113174377SjhbCTASSERT(sizeof(struct sigaction32) == 24);
114121719Speter
115174377Sjhbstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
116174377Sjhbstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
117174377Sjhb
118100384Speterint
119119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
120100384Speter{
121127140Sjhb	int error, status;
122127140Sjhb	struct rusage32 ru32;
123136152Sjhb	struct rusage ru, *rup;
124100384Speter
125136152Sjhb	if (uap->rusage != NULL)
126136152Sjhb		rup = &ru;
127136152Sjhb	else
128136152Sjhb		rup = NULL;
129136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
130100384Speter	if (error)
131100384Speter		return (error);
132127140Sjhb	if (uap->status != NULL)
133127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
134127140Sjhb	if (uap->rusage != NULL && error == 0) {
135100384Speter		TV_CP(ru, ru32, ru_utime);
136100384Speter		TV_CP(ru, ru32, ru_stime);
137100384Speter		CP(ru, ru32, ru_maxrss);
138100384Speter		CP(ru, ru32, ru_ixrss);
139100384Speter		CP(ru, ru32, ru_idrss);
140100384Speter		CP(ru, ru32, ru_isrss);
141100384Speter		CP(ru, ru32, ru_minflt);
142100384Speter		CP(ru, ru32, ru_majflt);
143100384Speter		CP(ru, ru32, ru_nswap);
144100384Speter		CP(ru, ru32, ru_inblock);
145100384Speter		CP(ru, ru32, ru_oublock);
146100384Speter		CP(ru, ru32, ru_msgsnd);
147100384Speter		CP(ru, ru32, ru_msgrcv);
148100384Speter		CP(ru, ru32, ru_nsignals);
149100384Speter		CP(ru, ru32, ru_nvcsw);
150100384Speter		CP(ru, ru32, ru_nivcsw);
151127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
152100384Speter	}
153100384Speter	return (error);
154100384Speter}
155100384Speter
156128597Smarcel#ifdef COMPAT_FREEBSD4
157174526Sjhbstatic void
158100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
159100384Speter{
160172003Sjhb
161174424Sscottl	statfs_scale_blocks(in, INT32_MAX);
162156266Sps	bzero(out, sizeof(*out));
163100384Speter	CP(*in, *out, f_bsize);
164172003Sjhb	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
165100384Speter	CP(*in, *out, f_blocks);
166100384Speter	CP(*in, *out, f_bfree);
167100384Speter	CP(*in, *out, f_bavail);
168172003Sjhb	out->f_files = MIN(in->f_files, INT32_MAX);
169174526Sjhb	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
170100384Speter	CP(*in, *out, f_fsid);
171100384Speter	CP(*in, *out, f_owner);
172100384Speter	CP(*in, *out, f_type);
173100384Speter	CP(*in, *out, f_flags);
174174526Sjhb	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
175174526Sjhb	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
176156266Sps	strlcpy(out->f_fstypename,
177156266Sps	      in->f_fstypename, MFSNAMELEN);
178156266Sps	strlcpy(out->f_mntonname,
179156266Sps	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
180174526Sjhb	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
181174526Sjhb	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
182156266Sps	strlcpy(out->f_mntfromname,
183156266Sps	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
184100384Speter}
185128597Smarcel#endif
186100384Speter
187128597Smarcel#ifdef COMPAT_FREEBSD4
188100384Speterint
189128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
190100384Speter{
191147178Spjd	struct statfs *buf, *sp;
192147178Spjd	struct statfs32 stat32;
193147178Spjd	size_t count, size;
194100384Speter	int error;
195100384Speter
196147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
197147178Spjd	size = count * sizeof(struct statfs);
198147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
199147302Spjd	if (size > 0) {
200100384Speter		count = td->td_retval[0];
201147178Spjd		sp = buf;
202147178Spjd		while (count > 0 && error == 0) {
203174526Sjhb			copy_statfs(sp, &stat32);
204147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
205147178Spjd			sp++;
206147178Spjd			uap->buf++;
207147178Spjd			count--;
208100384Speter		}
209147178Spjd		free(buf, M_TEMP);
210100384Speter	}
211100384Speter	return (error);
212100384Speter}
213128597Smarcel#endif
214100384Speter
215100384Speterint
216119333Speterfreebsd32_sigaltstack(struct thread *td,
217119333Speter		      struct freebsd32_sigaltstack_args *uap)
218100384Speter{
219113859Sjhb	struct sigaltstack32 s32;
220113859Sjhb	struct sigaltstack ss, oss, *ssp;
221100384Speter	int error;
222100384Speter
223113859Sjhb	if (uap->ss != NULL) {
224113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
225100384Speter		if (error)
226100384Speter			return (error);
227113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
228113859Sjhb		CP(s32, ss, ss_size);
229113859Sjhb		CP(s32, ss, ss_flags);
230113859Sjhb		ssp = &ss;
231113859Sjhb	} else
232113859Sjhb		ssp = NULL;
233113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
234113859Sjhb	if (error == 0 && uap->oss != NULL) {
235113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
236113859Sjhb		CP(oss, s32, ss_size);
237113859Sjhb		CP(oss, s32, ss_flags);
238113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
239100384Speter	}
240100384Speter	return (error);
241100384Speter}
242100384Speter
243142059Sjhb/*
244142059Sjhb * Custom version of exec_copyin_args() so that we can translate
245142059Sjhb * the pointers.
246142059Sjhb */
247142059Sjhbstatic int
248142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
249142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
250100384Speter{
251142059Sjhb	char *argp, *envp;
252142059Sjhb	u_int32_t *p32, arg;
253142059Sjhb	size_t length;
254100384Speter	int error;
255100384Speter
256142059Sjhb	bzero(args, sizeof(*args));
257142059Sjhb	if (argv == NULL)
258142059Sjhb		return (EFAULT);
259100384Speter
260142059Sjhb	/*
261142059Sjhb	 * Allocate temporary demand zeroed space for argument and
262142059Sjhb	 *	environment strings
263142059Sjhb	 */
264147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
265147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
266142059Sjhb	if (args->buf == NULL)
267142059Sjhb		return (ENOMEM);
268142059Sjhb	args->begin_argv = args->buf;
269142059Sjhb	args->endp = args->begin_argv;
270142059Sjhb	args->stringspace = ARG_MAX;
271142059Sjhb
272142059Sjhb	/*
273142059Sjhb	 * Copy the file name.
274142059Sjhb	 */
275177789Skib	if (fname != NULL) {
276177789Skib		args->fname = args->buf + ARG_MAX;
277177789Skib		error = (segflg == UIO_SYSSPACE) ?
278177789Skib		    copystr(fname, args->fname, PATH_MAX, &length) :
279177789Skib		    copyinstr(fname, args->fname, PATH_MAX, &length);
280177789Skib		if (error != 0)
281177789Skib			goto err_exit;
282177789Skib	} else
283177789Skib		args->fname = NULL;
284142059Sjhb
285142059Sjhb	/*
286142059Sjhb	 * extract arguments first
287142059Sjhb	 */
288142059Sjhb	p32 = argv;
289142059Sjhb	for (;;) {
290142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
291142059Sjhb		if (error)
292156440Sups			goto err_exit;
293142059Sjhb		if (arg == 0)
294142059Sjhb			break;
295142059Sjhb		argp = PTRIN(arg);
296142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
297142059Sjhb		if (error) {
298142059Sjhb			if (error == ENAMETOOLONG)
299156440Sups				error = E2BIG;
300156440Sups			goto err_exit;
301142059Sjhb		}
302142059Sjhb		args->stringspace -= length;
303142059Sjhb		args->endp += length;
304142059Sjhb		args->argc++;
305100384Speter	}
306142059Sjhb
307142059Sjhb	args->begin_envv = args->endp;
308142059Sjhb
309142059Sjhb	/*
310142059Sjhb	 * extract environment strings
311142059Sjhb	 */
312142059Sjhb	if (envv) {
313142059Sjhb		p32 = envv;
314142059Sjhb		for (;;) {
315100384Speter			error = copyin(p32++, &arg, sizeof(arg));
316100384Speter			if (error)
317156440Sups				goto err_exit;
318142059Sjhb			if (arg == 0)
319142059Sjhb				break;
320142059Sjhb			envp = PTRIN(arg);
321142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
322142059Sjhb			    &length);
323142059Sjhb			if (error) {
324142059Sjhb				if (error == ENAMETOOLONG)
325156440Sups					error = E2BIG;
326156440Sups				goto err_exit;
327142059Sjhb			}
328142059Sjhb			args->stringspace -= length;
329142059Sjhb			args->endp += length;
330142059Sjhb			args->envc++;
331142059Sjhb		}
332100384Speter	}
333100384Speter
334142059Sjhb	return (0);
335156440Sups
336156440Supserr_exit:
337156440Sups	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
338156440Sups	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
339156440Sups	args->buf = NULL;
340156440Sups	return (error);
341100384Speter}
342100384Speter
343142059Sjhbint
344142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
345142059Sjhb{
346142059Sjhb	struct image_args eargs;
347142059Sjhb	int error;
348142059Sjhb
349142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
350142059Sjhb	    uap->argv, uap->envv);
351142059Sjhb	if (error == 0)
352142059Sjhb		error = kern_execve(td, &eargs, NULL);
353142059Sjhb	return (error);
354142059Sjhb}
355142059Sjhb
356177789Skibint
357177789Skibfreebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
358177789Skib{
359177789Skib	struct image_args eargs;
360177789Skib	int error;
361177789Skib
362177789Skib	error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
363177789Skib	    uap->argv, uap->envv);
364177789Skib	if (error == 0) {
365177789Skib		eargs.fd = uap->fd;
366177789Skib		error = kern_execve(td, &eargs, NULL);
367177789Skib	}
368177789Skib	return (error);
369177789Skib}
370177789Skib
371114987Speter#ifdef __ia64__
372100384Speterstatic int
373119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
374119333Speter		       int prot, int fd, off_t pos)
375100384Speter{
376100384Speter	vm_map_t map;
377100384Speter	vm_map_entry_t entry;
378100384Speter	int rv;
379100384Speter
380100384Speter	map = &td->td_proc->p_vmspace->vm_map;
381100384Speter	if (fd != -1)
382100384Speter		prot |= VM_PROT_WRITE;
383100384Speter
384100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
385100384Speter		if ((entry->protection & prot) != prot) {
386100384Speter			rv = vm_map_protect(map,
387100384Speter					    trunc_page(start),
388100384Speter					    round_page(end),
389100384Speter					    entry->protection | prot,
390100384Speter					    FALSE);
391100384Speter			if (rv != KERN_SUCCESS)
392100384Speter				return (EINVAL);
393100384Speter		}
394100384Speter	} else {
395100384Speter		vm_offset_t addr = trunc_page(start);
396100384Speter		rv = vm_map_find(map, 0, 0,
397100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
398100384Speter				 VM_PROT_ALL, 0);
399100384Speter		if (rv != KERN_SUCCESS)
400100384Speter			return (EINVAL);
401100384Speter	}
402100384Speter
403100384Speter	if (fd != -1) {
404100384Speter		struct pread_args r;
405107849Salfred		r.fd = fd;
406107849Salfred		r.buf = (void *) start;
407107849Salfred		r.nbyte = end - start;
408107849Salfred		r.offset = pos;
409100384Speter		return (pread(td, &r));
410100384Speter	} else {
411100384Speter		while (start < end) {
412100384Speter			subyte((void *) start, 0);
413100384Speter			start++;
414100384Speter		}
415100384Speter		return (0);
416100384Speter	}
417100384Speter}
418114987Speter#endif
419100384Speter
420100384Speterint
421119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
422100384Speter{
423100384Speter	struct mmap_args ap;
424107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
425107849Salfred	vm_size_t len	 = uap->len;
426107849Salfred	int prot	 = uap->prot;
427107849Salfred	int flags	 = uap->flags;
428107849Salfred	int fd		 = uap->fd;
429107849Salfred	off_t pos	 = (uap->poslo
430107849Salfred			    | ((off_t)uap->poshi << 32));
431114987Speter#ifdef __ia64__
432100384Speter	vm_size_t pageoff;
433100384Speter	int error;
434100384Speter
435100384Speter	/*
436100384Speter	 * Attempt to handle page size hassles.
437100384Speter	 */
438100384Speter	pageoff = (pos & PAGE_MASK);
439100384Speter	if (flags & MAP_FIXED) {
440100384Speter		vm_offset_t start, end;
441100384Speter		start = addr;
442100384Speter		end = addr + len;
443100384Speter
444100384Speter		if (start != trunc_page(start)) {
445119333Speter			error = freebsd32_mmap_partial(td, start,
446119333Speter						       round_page(start), prot,
447119333Speter						       fd, pos);
448100384Speter			if (fd != -1)
449100384Speter				pos += round_page(start) - start;
450100384Speter			start = round_page(start);
451100384Speter		}
452100384Speter		if (end != round_page(end)) {
453100384Speter			vm_offset_t t = trunc_page(end);
454119333Speter			error = freebsd32_mmap_partial(td, t, end,
455100384Speter						  prot, fd,
456100384Speter						  pos + t - start);
457100384Speter			end = trunc_page(end);
458100384Speter		}
459100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
460100384Speter			/*
461100384Speter			 * We can't map this region at all. The specified
462100384Speter			 * address doesn't have the same alignment as the file
463100384Speter			 * position. Fake the mapping by simply reading the
464100384Speter			 * entire region into memory. First we need to make
465100384Speter			 * sure the region exists.
466100384Speter			 */
467100384Speter			vm_map_t map;
468100384Speter			struct pread_args r;
469100384Speter			int rv;
470100384Speter
471100384Speter			prot |= VM_PROT_WRITE;
472100384Speter			map = &td->td_proc->p_vmspace->vm_map;
473100384Speter			rv = vm_map_remove(map, start, end);
474169181Salc			if (rv != KERN_SUCCESS)
475100384Speter				return (EINVAL);
476100384Speter			rv = vm_map_find(map, 0, 0,
477100384Speter					 &start, end - start, FALSE,
478100384Speter					 prot, VM_PROT_ALL, 0);
479100384Speter			if (rv != KERN_SUCCESS)
480100384Speter				return (EINVAL);
481107849Salfred			r.fd = fd;
482107849Salfred			r.buf = (void *) start;
483107849Salfred			r.nbyte = end - start;
484107849Salfred			r.offset = pos;
485100384Speter			error = pread(td, &r);
486100384Speter			if (error)
487100384Speter				return (error);
488100384Speter
489100384Speter			td->td_retval[0] = addr;
490100384Speter			return (0);
491100384Speter		}
492100384Speter		if (end == start) {
493100384Speter			/*
494100384Speter			 * After dealing with the ragged ends, there
495100384Speter			 * might be none left.
496100384Speter			 */
497100384Speter			td->td_retval[0] = addr;
498100384Speter			return (0);
499100384Speter		}
500100384Speter		addr = start;
501100384Speter		len = end - start;
502100384Speter	}
503114987Speter#endif
504100384Speter
505107849Salfred	ap.addr = (void *) addr;
506107849Salfred	ap.len = len;
507107849Salfred	ap.prot = prot;
508107849Salfred	ap.flags = flags;
509107849Salfred	ap.fd = fd;
510107849Salfred	ap.pos = pos;
511100384Speter
512100384Speter	return (mmap(td, &ap));
513100384Speter}
514100384Speter
515171215Speter#ifdef COMPAT_FREEBSD6
516171215Speterint
517171215Speterfreebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
518171215Speter{
519171215Speter	struct freebsd32_mmap_args ap;
520171215Speter
521171215Speter	ap.addr = uap->addr;
522171215Speter	ap.len = uap->len;
523171215Speter	ap.prot = uap->prot;
524171215Speter	ap.flags = uap->flags;
525171215Speter	ap.fd = uap->fd;
526171215Speter	ap.poslo = uap->poslo;
527171215Speter	ap.poshi = uap->poshi;
528171215Speter
529171215Speter	return (freebsd32_mmap(td, &ap));
530171215Speter}
531171215Speter#endif
532171215Speter
533100384Speterint
534119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
535100384Speter{
536142059Sjhb	struct itimerval itv, oitv, *itvp;
537142059Sjhb	struct itimerval32 i32;
538100384Speter	int error;
539100384Speter
540142059Sjhb	if (uap->itv != NULL) {
541142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
542100384Speter		if (error)
543100384Speter			return (error);
544142059Sjhb		TV_CP(i32, itv, it_interval);
545142059Sjhb		TV_CP(i32, itv, it_value);
546142059Sjhb		itvp = &itv;
547142059Sjhb	} else
548142059Sjhb		itvp = NULL;
549142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
550142059Sjhb	if (error || uap->oitv == NULL)
551100384Speter		return (error);
552142059Sjhb	TV_CP(oitv, i32, it_interval);
553142059Sjhb	TV_CP(oitv, i32, it_value);
554142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
555100384Speter}
556100384Speter
557100384Speterint
558125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
559125171Speter{
560142059Sjhb	struct itimerval itv;
561142059Sjhb	struct itimerval32 i32;
562125171Speter	int error;
563125171Speter
564142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
565142059Sjhb	if (error || uap->itv == NULL)
566125171Speter		return (error);
567142059Sjhb	TV_CP(itv, i32, it_interval);
568142059Sjhb	TV_CP(itv, i32, it_value);
569142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
570125171Speter}
571125171Speter
572125171Speterint
573119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
574100384Speter{
575142059Sjhb	struct timeval32 tv32;
576142059Sjhb	struct timeval tv, *tvp;
577100384Speter	int error;
578100384Speter
579142059Sjhb	if (uap->tv != NULL) {
580142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
581100384Speter		if (error)
582100384Speter			return (error);
583142059Sjhb		CP(tv32, tv, tv_sec);
584142059Sjhb		CP(tv32, tv, tv_usec);
585142059Sjhb		tvp = &tv;
586142059Sjhb	} else
587142059Sjhb		tvp = NULL;
588100384Speter	/*
589100384Speter	 * XXX big-endian needs to convert the fd_sets too.
590142059Sjhb	 * XXX Do pointers need PTRIN()?
591100384Speter	 */
592197049Skib	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
593197049Skib	    sizeof(int32_t) * 8));
594100384Speter}
595100384Speter
596146950Sps/*
597146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
598146950Sps */
599146950Spsstatic int
600146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
601146950Sps{
602146950Sps	struct freebsd32_kevent_args *uap;
603146950Sps	struct kevent32	ks32[KQ_NEVENTS];
604146950Sps	int i, error = 0;
605146950Sps
606146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
607146950Sps	uap = (struct freebsd32_kevent_args *)arg;
608146950Sps
609146950Sps	for (i = 0; i < count; i++) {
610146950Sps		CP(kevp[i], ks32[i], ident);
611146950Sps		CP(kevp[i], ks32[i], filter);
612146950Sps		CP(kevp[i], ks32[i], flags);
613146950Sps		CP(kevp[i], ks32[i], fflags);
614146950Sps		CP(kevp[i], ks32[i], data);
615146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
616146950Sps	}
617146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
618146950Sps	if (error == 0)
619146950Sps		uap->eventlist += count;
620146950Sps	return (error);
621146950Sps}
622146950Sps
623146950Sps/*
624146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
625146950Sps */
626146950Spsstatic int
627146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
628146950Sps{
629146950Sps	struct freebsd32_kevent_args *uap;
630146950Sps	struct kevent32	ks32[KQ_NEVENTS];
631146950Sps	int i, error = 0;
632146950Sps
633146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
634146950Sps	uap = (struct freebsd32_kevent_args *)arg;
635146950Sps
636146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
637146950Sps	if (error)
638146950Sps		goto done;
639146950Sps	uap->changelist += count;
640146950Sps
641146950Sps	for (i = 0; i < count; i++) {
642146950Sps		CP(ks32[i], kevp[i], ident);
643146950Sps		CP(ks32[i], kevp[i], filter);
644146950Sps		CP(ks32[i], kevp[i], flags);
645146950Sps		CP(ks32[i], kevp[i], fflags);
646146950Sps		CP(ks32[i], kevp[i], data);
647146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
648146950Sps	}
649146950Spsdone:
650146950Sps	return (error);
651146950Sps}
652146950Sps
653100384Speterint
654119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
655114987Speter{
656114987Speter	struct timespec32 ts32;
657142934Sps	struct timespec ts, *tsp;
658146950Sps	struct kevent_copyops k_ops = { uap,
659146950Sps					freebsd32_kevent_copyout,
660146950Sps					freebsd32_kevent_copyin};
661146950Sps	int error;
662114987Speter
663114987Speter
664114987Speter	if (uap->timeout) {
665114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
666114987Speter		if (error)
667114987Speter			return (error);
668114987Speter		CP(ts32, ts, tv_sec);
669114987Speter		CP(ts32, ts, tv_nsec);
670142934Sps		tsp = &ts;
671142934Sps	} else
672142934Sps		tsp = NULL;
673146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
674146950Sps	    &k_ops, tsp);
675142934Sps	return (error);
676114987Speter}
677114987Speter
678114987Speterint
679119333Speterfreebsd32_gettimeofday(struct thread *td,
680119333Speter		       struct freebsd32_gettimeofday_args *uap)
681100384Speter{
682123425Speter	struct timeval atv;
683123425Speter	struct timeval32 atv32;
684123425Speter	struct timezone rtz;
685123425Speter	int error = 0;
686100384Speter
687123425Speter	if (uap->tp) {
688123425Speter		microtime(&atv);
689123425Speter		CP(atv, atv32, tv_sec);
690123425Speter		CP(atv, atv32, tv_usec);
691123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
692100384Speter	}
693123425Speter	if (error == 0 && uap->tzp != NULL) {
694123425Speter		rtz.tz_minuteswest = tz_minuteswest;
695123425Speter		rtz.tz_dsttime = tz_dsttime;
696123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
697100384Speter	}
698100384Speter	return (error);
699100384Speter}
700100384Speter
701100384Speterint
702119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
703100384Speter{
704136152Sjhb	struct rusage32 s32;
705136152Sjhb	struct rusage s;
706100384Speter	int error;
707100384Speter
708136152Sjhb	error = kern_getrusage(td, uap->who, &s);
709100384Speter	if (error)
710100384Speter		return (error);
711136152Sjhb	if (uap->rusage != NULL) {
712100384Speter		TV_CP(s, s32, ru_utime);
713100384Speter		TV_CP(s, s32, ru_stime);
714100384Speter		CP(s, s32, ru_maxrss);
715100384Speter		CP(s, s32, ru_ixrss);
716100384Speter		CP(s, s32, ru_idrss);
717100384Speter		CP(s, s32, ru_isrss);
718100384Speter		CP(s, s32, ru_minflt);
719100384Speter		CP(s, s32, ru_majflt);
720100384Speter		CP(s, s32, ru_nswap);
721100384Speter		CP(s, s32, ru_inblock);
722100384Speter		CP(s, s32, ru_oublock);
723100384Speter		CP(s, s32, ru_msgsnd);
724100384Speter		CP(s, s32, ru_msgrcv);
725100384Speter		CP(s, s32, ru_nsignals);
726100384Speter		CP(s, s32, ru_nvcsw);
727100384Speter		CP(s, s32, ru_nivcsw);
728136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
729100384Speter	}
730100384Speter	return (error);
731100384Speter}
732100384Speter
733144450Sjhbstatic int
734144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
735100384Speter{
736144450Sjhb	struct iovec32 iov32;
737144450Sjhb	struct iovec *iov;
738144450Sjhb	struct uio *uio;
739144450Sjhb	u_int iovlen;
740144450Sjhb	int error, i;
741100384Speter
742144450Sjhb	*uiop = NULL;
743144450Sjhb	if (iovcnt > UIO_MAXIOV)
744100384Speter		return (EINVAL);
745144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
746144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
747144450Sjhb	iov = (struct iovec *)(uio + 1);
748144450Sjhb	for (i = 0; i < iovcnt; i++) {
749144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
750144450Sjhb		if (error) {
751144450Sjhb			free(uio, M_IOV);
752144450Sjhb			return (error);
753144450Sjhb		}
754144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
755144450Sjhb		iov[i].iov_len = iov32.iov_len;
756100384Speter	}
757144450Sjhb	uio->uio_iov = iov;
758144450Sjhb	uio->uio_iovcnt = iovcnt;
759144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
760144450Sjhb	uio->uio_offset = -1;
761144450Sjhb	uio->uio_resid = 0;
762144450Sjhb	for (i = 0; i < iovcnt; i++) {
763144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
764144450Sjhb			free(uio, M_IOV);
765144450Sjhb			return (EINVAL);
766144450Sjhb		}
767144450Sjhb		uio->uio_resid += iov->iov_len;
768144450Sjhb		iov++;
769144450Sjhb	}
770144450Sjhb	*uiop = uio;
771144450Sjhb	return (0);
772144450Sjhb}
773100384Speter
774144450Sjhbint
775144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
776144450Sjhb{
777144450Sjhb	struct uio *auio;
778144450Sjhb	int error;
779100384Speter
780144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
781144450Sjhb	if (error)
782144450Sjhb		return (error);
783144450Sjhb	error = kern_readv(td, uap->fd, auio);
784144450Sjhb	free(auio, M_IOV);
785100384Speter	return (error);
786100384Speter}
787100384Speter
788100384Speterint
789119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
790100384Speter{
791144450Sjhb	struct uio *auio;
792144450Sjhb	int error;
793100384Speter
794144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
795144450Sjhb	if (error)
796144450Sjhb		return (error);
797144450Sjhb	error = kern_writev(td, uap->fd, auio);
798144450Sjhb	free(auio, M_IOV);
799100384Speter	return (error);
800100384Speter}
801100384Speter
802100384Speterint
803147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
804147813Sjhb{
805147813Sjhb	struct uio *auio;
806147813Sjhb	int error;
807147813Sjhb
808147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
809147813Sjhb	if (error)
810147813Sjhb		return (error);
811147813Sjhb	error = kern_preadv(td, uap->fd, auio, uap->offset);
812147813Sjhb	free(auio, M_IOV);
813147813Sjhb	return (error);
814147813Sjhb}
815147813Sjhb
816147813Sjhbint
817147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
818147813Sjhb{
819147813Sjhb	struct uio *auio;
820147813Sjhb	int error;
821147813Sjhb
822147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
823147813Sjhb	if (error)
824147813Sjhb		return (error);
825147813Sjhb	error = kern_pwritev(td, uap->fd, auio, uap->offset);
826147813Sjhb	free(auio, M_IOV);
827147813Sjhb	return (error);
828147813Sjhb}
829147813Sjhb
830151359Spsstatic int
831151909Spsfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
832151359Sps    int error)
833151359Sps{
834151359Sps	struct iovec32 iov32;
835151909Sps	struct iovec *iov;
836151909Sps	u_int iovlen;
837151359Sps	int i;
838151359Sps
839151909Sps	*iovp = NULL;
840151359Sps	if (iovcnt > UIO_MAXIOV)
841151359Sps		return (error);
842151359Sps	iovlen = iovcnt * sizeof(struct iovec);
843151909Sps	iov = malloc(iovlen, M_IOV, M_WAITOK);
844151359Sps	for (i = 0; i < iovcnt; i++) {
845151909Sps		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
846151359Sps		if (error) {
847151909Sps			free(iov, M_IOV);
848151359Sps			return (error);
849151359Sps		}
850151909Sps		iov[i].iov_base = PTRIN(iov32.iov_base);
851151909Sps		iov[i].iov_len = iov32.iov_len;
852151359Sps	}
853151909Sps	*iovp = iov;
854151359Sps	return (0);
855151359Sps}
856151359Sps
857151359Spsstatic int
858151359Spsfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
859151359Sps{
860151359Sps	struct msghdr32 m32;
861151359Sps	int error;
862151359Sps
863151359Sps	error = copyin(msg32, &m32, sizeof(m32));
864151359Sps	if (error)
865151359Sps		return (error);
866151359Sps	msg->msg_name = PTRIN(m32.msg_name);
867151359Sps	msg->msg_namelen = m32.msg_namelen;
868151359Sps	msg->msg_iov = PTRIN(m32.msg_iov);
869151359Sps	msg->msg_iovlen = m32.msg_iovlen;
870151359Sps	msg->msg_control = PTRIN(m32.msg_control);
871151359Sps	msg->msg_controllen = m32.msg_controllen;
872151359Sps	msg->msg_flags = m32.msg_flags;
873151909Sps	return (0);
874151359Sps}
875151359Sps
876151359Spsstatic int
877151359Spsfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
878151359Sps{
879151359Sps	struct msghdr32 m32;
880151359Sps	int error;
881151359Sps
882151359Sps	m32.msg_name = PTROUT(msg->msg_name);
883151359Sps	m32.msg_namelen = msg->msg_namelen;
884151359Sps	m32.msg_iov = PTROUT(msg->msg_iov);
885151359Sps	m32.msg_iovlen = msg->msg_iovlen;
886151359Sps	m32.msg_control = PTROUT(msg->msg_control);
887151359Sps	m32.msg_controllen = msg->msg_controllen;
888151359Sps	m32.msg_flags = msg->msg_flags;
889151359Sps	error = copyout(&m32, msg32, sizeof(m32));
890151359Sps	return (error);
891151359Sps}
892151359Sps
893151909Sps#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
894151909Sps#define FREEBSD32_ALIGN(p)	\
895151909Sps	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
896151909Sps#define	FREEBSD32_CMSG_SPACE(l)	\
897151909Sps	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
898151909Sps
899151909Sps#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
900151909Sps				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
901151909Spsstatic int
902151909Spsfreebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
903151909Sps{
904151909Sps	struct cmsghdr *cm;
905151909Sps	void *data;
906151909Sps	socklen_t clen, datalen;
907151909Sps	int error;
908151909Sps	caddr_t ctlbuf;
909151909Sps	int len, maxlen, copylen;
910151909Sps	struct mbuf *m;
911151909Sps	error = 0;
912151909Sps
913151909Sps	len    = msg->msg_controllen;
914151909Sps	maxlen = msg->msg_controllen;
915151909Sps	msg->msg_controllen = 0;
916151909Sps
917151909Sps	m = control;
918151909Sps	ctlbuf = msg->msg_control;
919151909Sps
920151909Sps	while (m && len > 0) {
921151909Sps		cm = mtod(m, struct cmsghdr *);
922151909Sps		clen = m->m_len;
923151909Sps
924151909Sps		while (cm != NULL) {
925151909Sps
926151909Sps			if (sizeof(struct cmsghdr) > clen ||
927151909Sps			    cm->cmsg_len > clen) {
928151909Sps				error = EINVAL;
929151909Sps				break;
930151909Sps			}
931151909Sps
932151909Sps			data   = CMSG_DATA(cm);
933151909Sps			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
934151909Sps
935151909Sps			/* Adjust message length */
936151909Sps			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
937151909Sps			    datalen;
938151909Sps
939151909Sps
940151909Sps			/* Copy cmsghdr */
941151909Sps			copylen = sizeof(struct cmsghdr);
942151909Sps			if (len < copylen) {
943151909Sps				msg->msg_flags |= MSG_CTRUNC;
944151909Sps				copylen = len;
945151909Sps			}
946151909Sps
947151909Sps			error = copyout(cm,ctlbuf,copylen);
948151909Sps			if (error)
949151909Sps				goto exit;
950151909Sps
951151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
952151909Sps			len    -= FREEBSD32_ALIGN(copylen);
953151909Sps
954151909Sps			if (len <= 0)
955151909Sps				break;
956151909Sps
957151909Sps			/* Copy data */
958151909Sps			copylen = datalen;
959151909Sps			if (len < copylen) {
960151909Sps				msg->msg_flags |= MSG_CTRUNC;
961151909Sps				copylen = len;
962151909Sps			}
963151909Sps
964151909Sps			error = copyout(data,ctlbuf,copylen);
965151909Sps			if (error)
966151909Sps				goto exit;
967151909Sps
968151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
969151909Sps			len    -= FREEBSD32_ALIGN(copylen);
970151909Sps
971151909Sps			if (CMSG_SPACE(datalen) < clen) {
972151909Sps				clen -= CMSG_SPACE(datalen);
973151909Sps				cm = (struct cmsghdr *)
974151909Sps					((caddr_t)cm + CMSG_SPACE(datalen));
975151909Sps			} else {
976151909Sps				clen = 0;
977151909Sps				cm = NULL;
978151909Sps			}
979151909Sps		}
980151909Sps		m = m->m_next;
981151909Sps	}
982151909Sps
983151909Sps	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
984151909Sps
985151909Spsexit:
986151909Sps	return (error);
987151909Sps
988151909Sps}
989151909Sps
990147813Sjhbint
991151359Spsfreebsd32_recvmsg(td, uap)
992151359Sps	struct thread *td;
993151359Sps	struct freebsd32_recvmsg_args /* {
994151359Sps		int	s;
995151359Sps		struct	msghdr32 *msg;
996151359Sps		int	flags;
997151359Sps	} */ *uap;
998151359Sps{
999151359Sps	struct msghdr msg;
1000151359Sps	struct msghdr32 m32;
1001151359Sps	struct iovec *uiov, *iov;
1002151909Sps	struct mbuf *control = NULL;
1003151909Sps	struct mbuf **controlp;
1004151909Sps
1005151359Sps	int error;
1006151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1007151359Sps	if (error)
1008151359Sps		return (error);
1009151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1010151359Sps	if (error)
1011151359Sps		return (error);
1012160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1013160246Sjhb	    EMSGSIZE);
1014151359Sps	if (error)
1015151359Sps		return (error);
1016151359Sps	msg.msg_flags = uap->flags;
1017151359Sps	uiov = msg.msg_iov;
1018151359Sps	msg.msg_iov = iov;
1019151909Sps
1020151909Sps	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1021160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1022151359Sps	if (error == 0) {
1023151359Sps		msg.msg_iov = uiov;
1024151909Sps
1025151909Sps		if (control != NULL)
1026151909Sps			error = freebsd32_copy_msg_out(&msg, control);
1027151909Sps
1028151909Sps		if (error == 0)
1029151909Sps			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1030151359Sps	}
1031151359Sps	free(iov, M_IOV);
1032151909Sps
1033151909Sps	if (control != NULL)
1034151909Sps		m_freem(control);
1035151909Sps
1036151359Sps	return (error);
1037151359Sps}
1038151359Sps
1039151909Sps
1040151909Spsstatic int
1041151909Spsfreebsd32_convert_msg_in(struct mbuf **controlp)
1042151909Sps{
1043151909Sps	struct mbuf *control = *controlp;
1044151909Sps	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1045151909Sps	void *data;
1046151909Sps	socklen_t clen = control->m_len, datalen;
1047151909Sps	int error;
1048151909Sps
1049151909Sps	error = 0;
1050151909Sps	*controlp = NULL;
1051151909Sps
1052151909Sps	while (cm != NULL) {
1053151909Sps		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1054151909Sps			error = EINVAL;
1055151909Sps			break;
1056151909Sps		}
1057151909Sps
1058151909Sps		data = FREEBSD32_CMSG_DATA(cm);
1059151909Sps		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1060151909Sps
1061151909Sps		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1062151909Sps		    cm->cmsg_level);
1063151909Sps		controlp = &(*controlp)->m_next;
1064151909Sps
1065151909Sps		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1066151909Sps			clen -= FREEBSD32_CMSG_SPACE(datalen);
1067151909Sps			cm = (struct cmsghdr *)
1068151909Sps				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1069151909Sps		} else {
1070151909Sps			clen = 0;
1071151909Sps			cm = NULL;
1072151909Sps		}
1073151909Sps	}
1074151909Sps
1075151909Sps	m_freem(control);
1076151909Sps	return (error);
1077151909Sps}
1078151909Sps
1079151909Sps
1080151359Spsint
1081151359Spsfreebsd32_sendmsg(struct thread *td,
1082151359Sps		  struct freebsd32_sendmsg_args *uap)
1083151359Sps{
1084151359Sps	struct msghdr msg;
1085151359Sps	struct msghdr32 m32;
1086151359Sps	struct iovec *iov;
1087151909Sps	struct mbuf *control = NULL;
1088151909Sps	struct sockaddr *to = NULL;
1089151359Sps	int error;
1090151359Sps
1091151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1092151359Sps	if (error)
1093151359Sps		return (error);
1094151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1095151359Sps	if (error)
1096151359Sps		return (error);
1097160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1098160246Sjhb	    EMSGSIZE);
1099151359Sps	if (error)
1100151359Sps		return (error);
1101151359Sps	msg.msg_iov = iov;
1102151909Sps	if (msg.msg_name != NULL) {
1103151909Sps		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1104151909Sps		if (error) {
1105151909Sps			to = NULL;
1106151909Sps			goto out;
1107151909Sps		}
1108151909Sps		msg.msg_name = to;
1109151909Sps	}
1110151909Sps
1111151909Sps	if (msg.msg_control) {
1112151909Sps		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1113151909Sps			error = EINVAL;
1114151909Sps			goto out;
1115151909Sps		}
1116151909Sps
1117151909Sps		error = sockargs(&control, msg.msg_control,
1118151909Sps		    msg.msg_controllen, MT_CONTROL);
1119151909Sps		if (error)
1120151909Sps			goto out;
1121151909Sps
1122151909Sps		error = freebsd32_convert_msg_in(&control);
1123151909Sps		if (error)
1124151909Sps			goto out;
1125151909Sps	}
1126151909Sps
1127151909Sps	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1128151909Sps	    UIO_USERSPACE);
1129151909Sps
1130151909Spsout:
1131151359Sps	free(iov, M_IOV);
1132151909Sps	if (to)
1133151909Sps		free(to, M_SONAME);
1134151359Sps	return (error);
1135151359Sps}
1136151359Sps
1137151359Spsint
1138151359Spsfreebsd32_recvfrom(struct thread *td,
1139151359Sps		   struct freebsd32_recvfrom_args *uap)
1140151359Sps{
1141151359Sps	struct msghdr msg;
1142151359Sps	struct iovec aiov;
1143151359Sps	int error;
1144151359Sps
1145151359Sps	if (uap->fromlenaddr) {
1146160246Sjhb		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1147160246Sjhb		    sizeof(msg.msg_namelen));
1148151359Sps		if (error)
1149151359Sps			return (error);
1150151359Sps	} else {
1151151359Sps		msg.msg_namelen = 0;
1152151359Sps	}
1153151359Sps
1154160246Sjhb	msg.msg_name = PTRIN(uap->from);
1155151359Sps	msg.msg_iov = &aiov;
1156151359Sps	msg.msg_iovlen = 1;
1157160246Sjhb	aiov.iov_base = PTRIN(uap->buf);
1158151359Sps	aiov.iov_len = uap->len;
1159160246Sjhb	msg.msg_control = NULL;
1160151359Sps	msg.msg_flags = uap->flags;
1161160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1162160249Sjhb	if (error == 0 && uap->fromlenaddr)
1163160249Sjhb		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1164160249Sjhb		    sizeof (msg.msg_namelen));
1165151359Sps	return (error);
1166151359Sps}
1167151359Sps
1168151359Spsint
1169119333Speterfreebsd32_settimeofday(struct thread *td,
1170119333Speter		       struct freebsd32_settimeofday_args *uap)
1171100384Speter{
1172144450Sjhb	struct timeval32 tv32;
1173144450Sjhb	struct timeval tv, *tvp;
1174144450Sjhb	struct timezone tz, *tzp;
1175100384Speter	int error;
1176100384Speter
1177144450Sjhb	if (uap->tv) {
1178144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
1179100384Speter		if (error)
1180100384Speter			return (error);
1181144450Sjhb		CP(tv32, tv, tv_sec);
1182144450Sjhb		CP(tv32, tv, tv_usec);
1183144450Sjhb		tvp = &tv;
1184144450Sjhb	} else
1185144450Sjhb		tvp = NULL;
1186144450Sjhb	if (uap->tzp) {
1187144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
1188100384Speter		if (error)
1189100384Speter			return (error);
1190144450Sjhb		tzp = &tz;
1191144450Sjhb	} else
1192144450Sjhb		tzp = NULL;
1193144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
1194100384Speter}
1195100384Speter
1196100384Speterint
1197119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1198100384Speter{
1199142059Sjhb	struct timeval32 s32[2];
1200142059Sjhb	struct timeval s[2], *sp;
1201100384Speter	int error;
1202100384Speter
1203142059Sjhb	if (uap->tptr != NULL) {
1204142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
1205100384Speter		if (error)
1206100384Speter			return (error);
1207100384Speter		CP(s32[0], s[0], tv_sec);
1208100384Speter		CP(s32[0], s[0], tv_usec);
1209100384Speter		CP(s32[1], s[1], tv_sec);
1210100384Speter		CP(s32[1], s[1], tv_usec);
1211142059Sjhb		sp = s;
1212142059Sjhb	} else
1213142059Sjhb		sp = NULL;
1214142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1215100384Speter}
1216100384Speter
1217100384Speterint
1218154586Sambriskofreebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1219154586Sambrisko{
1220154586Sambrisko	struct timeval32 s32[2];
1221154586Sambrisko	struct timeval s[2], *sp;
1222154586Sambrisko	int error;
1223154586Sambrisko
1224154586Sambrisko	if (uap->tptr != NULL) {
1225154586Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1226154586Sambrisko		if (error)
1227154586Sambrisko			return (error);
1228154586Sambrisko		CP(s32[0], s[0], tv_sec);
1229154586Sambrisko		CP(s32[0], s[0], tv_usec);
1230154586Sambrisko		CP(s32[1], s[1], tv_sec);
1231154586Sambrisko		CP(s32[1], s[1], tv_usec);
1232154586Sambrisko		sp = s;
1233154586Sambrisko	} else
1234154586Sambrisko		sp = NULL;
1235154586Sambrisko	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1236154586Sambrisko}
1237154586Sambrisko
1238154586Sambriskoint
1239153247Sambriskofreebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1240153247Sambrisko{
1241153247Sambrisko	struct timeval32 s32[2];
1242153247Sambrisko	struct timeval s[2], *sp;
1243153247Sambrisko	int error;
1244153247Sambrisko
1245153247Sambrisko	if (uap->tptr != NULL) {
1246153247Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1247153247Sambrisko		if (error)
1248153247Sambrisko			return (error);
1249153247Sambrisko		CP(s32[0], s[0], tv_sec);
1250153247Sambrisko		CP(s32[0], s[0], tv_usec);
1251153247Sambrisko		CP(s32[1], s[1], tv_sec);
1252153247Sambrisko		CP(s32[1], s[1], tv_usec);
1253153247Sambrisko		sp = s;
1254153247Sambrisko	} else
1255153247Sambrisko		sp = NULL;
1256153247Sambrisko	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1257153247Sambrisko}
1258153247Sambrisko
1259177789Skibint
1260177789Skibfreebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
1261177789Skib{
1262177789Skib	struct timeval32 s32[2];
1263177789Skib	struct timeval s[2], *sp;
1264177789Skib	int error;
1265153247Sambrisko
1266177789Skib	if (uap->times != NULL) {
1267177789Skib		error = copyin(uap->times, s32, sizeof(s32));
1268177789Skib		if (error)
1269177789Skib			return (error);
1270177789Skib		CP(s32[0], s[0], tv_sec);
1271177789Skib		CP(s32[0], s[0], tv_usec);
1272177789Skib		CP(s32[1], s[1], tv_sec);
1273177789Skib		CP(s32[1], s[1], tv_usec);
1274177789Skib		sp = s;
1275177789Skib	} else
1276177789Skib		sp = NULL;
1277177789Skib	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
1278177789Skib		sp, UIO_SYSSPACE));
1279177789Skib}
1280177789Skib
1281153247Sambriskoint
1282119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1283100384Speter{
1284144450Sjhb	struct timeval32 tv32;
1285144450Sjhb	struct timeval delta, olddelta, *deltap;
1286100384Speter	int error;
1287100384Speter
1288144450Sjhb	if (uap->delta) {
1289144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
1290100384Speter		if (error)
1291100384Speter			return (error);
1292144450Sjhb		CP(tv32, delta, tv_sec);
1293144450Sjhb		CP(tv32, delta, tv_usec);
1294144450Sjhb		deltap = &delta;
1295144450Sjhb	} else
1296144450Sjhb		deltap = NULL;
1297144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
1298144450Sjhb	if (uap->olddelta && error == 0) {
1299144450Sjhb		CP(olddelta, tv32, tv_sec);
1300144450Sjhb		CP(olddelta, tv32, tv_usec);
1301144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1302100384Speter	}
1303100384Speter	return (error);
1304100384Speter}
1305100384Speter
1306128597Smarcel#ifdef COMPAT_FREEBSD4
1307100384Speterint
1308128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1309100384Speter{
1310142059Sjhb	struct statfs32 s32;
1311142059Sjhb	struct statfs s;
1312100384Speter	int error;
1313100384Speter
1314142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1315100384Speter	if (error)
1316100384Speter		return (error);
1317174526Sjhb	copy_statfs(&s, &s32);
1318142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1319100384Speter}
1320128597Smarcel#endif
1321100384Speter
1322128597Smarcel#ifdef COMPAT_FREEBSD4
1323100384Speterint
1324128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1325100384Speter{
1326142059Sjhb	struct statfs32 s32;
1327142059Sjhb	struct statfs s;
1328100384Speter	int error;
1329100384Speter
1330142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
1331100384Speter	if (error)
1332100384Speter		return (error);
1333174526Sjhb	copy_statfs(&s, &s32);
1334142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1335100384Speter}
1336128597Smarcel#endif
1337100384Speter
1338128597Smarcel#ifdef COMPAT_FREEBSD4
1339100384Speterint
1340128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1341128260Speter{
1342142059Sjhb	struct statfs32 s32;
1343142059Sjhb	struct statfs s;
1344142059Sjhb	fhandle_t fh;
1345128260Speter	int error;
1346128260Speter
1347142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1348142059Sjhb		return (error);
1349142059Sjhb	error = kern_fhstatfs(td, fh, &s);
1350128260Speter	if (error)
1351128260Speter		return (error);
1352174526Sjhb	copy_statfs(&s, &s32);
1353142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1354128260Speter}
1355128597Smarcel#endif
1356128260Speter
1357194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1358194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1359174381Sjhbstatic void
1360194910Sjhbfreebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip)
1361194910Sjhb{
1362194910Sjhb
1363194910Sjhb	CP(*ip32, *ip, cuid);
1364194910Sjhb	CP(*ip32, *ip, cgid);
1365194910Sjhb	CP(*ip32, *ip, uid);
1366194910Sjhb	CP(*ip32, *ip, gid);
1367194910Sjhb	CP(*ip32, *ip, mode);
1368194910Sjhb	CP(*ip32, *ip, seq);
1369194910Sjhb	CP(*ip32, *ip, key);
1370194910Sjhb}
1371194910Sjhb
1372194910Sjhbstatic void
1373194910Sjhbfreebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32)
1374194910Sjhb{
1375194910Sjhb
1376194910Sjhb	CP(*ip, *ip32, cuid);
1377194910Sjhb	CP(*ip, *ip32, cgid);
1378194910Sjhb	CP(*ip, *ip32, uid);
1379194910Sjhb	CP(*ip, *ip32, gid);
1380194910Sjhb	CP(*ip, *ip32, mode);
1381194910Sjhb	CP(*ip, *ip32, seq);
1382194910Sjhb	CP(*ip, *ip32, key);
1383194910Sjhb}
1384194910Sjhb#endif
1385194910Sjhb
1386194910Sjhbstatic void
1387174381Sjhbfreebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1388174381Sjhb{
1389174381Sjhb
1390174381Sjhb	CP(*ip32, *ip, cuid);
1391174381Sjhb	CP(*ip32, *ip, cgid);
1392174381Sjhb	CP(*ip32, *ip, uid);
1393174381Sjhb	CP(*ip32, *ip, gid);
1394174381Sjhb	CP(*ip32, *ip, mode);
1395174381Sjhb	CP(*ip32, *ip, seq);
1396174381Sjhb	CP(*ip32, *ip, key);
1397174381Sjhb}
1398174381Sjhb
1399174381Sjhbstatic void
1400174381Sjhbfreebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1401174381Sjhb{
1402174381Sjhb
1403174381Sjhb	CP(*ip, *ip32, cuid);
1404174381Sjhb	CP(*ip, *ip32, cgid);
1405174381Sjhb	CP(*ip, *ip32, uid);
1406174381Sjhb	CP(*ip, *ip32, gid);
1407174381Sjhb	CP(*ip, *ip32, mode);
1408174381Sjhb	CP(*ip, *ip32, seq);
1409174381Sjhb	CP(*ip, *ip32, key);
1410174381Sjhb}
1411174381Sjhb
1412128260Speterint
1413119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1414100384Speter{
1415174381Sjhb
1416194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1417194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1418174381Sjhb	switch (uap->which) {
1419174381Sjhb	case 0:
1420195911Sjhb		return (freebsd7_freebsd32_semctl(td,
1421195911Sjhb		    (struct freebsd7_freebsd32_semctl_args *)&uap->a2));
1422174381Sjhb	default:
1423174381Sjhb		return (semsys(td, (struct semsys_args *)uap));
1424174381Sjhb	}
1425194910Sjhb#else
1426194910Sjhb	return (nosys(td, NULL));
1427194910Sjhb#endif
1428100384Speter}
1429100384Speter
1430194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1431194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1432100384Speterint
1433194910Sjhbfreebsd7_freebsd32_semctl(struct thread *td,
1434194910Sjhb    struct freebsd7_freebsd32_semctl_args *uap)
1435194910Sjhb{
1436194910Sjhb	struct semid_ds32_old dsbuf32;
1437194910Sjhb	struct semid_ds dsbuf;
1438194910Sjhb	union semun semun;
1439194910Sjhb	union semun32 arg;
1440194910Sjhb	register_t rval;
1441194910Sjhb	int error;
1442194910Sjhb
1443194910Sjhb	switch (uap->cmd) {
1444194910Sjhb	case SEM_STAT:
1445194910Sjhb	case IPC_SET:
1446194910Sjhb	case IPC_STAT:
1447194910Sjhb	case GETALL:
1448194910Sjhb	case SETVAL:
1449194910Sjhb	case SETALL:
1450194910Sjhb		error = copyin(uap->arg, &arg, sizeof(arg));
1451194910Sjhb		if (error)
1452194910Sjhb			return (error);
1453194910Sjhb		break;
1454194910Sjhb	}
1455194910Sjhb
1456194910Sjhb	switch (uap->cmd) {
1457194910Sjhb	case SEM_STAT:
1458194910Sjhb	case IPC_STAT:
1459194910Sjhb		semun.buf = &dsbuf;
1460194910Sjhb		break;
1461194910Sjhb	case IPC_SET:
1462194910Sjhb		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1463194910Sjhb		if (error)
1464194910Sjhb			return (error);
1465194910Sjhb		freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1466194910Sjhb		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1467194910Sjhb		CP(dsbuf32, dsbuf, sem_nsems);
1468194910Sjhb		CP(dsbuf32, dsbuf, sem_otime);
1469194910Sjhb		CP(dsbuf32, dsbuf, sem_ctime);
1470194910Sjhb		semun.buf = &dsbuf;
1471194910Sjhb		break;
1472194910Sjhb	case GETALL:
1473194910Sjhb	case SETALL:
1474194910Sjhb		semun.array = PTRIN(arg.array);
1475194910Sjhb		break;
1476194910Sjhb	case SETVAL:
1477194910Sjhb		semun.val = arg.val;
1478194910Sjhb		break;
1479194910Sjhb	}
1480194910Sjhb
1481194910Sjhb	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1482194910Sjhb	    &rval);
1483194910Sjhb	if (error)
1484194910Sjhb		return (error);
1485194910Sjhb
1486194910Sjhb	switch (uap->cmd) {
1487194910Sjhb	case SEM_STAT:
1488194910Sjhb	case IPC_STAT:
1489194910Sjhb		bzero(&dsbuf32, sizeof(dsbuf32));
1490194910Sjhb		freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1491194910Sjhb		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1492194910Sjhb		CP(dsbuf, dsbuf32, sem_nsems);
1493194910Sjhb		CP(dsbuf, dsbuf32, sem_otime);
1494194910Sjhb		CP(dsbuf, dsbuf32, sem_ctime);
1495194910Sjhb		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1496194910Sjhb		break;
1497194910Sjhb	}
1498194910Sjhb
1499194910Sjhb	if (error == 0)
1500194910Sjhb		td->td_retval[0] = rval;
1501194910Sjhb	return (error);
1502194910Sjhb}
1503194910Sjhb#endif
1504194910Sjhb
1505194910Sjhbint
1506174381Sjhbfreebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1507174381Sjhb{
1508174381Sjhb	struct semid_ds32 dsbuf32;
1509174381Sjhb	struct semid_ds dsbuf;
1510174381Sjhb	union semun semun;
1511174381Sjhb	union semun32 arg;
1512174381Sjhb	register_t rval;
1513174381Sjhb	int error;
1514174381Sjhb
1515174381Sjhb	switch (uap->cmd) {
1516174381Sjhb	case SEM_STAT:
1517174381Sjhb	case IPC_SET:
1518174381Sjhb	case IPC_STAT:
1519174381Sjhb	case GETALL:
1520174381Sjhb	case SETVAL:
1521174381Sjhb	case SETALL:
1522174381Sjhb		error = copyin(uap->arg, &arg, sizeof(arg));
1523174381Sjhb		if (error)
1524174381Sjhb			return (error);
1525174381Sjhb		break;
1526174381Sjhb	}
1527174381Sjhb
1528174381Sjhb	switch (uap->cmd) {
1529174381Sjhb	case SEM_STAT:
1530174381Sjhb	case IPC_STAT:
1531174381Sjhb		semun.buf = &dsbuf;
1532174381Sjhb		break;
1533174381Sjhb	case IPC_SET:
1534174381Sjhb		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1535174381Sjhb		if (error)
1536174381Sjhb			return (error);
1537174381Sjhb		freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1538174381Sjhb		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1539174381Sjhb		CP(dsbuf32, dsbuf, sem_nsems);
1540174381Sjhb		CP(dsbuf32, dsbuf, sem_otime);
1541174381Sjhb		CP(dsbuf32, dsbuf, sem_ctime);
1542174381Sjhb		semun.buf = &dsbuf;
1543174381Sjhb		break;
1544174381Sjhb	case GETALL:
1545174381Sjhb	case SETALL:
1546174381Sjhb		semun.array = PTRIN(arg.array);
1547174381Sjhb		break;
1548174381Sjhb	case SETVAL:
1549174381Sjhb		semun.val = arg.val;
1550174381Sjhb		break;
1551174381Sjhb	}
1552174381Sjhb
1553174381Sjhb	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1554174381Sjhb	    &rval);
1555174381Sjhb	if (error)
1556174381Sjhb		return (error);
1557174381Sjhb
1558174381Sjhb	switch (uap->cmd) {
1559174381Sjhb	case SEM_STAT:
1560174381Sjhb	case IPC_STAT:
1561194910Sjhb		bzero(&dsbuf32, sizeof(dsbuf32));
1562174381Sjhb		freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1563174381Sjhb		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1564174381Sjhb		CP(dsbuf, dsbuf32, sem_nsems);
1565174381Sjhb		CP(dsbuf, dsbuf32, sem_otime);
1566174381Sjhb		CP(dsbuf, dsbuf32, sem_ctime);
1567174381Sjhb		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1568174381Sjhb		break;
1569174381Sjhb	}
1570174381Sjhb
1571174381Sjhb	if (error == 0)
1572174381Sjhb		td->td_retval[0] = rval;
1573174381Sjhb	return (error);
1574174381Sjhb}
1575174381Sjhb
1576174381Sjhbint
1577119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1578100384Speter{
1579174381Sjhb
1580194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1581194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1582165405Sjkim	switch (uap->which) {
1583174381Sjhb	case 0:
1584195911Sjhb		return (freebsd7_freebsd32_msgctl(td,
1585195911Sjhb		    (struct freebsd7_freebsd32_msgctl_args *)&uap->a2));
1586165405Sjkim	case 2:
1587165405Sjkim		return (freebsd32_msgsnd(td,
1588165405Sjkim		    (struct freebsd32_msgsnd_args *)&uap->a2));
1589165405Sjkim	case 3:
1590165405Sjkim		return (freebsd32_msgrcv(td,
1591165405Sjkim		    (struct freebsd32_msgrcv_args *)&uap->a2));
1592165405Sjkim	default:
1593174381Sjhb		return (msgsys(td, (struct msgsys_args *)uap));
1594165405Sjkim	}
1595194910Sjhb#else
1596194910Sjhb	return (nosys(td, NULL));
1597194910Sjhb#endif
1598100384Speter}
1599100384Speter
1600194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1601194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1602100384Speterint
1603194910Sjhbfreebsd7_freebsd32_msgctl(struct thread *td,
1604194910Sjhb    struct freebsd7_freebsd32_msgctl_args *uap)
1605194910Sjhb{
1606194910Sjhb	struct msqid_ds msqbuf;
1607194910Sjhb	struct msqid_ds32_old msqbuf32;
1608194910Sjhb	int error;
1609194910Sjhb
1610194910Sjhb	if (uap->cmd == IPC_SET) {
1611194910Sjhb		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1612194910Sjhb		if (error)
1613194910Sjhb			return (error);
1614194910Sjhb		freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1615194910Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1616194910Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1617194910Sjhb		CP(msqbuf32, msqbuf, msg_cbytes);
1618194910Sjhb		CP(msqbuf32, msqbuf, msg_qnum);
1619194910Sjhb		CP(msqbuf32, msqbuf, msg_qbytes);
1620194910Sjhb		CP(msqbuf32, msqbuf, msg_lspid);
1621194910Sjhb		CP(msqbuf32, msqbuf, msg_lrpid);
1622194910Sjhb		CP(msqbuf32, msqbuf, msg_stime);
1623194910Sjhb		CP(msqbuf32, msqbuf, msg_rtime);
1624194910Sjhb		CP(msqbuf32, msqbuf, msg_ctime);
1625194910Sjhb	}
1626194910Sjhb	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1627194910Sjhb	if (error)
1628194910Sjhb		return (error);
1629194910Sjhb	if (uap->cmd == IPC_STAT) {
1630194910Sjhb		bzero(&msqbuf32, sizeof(msqbuf32));
1631194910Sjhb		freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1632194910Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1633194910Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1634194910Sjhb		CP(msqbuf, msqbuf32, msg_cbytes);
1635194910Sjhb		CP(msqbuf, msqbuf32, msg_qnum);
1636194910Sjhb		CP(msqbuf, msqbuf32, msg_qbytes);
1637194910Sjhb		CP(msqbuf, msqbuf32, msg_lspid);
1638194910Sjhb		CP(msqbuf, msqbuf32, msg_lrpid);
1639194910Sjhb		CP(msqbuf, msqbuf32, msg_stime);
1640194910Sjhb		CP(msqbuf, msqbuf32, msg_rtime);
1641194910Sjhb		CP(msqbuf, msqbuf32, msg_ctime);
1642194910Sjhb		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1643194910Sjhb	}
1644194910Sjhb	return (error);
1645194910Sjhb}
1646194910Sjhb#endif
1647194910Sjhb
1648194910Sjhbint
1649174381Sjhbfreebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1650174381Sjhb{
1651174381Sjhb	struct msqid_ds msqbuf;
1652174381Sjhb	struct msqid_ds32 msqbuf32;
1653174381Sjhb	int error;
1654174381Sjhb
1655174381Sjhb	if (uap->cmd == IPC_SET) {
1656174381Sjhb		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1657174381Sjhb		if (error)
1658174381Sjhb			return (error);
1659174381Sjhb		freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1660174381Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1661174381Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1662174381Sjhb		CP(msqbuf32, msqbuf, msg_cbytes);
1663174381Sjhb		CP(msqbuf32, msqbuf, msg_qnum);
1664174381Sjhb		CP(msqbuf32, msqbuf, msg_qbytes);
1665174381Sjhb		CP(msqbuf32, msqbuf, msg_lspid);
1666174381Sjhb		CP(msqbuf32, msqbuf, msg_lrpid);
1667174381Sjhb		CP(msqbuf32, msqbuf, msg_stime);
1668174381Sjhb		CP(msqbuf32, msqbuf, msg_rtime);
1669174381Sjhb		CP(msqbuf32, msqbuf, msg_ctime);
1670174381Sjhb	}
1671174381Sjhb	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1672174381Sjhb	if (error)
1673174381Sjhb		return (error);
1674174381Sjhb	if (uap->cmd == IPC_STAT) {
1675174381Sjhb		freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1676174381Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1677174381Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1678174381Sjhb		CP(msqbuf, msqbuf32, msg_cbytes);
1679174381Sjhb		CP(msqbuf, msqbuf32, msg_qnum);
1680174381Sjhb		CP(msqbuf, msqbuf32, msg_qbytes);
1681174381Sjhb		CP(msqbuf, msqbuf32, msg_lspid);
1682174381Sjhb		CP(msqbuf, msqbuf32, msg_lrpid);
1683174381Sjhb		CP(msqbuf, msqbuf32, msg_stime);
1684174381Sjhb		CP(msqbuf, msqbuf32, msg_rtime);
1685174381Sjhb		CP(msqbuf, msqbuf32, msg_ctime);
1686174381Sjhb		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1687174381Sjhb	}
1688174381Sjhb	return (error);
1689174381Sjhb}
1690174381Sjhb
1691174381Sjhbint
1692165405Sjkimfreebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1693165405Sjkim{
1694165405Sjkim	const void *msgp;
1695165405Sjkim	long mtype;
1696165405Sjkim	int32_t mtype32;
1697165405Sjkim	int error;
1698165405Sjkim
1699165405Sjkim	msgp = PTRIN(uap->msgp);
1700165405Sjkim	if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1701165405Sjkim		return (error);
1702165405Sjkim	mtype = mtype32;
1703165405Sjkim	return (kern_msgsnd(td, uap->msqid,
1704165405Sjkim	    (const char *)msgp + sizeof(mtype32),
1705165405Sjkim	    uap->msgsz, uap->msgflg, mtype));
1706165405Sjkim}
1707165405Sjkim
1708165405Sjkimint
1709165405Sjkimfreebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1710165405Sjkim{
1711165405Sjkim	void *msgp;
1712165405Sjkim	long mtype;
1713165405Sjkim	int32_t mtype32;
1714165405Sjkim	int error;
1715165405Sjkim
1716165405Sjkim	msgp = PTRIN(uap->msgp);
1717165405Sjkim	if ((error = kern_msgrcv(td, uap->msqid,
1718165405Sjkim	    (char *)msgp + sizeof(mtype32), uap->msgsz,
1719165405Sjkim	    uap->msgtyp, uap->msgflg, &mtype)) != 0)
1720165405Sjkim		return (error);
1721165405Sjkim	mtype32 = (int32_t)mtype;
1722165405Sjkim	return (copyout(&mtype32, msgp, sizeof(mtype32)));
1723165405Sjkim}
1724165405Sjkim
1725165405Sjkimint
1726119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1727100384Speter{
1728157285Sps
1729194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1730194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1731157285Sps	switch (uap->which) {
1732157285Sps	case 0:	{	/* shmat */
1733157285Sps		struct shmat_args ap;
1734157285Sps
1735157285Sps		ap.shmid = uap->a2;
1736157285Sps		ap.shmaddr = PTRIN(uap->a3);
1737157285Sps		ap.shmflg = uap->a4;
1738157285Sps		return (sysent[SYS_shmat].sy_call(td, &ap));
1739157285Sps	}
1740157285Sps	case 2: {	/* shmdt */
1741157285Sps		struct shmdt_args ap;
1742157285Sps
1743157285Sps		ap.shmaddr = PTRIN(uap->a2);
1744157285Sps		return (sysent[SYS_shmdt].sy_call(td, &ap));
1745157285Sps	}
1746157285Sps	case 3: {	/* shmget */
1747157285Sps		struct shmget_args ap;
1748157285Sps
1749157285Sps		ap.key = uap->a2;
1750157285Sps		ap.size = uap->a3;
1751157285Sps		ap.shmflg = uap->a4;
1752157285Sps		return (sysent[SYS_shmget].sy_call(td, &ap));
1753157285Sps	}
1754157285Sps	case 4: {	/* shmctl */
1755195911Sjhb		struct freebsd7_freebsd32_shmctl_args ap;
1756157285Sps
1757157285Sps		ap.shmid = uap->a2;
1758157285Sps		ap.cmd = uap->a3;
1759157285Sps		ap.buf = PTRIN(uap->a4);
1760195911Sjhb		return (freebsd7_freebsd32_shmctl(td, &ap));
1761157285Sps	}
1762157285Sps	case 1:		/* oshmctl */
1763157285Sps	default:
1764157285Sps		return (EINVAL);
1765157285Sps	}
1766194910Sjhb#else
1767194910Sjhb	return (nosys(td, NULL));
1768194910Sjhb#endif
1769100384Speter}
1770100384Speter
1771194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1772194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1773100384Speterint
1774194910Sjhbfreebsd7_freebsd32_shmctl(struct thread *td,
1775194910Sjhb    struct freebsd7_freebsd32_shmctl_args *uap)
1776194910Sjhb{
1777194910Sjhb	int error = 0;
1778194910Sjhb	union {
1779194910Sjhb		struct shmid_ds shmid_ds;
1780194910Sjhb		struct shm_info shm_info;
1781194910Sjhb		struct shminfo shminfo;
1782194910Sjhb	} u;
1783194910Sjhb	union {
1784194910Sjhb		struct shmid_ds32_old shmid_ds32;
1785194910Sjhb		struct shm_info32 shm_info32;
1786194910Sjhb		struct shminfo32 shminfo32;
1787194910Sjhb	} u32;
1788194910Sjhb	size_t sz;
1789194910Sjhb
1790194910Sjhb	if (uap->cmd == IPC_SET) {
1791194910Sjhb		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1792194910Sjhb		    sizeof(u32.shmid_ds32))))
1793194910Sjhb			goto done;
1794194910Sjhb		freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm,
1795194910Sjhb		    &u.shmid_ds.shm_perm);
1796194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1797194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1798194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1799194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1800194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1801194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1802194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1803194910Sjhb	}
1804194910Sjhb
1805194910Sjhb	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1806194910Sjhb	if (error)
1807194910Sjhb		goto done;
1808194910Sjhb
1809194910Sjhb	/* Cases in which we need to copyout */
1810194910Sjhb	switch (uap->cmd) {
1811194910Sjhb	case IPC_INFO:
1812194910Sjhb		CP(u.shminfo, u32.shminfo32, shmmax);
1813194910Sjhb		CP(u.shminfo, u32.shminfo32, shmmin);
1814194910Sjhb		CP(u.shminfo, u32.shminfo32, shmmni);
1815194910Sjhb		CP(u.shminfo, u32.shminfo32, shmseg);
1816194910Sjhb		CP(u.shminfo, u32.shminfo32, shmall);
1817194910Sjhb		error = copyout(&u32.shminfo32, uap->buf,
1818194910Sjhb		    sizeof(u32.shminfo32));
1819194910Sjhb		break;
1820194910Sjhb	case SHM_INFO:
1821194910Sjhb		CP(u.shm_info, u32.shm_info32, used_ids);
1822194910Sjhb		CP(u.shm_info, u32.shm_info32, shm_rss);
1823194910Sjhb		CP(u.shm_info, u32.shm_info32, shm_tot);
1824194910Sjhb		CP(u.shm_info, u32.shm_info32, shm_swp);
1825194910Sjhb		CP(u.shm_info, u32.shm_info32, swap_attempts);
1826194910Sjhb		CP(u.shm_info, u32.shm_info32, swap_successes);
1827194910Sjhb		error = copyout(&u32.shm_info32, uap->buf,
1828194910Sjhb		    sizeof(u32.shm_info32));
1829194910Sjhb		break;
1830194910Sjhb	case SHM_STAT:
1831194910Sjhb	case IPC_STAT:
1832194910Sjhb		freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm,
1833194910Sjhb		    &u32.shmid_ds32.shm_perm);
1834194910Sjhb		if (u.shmid_ds.shm_segsz > INT32_MAX)
1835194910Sjhb			u32.shmid_ds32.shm_segsz = INT32_MAX;
1836194910Sjhb		else
1837194910Sjhb			CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1838194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1839194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1840194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1841194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1842194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1843194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1844194910Sjhb		u32.shmid_ds32.shm_internal = 0;
1845194910Sjhb		error = copyout(&u32.shmid_ds32, uap->buf,
1846194910Sjhb		    sizeof(u32.shmid_ds32));
1847194910Sjhb		break;
1848194910Sjhb	}
1849194910Sjhb
1850194910Sjhbdone:
1851194910Sjhb	if (error) {
1852194910Sjhb		/* Invalidate the return value */
1853194910Sjhb		td->td_retval[0] = -1;
1854194910Sjhb	}
1855194910Sjhb	return (error);
1856194910Sjhb}
1857194910Sjhb#endif
1858194910Sjhb
1859194910Sjhbint
1860157285Spsfreebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1861157285Sps{
1862157285Sps	int error = 0;
1863157285Sps	union {
1864157285Sps		struct shmid_ds shmid_ds;
1865157285Sps		struct shm_info shm_info;
1866157285Sps		struct shminfo shminfo;
1867157285Sps	} u;
1868157285Sps	union {
1869157285Sps		struct shmid_ds32 shmid_ds32;
1870157285Sps		struct shm_info32 shm_info32;
1871157285Sps		struct shminfo32 shminfo32;
1872157285Sps	} u32;
1873157285Sps	size_t sz;
1874157285Sps
1875157285Sps	if (uap->cmd == IPC_SET) {
1876157285Sps		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1877157285Sps		    sizeof(u32.shmid_ds32))))
1878157285Sps			goto done;
1879174381Sjhb		freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1880174381Sjhb		    &u.shmid_ds.shm_perm);
1881157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1882157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1883157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1884157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1885157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1886157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1887157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1888157285Sps	}
1889157285Sps
1890157285Sps	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1891157285Sps	if (error)
1892157285Sps		goto done;
1893157285Sps
1894157285Sps	/* Cases in which we need to copyout */
1895157285Sps	switch (uap->cmd) {
1896157285Sps	case IPC_INFO:
1897157285Sps		CP(u.shminfo, u32.shminfo32, shmmax);
1898157285Sps		CP(u.shminfo, u32.shminfo32, shmmin);
1899157285Sps		CP(u.shminfo, u32.shminfo32, shmmni);
1900157285Sps		CP(u.shminfo, u32.shminfo32, shmseg);
1901157285Sps		CP(u.shminfo, u32.shminfo32, shmall);
1902157285Sps		error = copyout(&u32.shminfo32, uap->buf,
1903157285Sps		    sizeof(u32.shminfo32));
1904157285Sps		break;
1905157285Sps	case SHM_INFO:
1906157285Sps		CP(u.shm_info, u32.shm_info32, used_ids);
1907157285Sps		CP(u.shm_info, u32.shm_info32, shm_rss);
1908157285Sps		CP(u.shm_info, u32.shm_info32, shm_tot);
1909157285Sps		CP(u.shm_info, u32.shm_info32, shm_swp);
1910157285Sps		CP(u.shm_info, u32.shm_info32, swap_attempts);
1911157285Sps		CP(u.shm_info, u32.shm_info32, swap_successes);
1912157285Sps		error = copyout(&u32.shm_info32, uap->buf,
1913157285Sps		    sizeof(u32.shm_info32));
1914157285Sps		break;
1915157285Sps	case SHM_STAT:
1916157285Sps	case IPC_STAT:
1917174381Sjhb		freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1918174381Sjhb		    &u32.shmid_ds32.shm_perm);
1919194910Sjhb		if (u.shmid_ds.shm_segsz > INT32_MAX)
1920194910Sjhb			u32.shmid_ds32.shm_segsz = INT32_MAX;
1921194910Sjhb		else
1922194910Sjhb			CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1923157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1924157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1925157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1926157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1927157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1928157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1929157285Sps		error = copyout(&u32.shmid_ds32, uap->buf,
1930157285Sps		    sizeof(u32.shmid_ds32));
1931157285Sps		break;
1932157285Sps	}
1933157285Sps
1934157285Spsdone:
1935157285Sps	if (error) {
1936157285Sps		/* Invalidate the return value */
1937157285Sps		td->td_retval[0] = -1;
1938157285Sps	}
1939157285Sps	return (error);
1940157285Sps}
1941157285Sps
1942157285Spsint
1943119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1944100384Speter{
1945100384Speter	struct pread_args ap;
1946100384Speter
1947107849Salfred	ap.fd = uap->fd;
1948107849Salfred	ap.buf = uap->buf;
1949107849Salfred	ap.nbyte = uap->nbyte;
1950119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1951100384Speter	return (pread(td, &ap));
1952100384Speter}
1953100384Speter
1954100384Speterint
1955119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1956100384Speter{
1957100384Speter	struct pwrite_args ap;
1958100384Speter
1959107849Salfred	ap.fd = uap->fd;
1960107849Salfred	ap.buf = uap->buf;
1961107849Salfred	ap.nbyte = uap->nbyte;
1962119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1963100384Speter	return (pwrite(td, &ap));
1964100384Speter}
1965100384Speter
1966100384Speterint
1967119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1968100384Speter{
1969100384Speter	int error;
1970100384Speter	struct lseek_args ap;
1971100384Speter	off_t pos;
1972100384Speter
1973107849Salfred	ap.fd = uap->fd;
1974119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1975107849Salfred	ap.whence = uap->whence;
1976100384Speter	error = lseek(td, &ap);
1977100384Speter	/* Expand the quad return into two parts for eax and edx */
1978100384Speter	pos = *(off_t *)(td->td_retval);
1979100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1980100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1981100384Speter	return error;
1982100384Speter}
1983100384Speter
1984100384Speterint
1985119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1986100384Speter{
1987100384Speter	struct truncate_args ap;
1988100384Speter
1989107849Salfred	ap.path = uap->path;
1990119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1991100384Speter	return (truncate(td, &ap));
1992100384Speter}
1993100384Speter
1994100384Speterint
1995119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1996100384Speter{
1997100384Speter	struct ftruncate_args ap;
1998100384Speter
1999107849Salfred	ap.fd = uap->fd;
2000119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
2001100384Speter	return (ftruncate(td, &ap));
2002100384Speter}
2003100384Speter
2004184183Sjhbint
2005184183Sjhbfreebsd32_getdirentries(struct thread *td,
2006184183Sjhb    struct freebsd32_getdirentries_args *uap)
2007184183Sjhb{
2008184183Sjhb	long base;
2009184183Sjhb	int32_t base32;
2010184183Sjhb	int error;
2011184183Sjhb
2012184183Sjhb	error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
2013184183Sjhb	if (error)
2014184183Sjhb		return (error);
2015184183Sjhb	if (uap->basep != NULL) {
2016184183Sjhb		base32 = base;
2017184183Sjhb		error = copyout(&base32, uap->basep, sizeof(int32_t));
2018184183Sjhb	}
2019184183Sjhb	return (error);
2020184183Sjhb}
2021184183Sjhb
2022171215Speter#ifdef COMPAT_FREEBSD6
2023171215Speter/* versions with the 'int pad' argument */
2024171215Speterint
2025171215Speterfreebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
2026171215Speter{
2027171215Speter	struct pread_args ap;
2028171215Speter
2029171215Speter	ap.fd = uap->fd;
2030171215Speter	ap.buf = uap->buf;
2031171215Speter	ap.nbyte = uap->nbyte;
2032171215Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
2033171215Speter	return (pread(td, &ap));
2034171215Speter}
2035171215Speter
2036171215Speterint
2037171215Speterfreebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
2038171215Speter{
2039171215Speter	struct pwrite_args ap;
2040171215Speter
2041171215Speter	ap.fd = uap->fd;
2042171215Speter	ap.buf = uap->buf;
2043171215Speter	ap.nbyte = uap->nbyte;
2044171215Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
2045171215Speter	return (pwrite(td, &ap));
2046171215Speter}
2047171215Speter
2048171215Speterint
2049171215Speterfreebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
2050171215Speter{
2051171215Speter	int error;
2052171215Speter	struct lseek_args ap;
2053171215Speter	off_t pos;
2054171215Speter
2055171215Speter	ap.fd = uap->fd;
2056171215Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
2057171215Speter	ap.whence = uap->whence;
2058171215Speter	error = lseek(td, &ap);
2059171215Speter	/* Expand the quad return into two parts for eax and edx */
2060171215Speter	pos = *(off_t *)(td->td_retval);
2061171215Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
2062171215Speter	td->td_retval[1] = pos >> 32;		/* %edx */
2063171215Speter	return error;
2064171215Speter}
2065171215Speter
2066171215Speterint
2067171215Speterfreebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
2068171215Speter{
2069171215Speter	struct truncate_args ap;
2070171215Speter
2071171215Speter	ap.path = uap->path;
2072171215Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
2073171215Speter	return (truncate(td, &ap));
2074171215Speter}
2075171215Speter
2076171215Speterint
2077171215Speterfreebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
2078171215Speter{
2079171215Speter	struct ftruncate_args ap;
2080171215Speter
2081171215Speter	ap.fd = uap->fd;
2082171215Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
2083171215Speter	return (ftruncate(td, &ap));
2084171215Speter}
2085171215Speter#endif /* COMPAT_FREEBSD6 */
2086171215Speter
2087156114Spsstruct sf_hdtr32 {
2088156114Sps	uint32_t headers;
2089156114Sps	int hdr_cnt;
2090156114Sps	uint32_t trailers;
2091156114Sps	int trl_cnt;
2092156114Sps};
2093156114Sps
2094156114Spsstatic int
2095156114Spsfreebsd32_do_sendfile(struct thread *td,
2096156114Sps    struct freebsd32_sendfile_args *uap, int compat)
2097104738Speter{
2098156114Sps	struct sendfile_args ap;
2099156114Sps	struct sf_hdtr32 hdtr32;
2100156114Sps	struct sf_hdtr hdtr;
2101156114Sps	struct uio *hdr_uio, *trl_uio;
2102156114Sps	struct iovec32 *iov32;
2103156114Sps	int error;
2104104738Speter
2105156114Sps	hdr_uio = trl_uio = NULL;
2106156114Sps
2107107849Salfred	ap.fd = uap->fd;
2108107849Salfred	ap.s = uap->s;
2109119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
2110156114Sps	ap.nbytes = uap->nbytes;
2111156114Sps	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
2112156114Sps	ap.sbytes = uap->sbytes;
2113107849Salfred	ap.flags = uap->flags;
2114156114Sps
2115156114Sps	if (uap->hdtr != NULL) {
2116156114Sps		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
2117156114Sps		if (error)
2118156114Sps			goto out;
2119156114Sps		PTRIN_CP(hdtr32, hdtr, headers);
2120156114Sps		CP(hdtr32, hdtr, hdr_cnt);
2121156114Sps		PTRIN_CP(hdtr32, hdtr, trailers);
2122156114Sps		CP(hdtr32, hdtr, trl_cnt);
2123156114Sps
2124156114Sps		if (hdtr.headers != NULL) {
2125160246Sjhb			iov32 = PTRIN(hdtr32.headers);
2126156114Sps			error = freebsd32_copyinuio(iov32,
2127156114Sps			    hdtr32.hdr_cnt, &hdr_uio);
2128156114Sps			if (error)
2129156114Sps				goto out;
2130156114Sps		}
2131156114Sps		if (hdtr.trailers != NULL) {
2132160246Sjhb			iov32 = PTRIN(hdtr32.trailers);
2133156114Sps			error = freebsd32_copyinuio(iov32,
2134156114Sps			    hdtr32.trl_cnt, &trl_uio);
2135156114Sps			if (error)
2136156114Sps				goto out;
2137156114Sps		}
2138156114Sps	}
2139156114Sps
2140156114Sps	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
2141156114Spsout:
2142156114Sps	if (hdr_uio)
2143156114Sps		free(hdr_uio, M_IOV);
2144156114Sps	if (trl_uio)
2145156114Sps		free(trl_uio, M_IOV);
2146156114Sps	return (error);
2147104738Speter}
2148156114Sps
2149156114Sps#ifdef COMPAT_FREEBSD4
2150156114Spsint
2151156114Spsfreebsd4_freebsd32_sendfile(struct thread *td,
2152156114Sps    struct freebsd4_freebsd32_sendfile_args *uap)
2153156114Sps{
2154156114Sps	return (freebsd32_do_sendfile(td,
2155156114Sps	    (struct freebsd32_sendfile_args *)uap, 1));
2156156114Sps}
2157104738Speter#endif
2158104738Speter
2159104738Speterint
2160119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
2161100384Speter{
2162100384Speter
2163156114Sps	return (freebsd32_do_sendfile(td, uap, 0));
2164100384Speter}
2165100384Speter
2166100384Speterstatic void
2167100384Spetercopy_stat( struct stat *in, struct stat32 *out)
2168100384Speter{
2169100384Speter	CP(*in, *out, st_dev);
2170100384Speter	CP(*in, *out, st_ino);
2171100384Speter	CP(*in, *out, st_mode);
2172100384Speter	CP(*in, *out, st_nlink);
2173100384Speter	CP(*in, *out, st_uid);
2174100384Speter	CP(*in, *out, st_gid);
2175100384Speter	CP(*in, *out, st_rdev);
2176100384Speter	TS_CP(*in, *out, st_atimespec);
2177100384Speter	TS_CP(*in, *out, st_mtimespec);
2178100384Speter	TS_CP(*in, *out, st_ctimespec);
2179100384Speter	CP(*in, *out, st_size);
2180100384Speter	CP(*in, *out, st_blocks);
2181100384Speter	CP(*in, *out, st_blksize);
2182100384Speter	CP(*in, *out, st_flags);
2183100384Speter	CP(*in, *out, st_gen);
2184100384Speter}
2185100384Speter
2186100384Speterint
2187119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
2188100384Speter{
2189123746Speter	struct stat sb;
2190123746Speter	struct stat32 sb32;
2191100384Speter	int error;
2192100384Speter
2193142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2194100384Speter	if (error)
2195100384Speter		return (error);
2196123746Speter	copy_stat(&sb, &sb32);
2197123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
2198100384Speter	return (error);
2199100384Speter}
2200100384Speter
2201100384Speterint
2202119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
2203100384Speter{
2204123746Speter	struct stat ub;
2205123746Speter	struct stat32 ub32;
2206100384Speter	int error;
2207100384Speter
2208142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
2209100384Speter	if (error)
2210100384Speter		return (error);
2211123746Speter	copy_stat(&ub, &ub32);
2212123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
2213100384Speter	return (error);
2214100384Speter}
2215100384Speter
2216100384Speterint
2217177789Skibfreebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
2218177789Skib{
2219177789Skib	struct stat ub;
2220177789Skib	struct stat32 ub32;
2221177789Skib	int error;
2222177789Skib
2223177789Skib	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
2224177789Skib	if (error)
2225177789Skib		return (error);
2226177789Skib	copy_stat(&ub, &ub32);
2227177789Skib	error = copyout(&ub32, uap->buf, sizeof(ub32));
2228177789Skib	return (error);
2229177789Skib}
2230177789Skib
2231177789Skibint
2232119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
2233100384Speter{
2234123746Speter	struct stat sb;
2235123746Speter	struct stat32 sb32;
2236142059Sjhb	int error;
2237100384Speter
2238142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2239100384Speter	if (error)
2240100384Speter		return (error);
2241123746Speter	copy_stat(&sb, &sb32);
2242123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
2243100384Speter	return (error);
2244100384Speter}
2245100384Speter
2246100384Speter/*
2247100384Speter * MPSAFE
2248100384Speter */
2249100384Speterint
2250119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
2251100384Speter{
2252100384Speter	int error, name[CTL_MAXNAME];
2253100384Speter	size_t j, oldlen;
2254100384Speter
2255100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2256100384Speter		return (EINVAL);
2257136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
2258100384Speter 	if (error)
2259100384Speter		return (error);
2260100384Speter	if (uap->oldlenp)
2261100384Speter		oldlen = fuword32(uap->oldlenp);
2262100384Speter	else
2263100384Speter		oldlen = 0;
2264100384Speter	error = userland_sysctl(td, name, uap->namelen,
2265100384Speter		uap->old, &oldlen, 1,
2266136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
2267100384Speter	if (error && error != ENOMEM)
2268186564Sed		return (error);
2269136404Speter	if (uap->oldlenp)
2270100384Speter		suword32(uap->oldlenp, j);
2271186564Sed	return (0);
2272100384Speter}
2273100384Speter
2274100384Speterint
2275185435Sbzfreebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2276185435Sbz{
2277185435Sbz	uint32_t version;
2278185435Sbz	int error;
2279192895Sjamie	struct jail j;
2280185435Sbz
2281185435Sbz	error = copyin(uap->jail, &version, sizeof(uint32_t));
2282185435Sbz	if (error)
2283185435Sbz		return (error);
2284190466Sjamie
2285185435Sbz	switch (version) {
2286190466Sjamie	case 0:
2287185435Sbz	{
2288185435Sbz		/* FreeBSD single IPv4 jails. */
2289185435Sbz		struct jail32_v0 j32_v0;
2290185435Sbz
2291192895Sjamie		bzero(&j, sizeof(struct jail));
2292185435Sbz		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2293185435Sbz		if (error)
2294185435Sbz			return (error);
2295192895Sjamie		CP(j32_v0, j, version);
2296192895Sjamie		PTRIN_CP(j32_v0, j, path);
2297192895Sjamie		PTRIN_CP(j32_v0, j, hostname);
2298192895Sjamie		j.ip4s = j32_v0.ip_number;
2299185435Sbz		break;
2300185435Sbz	}
2301185435Sbz
2302185435Sbz	case 1:
2303185435Sbz		/*
2304185435Sbz		 * Version 1 was used by multi-IPv4 jail implementations
2305185435Sbz		 * that never made it into the official kernel.
2306185435Sbz		 */
2307185435Sbz		return (EINVAL);
2308185435Sbz
2309185435Sbz	case 2:	/* JAIL_API_VERSION */
2310185435Sbz	{
2311185435Sbz		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
2312185435Sbz		struct jail32 j32;
2313185435Sbz
2314185435Sbz		error = copyin(uap->jail, &j32, sizeof(struct jail32));
2315185435Sbz		if (error)
2316185435Sbz			return (error);
2317192895Sjamie		CP(j32, j, version);
2318192895Sjamie		PTRIN_CP(j32, j, path);
2319192895Sjamie		PTRIN_CP(j32, j, hostname);
2320192895Sjamie		PTRIN_CP(j32, j, jailname);
2321192895Sjamie		CP(j32, j, ip4s);
2322192895Sjamie		CP(j32, j, ip6s);
2323192895Sjamie		PTRIN_CP(j32, j, ip4);
2324192895Sjamie		PTRIN_CP(j32, j, ip6);
2325185435Sbz		break;
2326185435Sbz	}
2327185435Sbz
2328185435Sbz	default:
2329185435Sbz		/* Sci-Fi jails are not supported, sorry. */
2330185435Sbz		return (EINVAL);
2331185435Sbz	}
2332192895Sjamie	return (kern_jail(td, &j));
2333185435Sbz}
2334185435Sbz
2335185435Sbzint
2336191673Sjamiefreebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2337191673Sjamie{
2338191673Sjamie	struct uio *auio;
2339191673Sjamie	int error;
2340191673Sjamie
2341191673Sjamie	/* Check that we have an even number of iovecs. */
2342191673Sjamie	if (uap->iovcnt & 1)
2343191673Sjamie		return (EINVAL);
2344191673Sjamie
2345191673Sjamie	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2346191673Sjamie	if (error)
2347191673Sjamie		return (error);
2348191673Sjamie	error = kern_jail_set(td, auio, uap->flags);
2349191673Sjamie	free(auio, M_IOV);
2350191673Sjamie	return (error);
2351191673Sjamie}
2352191673Sjamie
2353191673Sjamieint
2354191673Sjamiefreebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2355191673Sjamie{
2356191673Sjamie	struct iovec32 iov32;
2357191673Sjamie	struct uio *auio;
2358191673Sjamie	int error, i;
2359191673Sjamie
2360191673Sjamie	/* Check that we have an even number of iovecs. */
2361191673Sjamie	if (uap->iovcnt & 1)
2362191673Sjamie		return (EINVAL);
2363191673Sjamie
2364191673Sjamie	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2365191673Sjamie	if (error)
2366191673Sjamie		return (error);
2367191673Sjamie	error = kern_jail_get(td, auio, uap->flags);
2368191673Sjamie	if (error == 0)
2369191673Sjamie		for (i = 0; i < uap->iovcnt; i++) {
2370191673Sjamie			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2371191673Sjamie			CP(auio->uio_iov[i], iov32, iov_len);
2372191673Sjamie			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2373191673Sjamie			if (error != 0)
2374191673Sjamie				break;
2375191673Sjamie		}
2376191673Sjamie	free(auio, M_IOV);
2377191673Sjamie	return (error);
2378191673Sjamie}
2379191673Sjamie
2380191673Sjamieint
2381119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
2382100384Speter{
2383113859Sjhb	struct sigaction32 s32;
2384113859Sjhb	struct sigaction sa, osa, *sap;
2385100384Speter	int error;
2386100384Speter
2387113859Sjhb	if (uap->act) {
2388113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
2389100384Speter		if (error)
2390100384Speter			return (error);
2391113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
2392113859Sjhb		CP(s32, sa, sa_flags);
2393113859Sjhb		CP(s32, sa, sa_mask);
2394113859Sjhb		sap = &sa;
2395113859Sjhb	} else
2396113859Sjhb		sap = NULL;
2397113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2398146583Sps	if (error == 0 && uap->oact != NULL) {
2399113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
2400113859Sjhb		CP(osa, s32, sa_flags);
2401113859Sjhb		CP(osa, s32, sa_mask);
2402113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
2403100384Speter	}
2404100384Speter	return (error);
2405100384Speter}
2406100384Speter
2407114987Speter#ifdef COMPAT_FREEBSD4
2408114987Speterint
2409119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
2410119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
2411114987Speter{
2412114987Speter	struct sigaction32 s32;
2413114987Speter	struct sigaction sa, osa, *sap;
2414114987Speter	int error;
2415114987Speter
2416114987Speter	if (uap->act) {
2417114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
2418114987Speter		if (error)
2419114987Speter			return (error);
2420114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
2421114987Speter		CP(s32, sa, sa_flags);
2422114987Speter		CP(s32, sa, sa_mask);
2423114987Speter		sap = &sa;
2424114987Speter	} else
2425114987Speter		sap = NULL;
2426114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2427146583Sps	if (error == 0 && uap->oact != NULL) {
2428114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
2429114987Speter		CP(osa, s32, sa_flags);
2430114987Speter		CP(osa, s32, sa_mask);
2431114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
2432114987Speter	}
2433114987Speter	return (error);
2434114987Speter}
2435114987Speter#endif
2436114987Speter
2437151582Sps#ifdef COMPAT_43
2438151720Speterstruct osigaction32 {
2439151582Sps	u_int32_t	sa_u;
2440151582Sps	osigset_t	sa_mask;
2441151582Sps	int		sa_flags;
2442151582Sps};
2443151582Sps
2444151582Sps#define	ONSIG	32
2445151582Sps
2446140481Spsint
2447151720Speterofreebsd32_sigaction(struct thread *td,
2448151720Speter			     struct ofreebsd32_sigaction_args *uap)
2449151582Sps{
2450151720Speter	struct osigaction32 s32;
2451151582Sps	struct sigaction sa, osa, *sap;
2452151582Sps	int error;
2453151582Sps
2454151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
2455151582Sps		return (EINVAL);
2456151582Sps
2457151582Sps	if (uap->nsa) {
2458151582Sps		error = copyin(uap->nsa, &s32, sizeof(s32));
2459151582Sps		if (error)
2460151582Sps			return (error);
2461151582Sps		sa.sa_handler = PTRIN(s32.sa_u);
2462151582Sps		CP(s32, sa, sa_flags);
2463151582Sps		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2464151582Sps		sap = &sa;
2465151582Sps	} else
2466151582Sps		sap = NULL;
2467151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2468151582Sps	if (error == 0 && uap->osa != NULL) {
2469151582Sps		s32.sa_u = PTROUT(osa.sa_handler);
2470151582Sps		CP(osa, s32, sa_flags);
2471151582Sps		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2472151582Sps		error = copyout(&s32, uap->osa, sizeof(s32));
2473151582Sps	}
2474151582Sps	return (error);
2475151582Sps}
2476151582Sps
2477151582Spsint
2478151720Speterofreebsd32_sigprocmask(struct thread *td,
2479151720Speter			       struct ofreebsd32_sigprocmask_args *uap)
2480151582Sps{
2481151582Sps	sigset_t set, oset;
2482151582Sps	int error;
2483151582Sps
2484151582Sps	OSIG2SIG(uap->mask, set);
2485151582Sps	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
2486151582Sps	SIG2OSIG(oset, td->td_retval[0]);
2487151582Sps	return (error);
2488151582Sps}
2489151582Sps
2490151582Spsint
2491151720Speterofreebsd32_sigpending(struct thread *td,
2492151720Speter			      struct ofreebsd32_sigpending_args *uap)
2493151582Sps{
2494151582Sps	struct proc *p = td->td_proc;
2495151582Sps	sigset_t siglist;
2496151582Sps
2497151582Sps	PROC_LOCK(p);
2498151582Sps	siglist = p->p_siglist;
2499151582Sps	SIGSETOR(siglist, td->td_siglist);
2500151582Sps	PROC_UNLOCK(p);
2501151582Sps	SIG2OSIG(siglist, td->td_retval[0]);
2502151582Sps	return (0);
2503151582Sps}
2504151582Sps
2505151582Spsstruct sigvec32 {
2506151582Sps	u_int32_t	sv_handler;
2507151582Sps	int		sv_mask;
2508151582Sps	int		sv_flags;
2509151582Sps};
2510151582Sps
2511151582Spsint
2512151720Speterofreebsd32_sigvec(struct thread *td,
2513151720Speter			  struct ofreebsd32_sigvec_args *uap)
2514151582Sps{
2515151582Sps	struct sigvec32 vec;
2516151582Sps	struct sigaction sa, osa, *sap;
2517151582Sps	int error;
2518151582Sps
2519151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
2520151582Sps		return (EINVAL);
2521151582Sps
2522151582Sps	if (uap->nsv) {
2523151582Sps		error = copyin(uap->nsv, &vec, sizeof(vec));
2524151582Sps		if (error)
2525151582Sps			return (error);
2526151582Sps		sa.sa_handler = PTRIN(vec.sv_handler);
2527151582Sps		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2528151582Sps		sa.sa_flags = vec.sv_flags;
2529151582Sps		sa.sa_flags ^= SA_RESTART;
2530151582Sps		sap = &sa;
2531151582Sps	} else
2532151582Sps		sap = NULL;
2533151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2534151582Sps	if (error == 0 && uap->osv != NULL) {
2535151582Sps		vec.sv_handler = PTROUT(osa.sa_handler);
2536151582Sps		SIG2OSIG(osa.sa_mask, vec.sv_mask);
2537151582Sps		vec.sv_flags = osa.sa_flags;
2538151582Sps		vec.sv_flags &= ~SA_NOCLDWAIT;
2539151582Sps		vec.sv_flags ^= SA_RESTART;
2540151582Sps		error = copyout(&vec, uap->osv, sizeof(vec));
2541151582Sps	}
2542151582Sps	return (error);
2543151582Sps}
2544151582Sps
2545151582Spsint
2546151720Speterofreebsd32_sigblock(struct thread *td,
2547151720Speter			    struct ofreebsd32_sigblock_args *uap)
2548151582Sps{
2549151582Sps	struct proc *p = td->td_proc;
2550151582Sps	sigset_t set;
2551151582Sps
2552151582Sps	OSIG2SIG(uap->mask, set);
2553151582Sps	SIG_CANTMASK(set);
2554151582Sps	PROC_LOCK(p);
2555151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2556151582Sps	SIGSETOR(td->td_sigmask, set);
2557151582Sps	PROC_UNLOCK(p);
2558151582Sps	return (0);
2559151582Sps}
2560151582Sps
2561151582Spsint
2562151720Speterofreebsd32_sigsetmask(struct thread *td,
2563151720Speter			      struct ofreebsd32_sigsetmask_args *uap)
2564151582Sps{
2565151582Sps	struct proc *p = td->td_proc;
2566151582Sps	sigset_t set;
2567151582Sps
2568151582Sps	OSIG2SIG(uap->mask, set);
2569151582Sps	SIG_CANTMASK(set);
2570151582Sps	PROC_LOCK(p);
2571151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2572151582Sps	SIGSETLO(td->td_sigmask, set);
2573151582Sps	signotify(td);
2574151582Sps	PROC_UNLOCK(p);
2575151582Sps	return (0);
2576151582Sps}
2577151582Sps
2578151582Spsint
2579151720Speterofreebsd32_sigsuspend(struct thread *td,
2580151720Speter			      struct ofreebsd32_sigsuspend_args *uap)
2581151582Sps{
2582151582Sps	struct proc *p = td->td_proc;
2583151582Sps	sigset_t mask;
2584151582Sps
2585151582Sps	PROC_LOCK(p);
2586151582Sps	td->td_oldsigmask = td->td_sigmask;
2587151582Sps	td->td_pflags |= TDP_OLDMASK;
2588151582Sps	OSIG2SIG(uap->mask, mask);
2589151582Sps	SIG_CANTMASK(mask);
2590151582Sps	SIGSETLO(td->td_sigmask, mask);
2591151582Sps	signotify(td);
2592151582Sps	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2593151582Sps		/* void */;
2594151582Sps	PROC_UNLOCK(p);
2595151582Sps	/* always return EINTR rather than ERESTART... */
2596151582Sps	return (EINTR);
2597151582Sps}
2598151582Sps
2599151582Spsstruct sigstack32 {
2600151582Sps	u_int32_t	ss_sp;
2601151582Sps	int		ss_onstack;
2602151582Sps};
2603151582Sps
2604151582Spsint
2605151720Speterofreebsd32_sigstack(struct thread *td,
2606151720Speter			    struct ofreebsd32_sigstack_args *uap)
2607151582Sps{
2608151582Sps	struct sigstack32 s32;
2609151582Sps	struct sigstack nss, oss;
2610170870Smjacob	int error = 0, unss;
2611151582Sps
2612151582Sps	if (uap->nss != NULL) {
2613151582Sps		error = copyin(uap->nss, &s32, sizeof(s32));
2614151582Sps		if (error)
2615151582Sps			return (error);
2616151582Sps		nss.ss_sp = PTRIN(s32.ss_sp);
2617151582Sps		CP(s32, nss, ss_onstack);
2618170870Smjacob		unss = 1;
2619170870Smjacob	} else {
2620170870Smjacob		unss = 0;
2621151582Sps	}
2622151582Sps	oss.ss_sp = td->td_sigstk.ss_sp;
2623151582Sps	oss.ss_onstack = sigonstack(cpu_getstack(td));
2624170870Smjacob	if (unss) {
2625151582Sps		td->td_sigstk.ss_sp = nss.ss_sp;
2626151582Sps		td->td_sigstk.ss_size = 0;
2627170870Smjacob		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2628151582Sps		td->td_pflags |= TDP_ALTSTACK;
2629151582Sps	}
2630151582Sps	if (uap->oss != NULL) {
2631151582Sps		s32.ss_sp = PTROUT(oss.ss_sp);
2632151582Sps		CP(oss, s32, ss_onstack);
2633151582Sps		error = copyout(&s32, uap->oss, sizeof(s32));
2634151582Sps	}
2635151582Sps	return (error);
2636151582Sps}
2637151582Sps#endif
2638151582Sps
2639151582Spsint
2640140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2641140481Sps{
2642140481Sps	struct timespec32 rmt32, rqt32;
2643140481Sps	struct timespec rmt, rqt;
2644140481Sps	int error;
2645140481Sps
2646151355Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2647140481Sps	if (error)
2648140481Sps		return (error);
2649140481Sps
2650140481Sps	CP(rqt32, rqt, tv_sec);
2651140481Sps	CP(rqt32, rqt, tv_nsec);
2652140481Sps
2653140481Sps	if (uap->rmtp &&
2654140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2655140481Sps		return (EFAULT);
2656140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
2657140481Sps	if (error && uap->rmtp) {
2658140481Sps		int error2;
2659140481Sps
2660140481Sps		CP(rmt, rmt32, tv_sec);
2661140481Sps		CP(rmt, rmt32, tv_nsec);
2662140481Sps
2663151355Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2664140481Sps		if (error2)
2665140481Sps			error = error2;
2666140481Sps	}
2667140481Sps	return (error);
2668140481Sps}
2669140481Sps
2670151357Spsint
2671151357Spsfreebsd32_clock_gettime(struct thread *td,
2672151357Sps			struct freebsd32_clock_gettime_args *uap)
2673151357Sps{
2674151357Sps	struct timespec	ats;
2675151357Sps	struct timespec32 ats32;
2676151357Sps	int error;
2677151357Sps
2678151357Sps	error = kern_clock_gettime(td, uap->clock_id, &ats);
2679151357Sps	if (error == 0) {
2680151357Sps		CP(ats, ats32, tv_sec);
2681151357Sps		CP(ats, ats32, tv_nsec);
2682151357Sps		error = copyout(&ats32, uap->tp, sizeof(ats32));
2683151357Sps	}
2684151357Sps	return (error);
2685151357Sps}
2686151357Sps
2687151357Spsint
2688151357Spsfreebsd32_clock_settime(struct thread *td,
2689151357Sps			struct freebsd32_clock_settime_args *uap)
2690151357Sps{
2691151357Sps	struct timespec	ats;
2692151357Sps	struct timespec32 ats32;
2693151357Sps	int error;
2694151357Sps
2695151357Sps	error = copyin(uap->tp, &ats32, sizeof(ats32));
2696151357Sps	if (error)
2697151357Sps		return (error);
2698151357Sps	CP(ats32, ats, tv_sec);
2699151357Sps	CP(ats32, ats, tv_nsec);
2700151357Sps
2701151357Sps	return (kern_clock_settime(td, uap->clock_id, &ats));
2702151357Sps}
2703151357Sps
2704151357Spsint
2705151357Spsfreebsd32_clock_getres(struct thread *td,
2706151357Sps		       struct freebsd32_clock_getres_args *uap)
2707151357Sps{
2708151357Sps	struct timespec	ts;
2709151357Sps	struct timespec32 ts32;
2710151357Sps	int error;
2711151357Sps
2712151357Sps	if (uap->tp == NULL)
2713151357Sps		return (0);
2714151357Sps	error = kern_clock_getres(td, uap->clock_id, &ts);
2715151357Sps	if (error == 0) {
2716151357Sps		CP(ts, ts32, tv_sec);
2717151357Sps		CP(ts, ts32, tv_nsec);
2718151357Sps		error = copyout(&ts32, uap->tp, sizeof(ts32));
2719151357Sps	}
2720151357Sps	return (error);
2721151357Sps}
2722151357Sps
2723162551Sdavidxuint
2724162551Sdavidxufreebsd32_thr_new(struct thread *td,
2725162551Sdavidxu		  struct freebsd32_thr_new_args *uap)
2726162551Sdavidxu{
2727162551Sdavidxu	struct thr_param32 param32;
2728162551Sdavidxu	struct thr_param param;
2729162551Sdavidxu	int error;
2730162551Sdavidxu
2731162551Sdavidxu	if (uap->param_size < 0 ||
2732162551Sdavidxu	    uap->param_size > sizeof(struct thr_param32))
2733162551Sdavidxu		return (EINVAL);
2734162551Sdavidxu	bzero(&param, sizeof(struct thr_param));
2735162551Sdavidxu	bzero(&param32, sizeof(struct thr_param32));
2736162551Sdavidxu	error = copyin(uap->param, &param32, uap->param_size);
2737162551Sdavidxu	if (error != 0)
2738162551Sdavidxu		return (error);
2739162551Sdavidxu	param.start_func = PTRIN(param32.start_func);
2740162551Sdavidxu	param.arg = PTRIN(param32.arg);
2741162551Sdavidxu	param.stack_base = PTRIN(param32.stack_base);
2742162551Sdavidxu	param.stack_size = param32.stack_size;
2743162551Sdavidxu	param.tls_base = PTRIN(param32.tls_base);
2744162551Sdavidxu	param.tls_size = param32.tls_size;
2745162551Sdavidxu	param.child_tid = PTRIN(param32.child_tid);
2746162551Sdavidxu	param.parent_tid = PTRIN(param32.parent_tid);
2747162551Sdavidxu	param.flags = param32.flags;
2748162551Sdavidxu	param.rtp = PTRIN(param32.rtp);
2749162551Sdavidxu	param.spare[0] = PTRIN(param32.spare[0]);
2750162551Sdavidxu	param.spare[1] = PTRIN(param32.spare[1]);
2751162551Sdavidxu	param.spare[2] = PTRIN(param32.spare[2]);
2752162551Sdavidxu
2753162551Sdavidxu	return (kern_thr_new(td, &param));
2754162551Sdavidxu}
2755162551Sdavidxu
2756162551Sdavidxuint
2757162551Sdavidxufreebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2758162551Sdavidxu{
2759162551Sdavidxu	struct timespec32 ts32;
2760162551Sdavidxu	struct timespec ts, *tsp;
2761162551Sdavidxu	int error;
2762162551Sdavidxu
2763162551Sdavidxu	error = 0;
2764162551Sdavidxu	tsp = NULL;
2765162551Sdavidxu	if (uap->timeout != NULL) {
2766162551Sdavidxu		error = copyin((const void *)uap->timeout, (void *)&ts32,
2767162551Sdavidxu		    sizeof(struct timespec32));
2768162551Sdavidxu		if (error != 0)
2769162551Sdavidxu			return (error);
2770162551Sdavidxu		ts.tv_sec = ts32.tv_sec;
2771162551Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2772162551Sdavidxu		tsp = &ts;
2773162551Sdavidxu	}
2774162551Sdavidxu	return (kern_thr_suspend(td, tsp));
2775162551Sdavidxu}
2776162551Sdavidxu
2777163018Sdavidxuvoid
2778163018Sdavidxusiginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2779163018Sdavidxu{
2780163018Sdavidxu	bzero(dst, sizeof(*dst));
2781163018Sdavidxu	dst->si_signo = src->si_signo;
2782163018Sdavidxu	dst->si_errno = src->si_errno;
2783163018Sdavidxu	dst->si_code = src->si_code;
2784163018Sdavidxu	dst->si_pid = src->si_pid;
2785163018Sdavidxu	dst->si_uid = src->si_uid;
2786163018Sdavidxu	dst->si_status = src->si_status;
2787184829Speter	dst->si_addr = (uintptr_t)src->si_addr;
2788163018Sdavidxu	dst->si_value.sigval_int = src->si_value.sival_int;
2789163018Sdavidxu	dst->si_timerid = src->si_timerid;
2790163018Sdavidxu	dst->si_overrun = src->si_overrun;
2791163018Sdavidxu}
2792163018Sdavidxu
2793163018Sdavidxuint
2794163018Sdavidxufreebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2795163018Sdavidxu{
2796163018Sdavidxu	struct timespec32 ts32;
2797163018Sdavidxu	struct timespec ts;
2798163018Sdavidxu	struct timespec *timeout;
2799163018Sdavidxu	sigset_t set;
2800163018Sdavidxu	ksiginfo_t ksi;
2801163018Sdavidxu	struct siginfo32 si32;
2802163018Sdavidxu	int error;
2803163018Sdavidxu
2804163018Sdavidxu	if (uap->timeout) {
2805163018Sdavidxu		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2806163018Sdavidxu		if (error)
2807163018Sdavidxu			return (error);
2808163018Sdavidxu		ts.tv_sec = ts32.tv_sec;
2809163018Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2810163018Sdavidxu		timeout = &ts;
2811163018Sdavidxu	} else
2812163018Sdavidxu		timeout = NULL;
2813163018Sdavidxu
2814163018Sdavidxu	error = copyin(uap->set, &set, sizeof(set));
2815163018Sdavidxu	if (error)
2816163018Sdavidxu		return (error);
2817163018Sdavidxu
2818163018Sdavidxu	error = kern_sigtimedwait(td, set, &ksi, timeout);
2819163018Sdavidxu	if (error)
2820163018Sdavidxu		return (error);
2821163018Sdavidxu
2822163018Sdavidxu	if (uap->info) {
2823163018Sdavidxu		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2824163018Sdavidxu		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2825163018Sdavidxu	}
2826163018Sdavidxu
2827163018Sdavidxu	if (error == 0)
2828163018Sdavidxu		td->td_retval[0] = ksi.ksi_signo;
2829163018Sdavidxu	return (error);
2830163018Sdavidxu}
2831163018Sdavidxu
2832163018Sdavidxu/*
2833163018Sdavidxu * MPSAFE
2834163018Sdavidxu */
2835163018Sdavidxuint
2836163018Sdavidxufreebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2837163018Sdavidxu{
2838163018Sdavidxu	ksiginfo_t ksi;
2839163018Sdavidxu	struct siginfo32 si32;
2840163018Sdavidxu	sigset_t set;
2841163018Sdavidxu	int error;
2842163018Sdavidxu
2843163018Sdavidxu	error = copyin(uap->set, &set, sizeof(set));
2844163018Sdavidxu	if (error)
2845163018Sdavidxu		return (error);
2846163018Sdavidxu
2847163018Sdavidxu	error = kern_sigtimedwait(td, set, &ksi, NULL);
2848163018Sdavidxu	if (error)
2849163018Sdavidxu		return (error);
2850163018Sdavidxu
2851163018Sdavidxu	if (uap->info) {
2852163018Sdavidxu		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2853163018Sdavidxu		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2854163018Sdavidxu	}
2855163018Sdavidxu	if (error == 0)
2856163018Sdavidxu		td->td_retval[0] = ksi.ksi_signo;
2857163018Sdavidxu	return (error);
2858163018Sdavidxu}
2859163018Sdavidxu
2860180433Sbrooksint
2861180433Sbrooksfreebsd32_cpuset_setid(struct thread *td,
2862180433Sbrooks    struct freebsd32_cpuset_setid_args *uap)
2863180433Sbrooks{
2864180433Sbrooks	struct cpuset_setid_args ap;
2865180433Sbrooks
2866180433Sbrooks	ap.which = uap->which;
2867180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2868180433Sbrooks	ap.setid = uap->setid;
2869180433Sbrooks
2870180436Sbrooks	return (cpuset_setid(td, &ap));
2871180433Sbrooks}
2872180433Sbrooks
2873180433Sbrooksint
2874180433Sbrooksfreebsd32_cpuset_getid(struct thread *td,
2875180433Sbrooks    struct freebsd32_cpuset_getid_args *uap)
2876180433Sbrooks{
2877180433Sbrooks	struct cpuset_getid_args ap;
2878180433Sbrooks
2879180433Sbrooks	ap.level = uap->level;
2880180433Sbrooks	ap.which = uap->which;
2881180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2882180433Sbrooks	ap.setid = uap->setid;
2883180433Sbrooks
2884180436Sbrooks	return (cpuset_getid(td, &ap));
2885180433Sbrooks}
2886180433Sbrooks
2887180433Sbrooksint
2888180433Sbrooksfreebsd32_cpuset_getaffinity(struct thread *td,
2889180433Sbrooks    struct freebsd32_cpuset_getaffinity_args *uap)
2890180433Sbrooks{
2891180433Sbrooks	struct cpuset_getaffinity_args ap;
2892180433Sbrooks
2893180433Sbrooks	ap.level = uap->level;
2894180433Sbrooks	ap.which = uap->which;
2895180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2896180433Sbrooks	ap.cpusetsize = uap->cpusetsize;
2897180433Sbrooks	ap.mask = uap->mask;
2898180433Sbrooks
2899180436Sbrooks	return (cpuset_getaffinity(td, &ap));
2900180433Sbrooks}
2901180433Sbrooks
2902180433Sbrooksint
2903180433Sbrooksfreebsd32_cpuset_setaffinity(struct thread *td,
2904180433Sbrooks    struct freebsd32_cpuset_setaffinity_args *uap)
2905180433Sbrooks{
2906180433Sbrooks	struct cpuset_setaffinity_args ap;
2907180433Sbrooks
2908180433Sbrooks	ap.level = uap->level;
2909180433Sbrooks	ap.which = uap->which;
2910180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2911180433Sbrooks	ap.cpusetsize = uap->cpusetsize;
2912180433Sbrooks	ap.mask = uap->mask;
2913180433Sbrooks
2914180436Sbrooks	return (cpuset_setaffinity(td, &ap));
2915180433Sbrooks}
2916180433Sbrooks
2917183188Sobrienint
2918183188Sobrienfreebsd32_nmount(struct thread *td,
2919183188Sobrien    struct freebsd32_nmount_args /* {
2920183188Sobrien    	struct iovec *iovp;
2921183188Sobrien    	unsigned int iovcnt;
2922183188Sobrien    	int flags;
2923183188Sobrien    } */ *uap)
2924183188Sobrien{
2925183188Sobrien	struct uio *auio;
2926189290Sjamie	int error;
2927183188Sobrien
2928195104Srwatson	AUDIT_ARG_FFLAGS(uap->flags);
2929183188Sobrien
2930183188Sobrien	/*
2931183188Sobrien	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2932183188Sobrien	 * userspace to set this flag, but we must filter it out if we want
2933183188Sobrien	 * MNT_UPDATE on the root file system to work.
2934183188Sobrien	 * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
2935183188Sobrien	 */
2936183188Sobrien	uap->flags &= ~MNT_ROOTFS;
2937183188Sobrien
2938183188Sobrien	/*
2939183188Sobrien	 * check that we have an even number of iovec's
2940183188Sobrien	 * and that we have at least two options.
2941183188Sobrien	 */
2942183188Sobrien	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2943183188Sobrien		return (EINVAL);
2944183188Sobrien
2945183188Sobrien	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2946183188Sobrien	if (error)
2947183188Sobrien		return (error);
2948189290Sjamie	error = vfs_donmount(td, uap->flags, auio);
2949183188Sobrien
2950183188Sobrien	free(auio, M_IOV);
2951183188Sobrien	return error;
2952183188Sobrien}
2953183188Sobrien
2954100384Speter#if 0
2955100384Speterint
2956119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2957100384Speter{
2958100384Speter	struct yyy32 *p32, s32;
2959100384Speter	struct yyy *p = NULL, s;
2960183044Sobrien	struct xxx_arg ap;
2961183044Sobrien	int error;
2962100384Speter
2963147654Sjhb	if (uap->zzz) {
2964147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
2965100384Speter		if (error)
2966100384Speter			return (error);
2967100384Speter		/* translate in */
2968147654Sjhb		p = &s;
2969100384Speter	}
2970147654Sjhb	error = kern_xxx(td, p);
2971100384Speter	if (error)
2972100384Speter		return (error);
2973147654Sjhb	if (uap->zzz) {
2974100384Speter		/* translate out */
2975100384Speter		error = copyout(&s32, p32, sizeof(s32));
2976100384Speter	}
2977100384Speter	return (error);
2978100384Speter}
2979100384Speter#endif
2980183365Sjhb
2981183365Sjhbint
2982183365Sjhbsyscall32_register(int *offset, struct sysent *new_sysent,
2983183365Sjhb    struct sysent *old_sysent)
2984183365Sjhb{
2985183365Sjhb	if (*offset == NO_SYSCALL) {
2986183365Sjhb		int i;
2987183365Sjhb
2988183365Sjhb		for (i = 1; i < SYS_MAXSYSCALL; ++i)
2989183365Sjhb			if (freebsd32_sysent[i].sy_call ==
2990183365Sjhb			    (sy_call_t *)lkmnosys)
2991183365Sjhb				break;
2992183365Sjhb		if (i == SYS_MAXSYSCALL)
2993183365Sjhb			return (ENFILE);
2994183365Sjhb		*offset = i;
2995183365Sjhb	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
2996183365Sjhb		return (EINVAL);
2997183365Sjhb	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
2998183365Sjhb	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
2999183365Sjhb		return (EEXIST);
3000183365Sjhb
3001183365Sjhb	*old_sysent = freebsd32_sysent[*offset];
3002183365Sjhb	freebsd32_sysent[*offset] = *new_sysent;
3003183365Sjhb	return 0;
3004183365Sjhb}
3005183365Sjhb
3006183365Sjhbint
3007183365Sjhbsyscall32_deregister(int *offset, struct sysent *old_sysent)
3008183365Sjhb{
3009183365Sjhb
3010183365Sjhb	if (*offset)
3011183365Sjhb		freebsd32_sysent[*offset] = *old_sysent;
3012183365Sjhb	return 0;
3013183365Sjhb}
3014183365Sjhb
3015183365Sjhbint
3016183365Sjhbsyscall32_module_handler(struct module *mod, int what, void *arg)
3017183365Sjhb{
3018183365Sjhb	struct syscall_module_data *data = (struct syscall_module_data*)arg;
3019183365Sjhb	modspecific_t ms;
3020183365Sjhb	int error;
3021183365Sjhb
3022183365Sjhb	switch (what) {
3023183365Sjhb	case MOD_LOAD:
3024183365Sjhb		error = syscall32_register(data->offset, data->new_sysent,
3025183365Sjhb		    &data->old_sysent);
3026183365Sjhb		if (error) {
3027183365Sjhb			/* Leave a mark so we know to safely unload below. */
3028183365Sjhb			data->offset = NULL;
3029183365Sjhb			return error;
3030183365Sjhb		}
3031183365Sjhb		ms.intval = *data->offset;
3032183365Sjhb		MOD_XLOCK;
3033183365Sjhb		module_setspecific(mod, &ms);
3034183365Sjhb		MOD_XUNLOCK;
3035183365Sjhb		if (data->chainevh)
3036183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
3037183365Sjhb		return (error);
3038183365Sjhb	case MOD_UNLOAD:
3039183365Sjhb		/*
3040183365Sjhb		 * MOD_LOAD failed, so just return without calling the
3041183365Sjhb		 * chained handler since we didn't pass along the MOD_LOAD
3042183365Sjhb		 * event.
3043183365Sjhb		 */
3044183365Sjhb		if (data->offset == NULL)
3045183365Sjhb			return (0);
3046183365Sjhb		if (data->chainevh) {
3047183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
3048183365Sjhb			if (error)
3049183365Sjhb				return (error);
3050183365Sjhb		}
3051185589Sjhb		error = syscall32_deregister(data->offset, &data->old_sysent);
3052183365Sjhb		return (error);
3053183365Sjhb	default:
3054183365Sjhb		error = EOPNOTSUPP;
3055183365Sjhb		if (data->chainevh)
3056183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
3057183365Sjhb		return (error);
3058183365Sjhb	}
3059183365Sjhb}
3060