freebsd32_misc.c revision 191673
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 191673 2009-04-29 21:14:15Z jamie $");
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
115191673Sjamieextern int jail_max_af_ips;
116191673Sjamie
117174377Sjhbstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
118174377Sjhbstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
119174377Sjhb
120100384Speterint
121119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
122100384Speter{
123127140Sjhb	int error, status;
124127140Sjhb	struct rusage32 ru32;
125136152Sjhb	struct rusage ru, *rup;
126100384Speter
127136152Sjhb	if (uap->rusage != NULL)
128136152Sjhb		rup = &ru;
129136152Sjhb	else
130136152Sjhb		rup = NULL;
131136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
132100384Speter	if (error)
133100384Speter		return (error);
134127140Sjhb	if (uap->status != NULL)
135127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
136127140Sjhb	if (uap->rusage != NULL && error == 0) {
137100384Speter		TV_CP(ru, ru32, ru_utime);
138100384Speter		TV_CP(ru, ru32, ru_stime);
139100384Speter		CP(ru, ru32, ru_maxrss);
140100384Speter		CP(ru, ru32, ru_ixrss);
141100384Speter		CP(ru, ru32, ru_idrss);
142100384Speter		CP(ru, ru32, ru_isrss);
143100384Speter		CP(ru, ru32, ru_minflt);
144100384Speter		CP(ru, ru32, ru_majflt);
145100384Speter		CP(ru, ru32, ru_nswap);
146100384Speter		CP(ru, ru32, ru_inblock);
147100384Speter		CP(ru, ru32, ru_oublock);
148100384Speter		CP(ru, ru32, ru_msgsnd);
149100384Speter		CP(ru, ru32, ru_msgrcv);
150100384Speter		CP(ru, ru32, ru_nsignals);
151100384Speter		CP(ru, ru32, ru_nvcsw);
152100384Speter		CP(ru, ru32, ru_nivcsw);
153127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
154100384Speter	}
155100384Speter	return (error);
156100384Speter}
157100384Speter
158128597Smarcel#ifdef COMPAT_FREEBSD4
159174526Sjhbstatic void
160100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
161100384Speter{
162172003Sjhb
163174424Sscottl	statfs_scale_blocks(in, INT32_MAX);
164156266Sps	bzero(out, sizeof(*out));
165100384Speter	CP(*in, *out, f_bsize);
166172003Sjhb	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
167100384Speter	CP(*in, *out, f_blocks);
168100384Speter	CP(*in, *out, f_bfree);
169100384Speter	CP(*in, *out, f_bavail);
170172003Sjhb	out->f_files = MIN(in->f_files, INT32_MAX);
171174526Sjhb	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
172100384Speter	CP(*in, *out, f_fsid);
173100384Speter	CP(*in, *out, f_owner);
174100384Speter	CP(*in, *out, f_type);
175100384Speter	CP(*in, *out, f_flags);
176174526Sjhb	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
177174526Sjhb	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
178156266Sps	strlcpy(out->f_fstypename,
179156266Sps	      in->f_fstypename, MFSNAMELEN);
180156266Sps	strlcpy(out->f_mntonname,
181156266Sps	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
182174526Sjhb	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
183174526Sjhb	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
184156266Sps	strlcpy(out->f_mntfromname,
185156266Sps	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
186100384Speter}
187128597Smarcel#endif
188100384Speter
189128597Smarcel#ifdef COMPAT_FREEBSD4
190100384Speterint
191128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
192100384Speter{
193147178Spjd	struct statfs *buf, *sp;
194147178Spjd	struct statfs32 stat32;
195147178Spjd	size_t count, size;
196100384Speter	int error;
197100384Speter
198147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
199147178Spjd	size = count * sizeof(struct statfs);
200147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
201147302Spjd	if (size > 0) {
202100384Speter		count = td->td_retval[0];
203147178Spjd		sp = buf;
204147178Spjd		while (count > 0 && error == 0) {
205174526Sjhb			copy_statfs(sp, &stat32);
206147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
207147178Spjd			sp++;
208147178Spjd			uap->buf++;
209147178Spjd			count--;
210100384Speter		}
211147178Spjd		free(buf, M_TEMP);
212100384Speter	}
213100384Speter	return (error);
214100384Speter}
215128597Smarcel#endif
216100384Speter
217100384Speterint
218119333Speterfreebsd32_sigaltstack(struct thread *td,
219119333Speter		      struct freebsd32_sigaltstack_args *uap)
220100384Speter{
221113859Sjhb	struct sigaltstack32 s32;
222113859Sjhb	struct sigaltstack ss, oss, *ssp;
223100384Speter	int error;
224100384Speter
225113859Sjhb	if (uap->ss != NULL) {
226113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
227100384Speter		if (error)
228100384Speter			return (error);
229113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
230113859Sjhb		CP(s32, ss, ss_size);
231113859Sjhb		CP(s32, ss, ss_flags);
232113859Sjhb		ssp = &ss;
233113859Sjhb	} else
234113859Sjhb		ssp = NULL;
235113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
236113859Sjhb	if (error == 0 && uap->oss != NULL) {
237113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
238113859Sjhb		CP(oss, s32, ss_size);
239113859Sjhb		CP(oss, s32, ss_flags);
240113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
241100384Speter	}
242100384Speter	return (error);
243100384Speter}
244100384Speter
245142059Sjhb/*
246142059Sjhb * Custom version of exec_copyin_args() so that we can translate
247142059Sjhb * the pointers.
248142059Sjhb */
249142059Sjhbstatic int
250142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
251142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
252100384Speter{
253142059Sjhb	char *argp, *envp;
254142059Sjhb	u_int32_t *p32, arg;
255142059Sjhb	size_t length;
256100384Speter	int error;
257100384Speter
258142059Sjhb	bzero(args, sizeof(*args));
259142059Sjhb	if (argv == NULL)
260142059Sjhb		return (EFAULT);
261100384Speter
262142059Sjhb	/*
263142059Sjhb	 * Allocate temporary demand zeroed space for argument and
264142059Sjhb	 *	environment strings
265142059Sjhb	 */
266147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
267147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
268142059Sjhb	if (args->buf == NULL)
269142059Sjhb		return (ENOMEM);
270142059Sjhb	args->begin_argv = args->buf;
271142059Sjhb	args->endp = args->begin_argv;
272142059Sjhb	args->stringspace = ARG_MAX;
273142059Sjhb
274142059Sjhb	/*
275142059Sjhb	 * Copy the file name.
276142059Sjhb	 */
277177789Skib	if (fname != NULL) {
278177789Skib		args->fname = args->buf + ARG_MAX;
279177789Skib		error = (segflg == UIO_SYSSPACE) ?
280177789Skib		    copystr(fname, args->fname, PATH_MAX, &length) :
281177789Skib		    copyinstr(fname, args->fname, PATH_MAX, &length);
282177789Skib		if (error != 0)
283177789Skib			goto err_exit;
284177789Skib	} else
285177789Skib		args->fname = NULL;
286142059Sjhb
287142059Sjhb	/*
288142059Sjhb	 * extract arguments first
289142059Sjhb	 */
290142059Sjhb	p32 = argv;
291142059Sjhb	for (;;) {
292142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
293142059Sjhb		if (error)
294156440Sups			goto err_exit;
295142059Sjhb		if (arg == 0)
296142059Sjhb			break;
297142059Sjhb		argp = PTRIN(arg);
298142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
299142059Sjhb		if (error) {
300142059Sjhb			if (error == ENAMETOOLONG)
301156440Sups				error = E2BIG;
302156440Sups			goto err_exit;
303142059Sjhb		}
304142059Sjhb		args->stringspace -= length;
305142059Sjhb		args->endp += length;
306142059Sjhb		args->argc++;
307100384Speter	}
308142059Sjhb
309142059Sjhb	args->begin_envv = args->endp;
310142059Sjhb
311142059Sjhb	/*
312142059Sjhb	 * extract environment strings
313142059Sjhb	 */
314142059Sjhb	if (envv) {
315142059Sjhb		p32 = envv;
316142059Sjhb		for (;;) {
317100384Speter			error = copyin(p32++, &arg, sizeof(arg));
318100384Speter			if (error)
319156440Sups				goto err_exit;
320142059Sjhb			if (arg == 0)
321142059Sjhb				break;
322142059Sjhb			envp = PTRIN(arg);
323142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
324142059Sjhb			    &length);
325142059Sjhb			if (error) {
326142059Sjhb				if (error == ENAMETOOLONG)
327156440Sups					error = E2BIG;
328156440Sups				goto err_exit;
329142059Sjhb			}
330142059Sjhb			args->stringspace -= length;
331142059Sjhb			args->endp += length;
332142059Sjhb			args->envc++;
333142059Sjhb		}
334100384Speter	}
335100384Speter
336142059Sjhb	return (0);
337156440Sups
338156440Supserr_exit:
339156440Sups	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
340156440Sups	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
341156440Sups	args->buf = NULL;
342156440Sups	return (error);
343100384Speter}
344100384Speter
345142059Sjhbint
346142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
347142059Sjhb{
348142059Sjhb	struct image_args eargs;
349142059Sjhb	int error;
350142059Sjhb
351142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
352142059Sjhb	    uap->argv, uap->envv);
353142059Sjhb	if (error == 0)
354142059Sjhb		error = kern_execve(td, &eargs, NULL);
355142059Sjhb	return (error);
356142059Sjhb}
357142059Sjhb
358177789Skibint
359177789Skibfreebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
360177789Skib{
361177789Skib	struct image_args eargs;
362177789Skib	int error;
363177789Skib
364177789Skib	error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
365177789Skib	    uap->argv, uap->envv);
366177789Skib	if (error == 0) {
367177789Skib		eargs.fd = uap->fd;
368177789Skib		error = kern_execve(td, &eargs, NULL);
369177789Skib	}
370177789Skib	return (error);
371177789Skib}
372177789Skib
373114987Speter#ifdef __ia64__
374100384Speterstatic int
375119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
376119333Speter		       int prot, int fd, off_t pos)
377100384Speter{
378100384Speter	vm_map_t map;
379100384Speter	vm_map_entry_t entry;
380100384Speter	int rv;
381100384Speter
382100384Speter	map = &td->td_proc->p_vmspace->vm_map;
383100384Speter	if (fd != -1)
384100384Speter		prot |= VM_PROT_WRITE;
385100384Speter
386100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
387100384Speter		if ((entry->protection & prot) != prot) {
388100384Speter			rv = vm_map_protect(map,
389100384Speter					    trunc_page(start),
390100384Speter					    round_page(end),
391100384Speter					    entry->protection | prot,
392100384Speter					    FALSE);
393100384Speter			if (rv != KERN_SUCCESS)
394100384Speter				return (EINVAL);
395100384Speter		}
396100384Speter	} else {
397100384Speter		vm_offset_t addr = trunc_page(start);
398100384Speter		rv = vm_map_find(map, 0, 0,
399100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
400100384Speter				 VM_PROT_ALL, 0);
401100384Speter		if (rv != KERN_SUCCESS)
402100384Speter			return (EINVAL);
403100384Speter	}
404100384Speter
405100384Speter	if (fd != -1) {
406100384Speter		struct pread_args r;
407107849Salfred		r.fd = fd;
408107849Salfred		r.buf = (void *) start;
409107849Salfred		r.nbyte = end - start;
410107849Salfred		r.offset = pos;
411100384Speter		return (pread(td, &r));
412100384Speter	} else {
413100384Speter		while (start < end) {
414100384Speter			subyte((void *) start, 0);
415100384Speter			start++;
416100384Speter		}
417100384Speter		return (0);
418100384Speter	}
419100384Speter}
420114987Speter#endif
421100384Speter
422100384Speterint
423119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
424100384Speter{
425100384Speter	struct mmap_args ap;
426107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
427107849Salfred	vm_size_t len	 = uap->len;
428107849Salfred	int prot	 = uap->prot;
429107849Salfred	int flags	 = uap->flags;
430107849Salfred	int fd		 = uap->fd;
431107849Salfred	off_t pos	 = (uap->poslo
432107849Salfred			    | ((off_t)uap->poshi << 32));
433114987Speter#ifdef __ia64__
434100384Speter	vm_size_t pageoff;
435100384Speter	int error;
436100384Speter
437100384Speter	/*
438100384Speter	 * Attempt to handle page size hassles.
439100384Speter	 */
440100384Speter	pageoff = (pos & PAGE_MASK);
441100384Speter	if (flags & MAP_FIXED) {
442100384Speter		vm_offset_t start, end;
443100384Speter		start = addr;
444100384Speter		end = addr + len;
445100384Speter
446100384Speter		if (start != trunc_page(start)) {
447119333Speter			error = freebsd32_mmap_partial(td, start,
448119333Speter						       round_page(start), prot,
449119333Speter						       fd, pos);
450100384Speter			if (fd != -1)
451100384Speter				pos += round_page(start) - start;
452100384Speter			start = round_page(start);
453100384Speter		}
454100384Speter		if (end != round_page(end)) {
455100384Speter			vm_offset_t t = trunc_page(end);
456119333Speter			error = freebsd32_mmap_partial(td, t, end,
457100384Speter						  prot, fd,
458100384Speter						  pos + t - start);
459100384Speter			end = trunc_page(end);
460100384Speter		}
461100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
462100384Speter			/*
463100384Speter			 * We can't map this region at all. The specified
464100384Speter			 * address doesn't have the same alignment as the file
465100384Speter			 * position. Fake the mapping by simply reading the
466100384Speter			 * entire region into memory. First we need to make
467100384Speter			 * sure the region exists.
468100384Speter			 */
469100384Speter			vm_map_t map;
470100384Speter			struct pread_args r;
471100384Speter			int rv;
472100384Speter
473100384Speter			prot |= VM_PROT_WRITE;
474100384Speter			map = &td->td_proc->p_vmspace->vm_map;
475100384Speter			rv = vm_map_remove(map, start, end);
476169181Salc			if (rv != KERN_SUCCESS)
477100384Speter				return (EINVAL);
478100384Speter			rv = vm_map_find(map, 0, 0,
479100384Speter					 &start, end - start, FALSE,
480100384Speter					 prot, VM_PROT_ALL, 0);
481100384Speter			if (rv != KERN_SUCCESS)
482100384Speter				return (EINVAL);
483107849Salfred			r.fd = fd;
484107849Salfred			r.buf = (void *) start;
485107849Salfred			r.nbyte = end - start;
486107849Salfred			r.offset = pos;
487100384Speter			error = pread(td, &r);
488100384Speter			if (error)
489100384Speter				return (error);
490100384Speter
491100384Speter			td->td_retval[0] = addr;
492100384Speter			return (0);
493100384Speter		}
494100384Speter		if (end == start) {
495100384Speter			/*
496100384Speter			 * After dealing with the ragged ends, there
497100384Speter			 * might be none left.
498100384Speter			 */
499100384Speter			td->td_retval[0] = addr;
500100384Speter			return (0);
501100384Speter		}
502100384Speter		addr = start;
503100384Speter		len = end - start;
504100384Speter	}
505114987Speter#endif
506100384Speter
507107849Salfred	ap.addr = (void *) addr;
508107849Salfred	ap.len = len;
509107849Salfred	ap.prot = prot;
510107849Salfred	ap.flags = flags;
511107849Salfred	ap.fd = fd;
512107849Salfred	ap.pos = pos;
513100384Speter
514100384Speter	return (mmap(td, &ap));
515100384Speter}
516100384Speter
517171215Speter#ifdef COMPAT_FREEBSD6
518171215Speterint
519171215Speterfreebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
520171215Speter{
521171215Speter	struct freebsd32_mmap_args ap;
522171215Speter
523171215Speter	ap.addr = uap->addr;
524171215Speter	ap.len = uap->len;
525171215Speter	ap.prot = uap->prot;
526171215Speter	ap.flags = uap->flags;
527171215Speter	ap.fd = uap->fd;
528171215Speter	ap.poslo = uap->poslo;
529171215Speter	ap.poshi = uap->poshi;
530171215Speter
531171215Speter	return (freebsd32_mmap(td, &ap));
532171215Speter}
533171215Speter#endif
534171215Speter
535100384Speterint
536119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
537100384Speter{
538142059Sjhb	struct itimerval itv, oitv, *itvp;
539142059Sjhb	struct itimerval32 i32;
540100384Speter	int error;
541100384Speter
542142059Sjhb	if (uap->itv != NULL) {
543142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
544100384Speter		if (error)
545100384Speter			return (error);
546142059Sjhb		TV_CP(i32, itv, it_interval);
547142059Sjhb		TV_CP(i32, itv, it_value);
548142059Sjhb		itvp = &itv;
549142059Sjhb	} else
550142059Sjhb		itvp = NULL;
551142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
552142059Sjhb	if (error || uap->oitv == NULL)
553100384Speter		return (error);
554142059Sjhb	TV_CP(oitv, i32, it_interval);
555142059Sjhb	TV_CP(oitv, i32, it_value);
556142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
557100384Speter}
558100384Speter
559100384Speterint
560125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
561125171Speter{
562142059Sjhb	struct itimerval itv;
563142059Sjhb	struct itimerval32 i32;
564125171Speter	int error;
565125171Speter
566142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
567142059Sjhb	if (error || uap->itv == NULL)
568125171Speter		return (error);
569142059Sjhb	TV_CP(itv, i32, it_interval);
570142059Sjhb	TV_CP(itv, i32, it_value);
571142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
572125171Speter}
573125171Speter
574125171Speterint
575119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
576100384Speter{
577142059Sjhb	struct timeval32 tv32;
578142059Sjhb	struct timeval tv, *tvp;
579100384Speter	int error;
580100384Speter
581142059Sjhb	if (uap->tv != NULL) {
582142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
583100384Speter		if (error)
584100384Speter			return (error);
585142059Sjhb		CP(tv32, tv, tv_sec);
586142059Sjhb		CP(tv32, tv, tv_usec);
587142059Sjhb		tvp = &tv;
588142059Sjhb	} else
589142059Sjhb		tvp = NULL;
590100384Speter	/*
591100384Speter	 * XXX big-endian needs to convert the fd_sets too.
592142059Sjhb	 * XXX Do pointers need PTRIN()?
593100384Speter	 */
594142059Sjhb	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
595100384Speter}
596100384Speter
597146950Sps/*
598146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
599146950Sps */
600146950Spsstatic int
601146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
602146950Sps{
603146950Sps	struct freebsd32_kevent_args *uap;
604146950Sps	struct kevent32	ks32[KQ_NEVENTS];
605146950Sps	int i, error = 0;
606146950Sps
607146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
608146950Sps	uap = (struct freebsd32_kevent_args *)arg;
609146950Sps
610146950Sps	for (i = 0; i < count; i++) {
611146950Sps		CP(kevp[i], ks32[i], ident);
612146950Sps		CP(kevp[i], ks32[i], filter);
613146950Sps		CP(kevp[i], ks32[i], flags);
614146950Sps		CP(kevp[i], ks32[i], fflags);
615146950Sps		CP(kevp[i], ks32[i], data);
616146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
617146950Sps	}
618146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
619146950Sps	if (error == 0)
620146950Sps		uap->eventlist += count;
621146950Sps	return (error);
622146950Sps}
623146950Sps
624146950Sps/*
625146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
626146950Sps */
627146950Spsstatic int
628146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
629146950Sps{
630146950Sps	struct freebsd32_kevent_args *uap;
631146950Sps	struct kevent32	ks32[KQ_NEVENTS];
632146950Sps	int i, error = 0;
633146950Sps
634146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
635146950Sps	uap = (struct freebsd32_kevent_args *)arg;
636146950Sps
637146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
638146950Sps	if (error)
639146950Sps		goto done;
640146950Sps	uap->changelist += count;
641146950Sps
642146950Sps	for (i = 0; i < count; i++) {
643146950Sps		CP(ks32[i], kevp[i], ident);
644146950Sps		CP(ks32[i], kevp[i], filter);
645146950Sps		CP(ks32[i], kevp[i], flags);
646146950Sps		CP(ks32[i], kevp[i], fflags);
647146950Sps		CP(ks32[i], kevp[i], data);
648146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
649146950Sps	}
650146950Spsdone:
651146950Sps	return (error);
652146950Sps}
653146950Sps
654100384Speterint
655119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
656114987Speter{
657114987Speter	struct timespec32 ts32;
658142934Sps	struct timespec ts, *tsp;
659146950Sps	struct kevent_copyops k_ops = { uap,
660146950Sps					freebsd32_kevent_copyout,
661146950Sps					freebsd32_kevent_copyin};
662146950Sps	int error;
663114987Speter
664114987Speter
665114987Speter	if (uap->timeout) {
666114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
667114987Speter		if (error)
668114987Speter			return (error);
669114987Speter		CP(ts32, ts, tv_sec);
670114987Speter		CP(ts32, ts, tv_nsec);
671142934Sps		tsp = &ts;
672142934Sps	} else
673142934Sps		tsp = NULL;
674146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
675146950Sps	    &k_ops, tsp);
676142934Sps	return (error);
677114987Speter}
678114987Speter
679114987Speterint
680119333Speterfreebsd32_gettimeofday(struct thread *td,
681119333Speter		       struct freebsd32_gettimeofday_args *uap)
682100384Speter{
683123425Speter	struct timeval atv;
684123425Speter	struct timeval32 atv32;
685123425Speter	struct timezone rtz;
686123425Speter	int error = 0;
687100384Speter
688123425Speter	if (uap->tp) {
689123425Speter		microtime(&atv);
690123425Speter		CP(atv, atv32, tv_sec);
691123425Speter		CP(atv, atv32, tv_usec);
692123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
693100384Speter	}
694123425Speter	if (error == 0 && uap->tzp != NULL) {
695123425Speter		rtz.tz_minuteswest = tz_minuteswest;
696123425Speter		rtz.tz_dsttime = tz_dsttime;
697123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
698100384Speter	}
699100384Speter	return (error);
700100384Speter}
701100384Speter
702100384Speterint
703119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
704100384Speter{
705136152Sjhb	struct rusage32 s32;
706136152Sjhb	struct rusage s;
707100384Speter	int error;
708100384Speter
709136152Sjhb	error = kern_getrusage(td, uap->who, &s);
710100384Speter	if (error)
711100384Speter		return (error);
712136152Sjhb	if (uap->rusage != NULL) {
713100384Speter		TV_CP(s, s32, ru_utime);
714100384Speter		TV_CP(s, s32, ru_stime);
715100384Speter		CP(s, s32, ru_maxrss);
716100384Speter		CP(s, s32, ru_ixrss);
717100384Speter		CP(s, s32, ru_idrss);
718100384Speter		CP(s, s32, ru_isrss);
719100384Speter		CP(s, s32, ru_minflt);
720100384Speter		CP(s, s32, ru_majflt);
721100384Speter		CP(s, s32, ru_nswap);
722100384Speter		CP(s, s32, ru_inblock);
723100384Speter		CP(s, s32, ru_oublock);
724100384Speter		CP(s, s32, ru_msgsnd);
725100384Speter		CP(s, s32, ru_msgrcv);
726100384Speter		CP(s, s32, ru_nsignals);
727100384Speter		CP(s, s32, ru_nvcsw);
728100384Speter		CP(s, s32, ru_nivcsw);
729136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
730100384Speter	}
731100384Speter	return (error);
732100384Speter}
733100384Speter
734144450Sjhbstatic int
735144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
736100384Speter{
737144450Sjhb	struct iovec32 iov32;
738144450Sjhb	struct iovec *iov;
739144450Sjhb	struct uio *uio;
740144450Sjhb	u_int iovlen;
741144450Sjhb	int error, i;
742100384Speter
743144450Sjhb	*uiop = NULL;
744144450Sjhb	if (iovcnt > UIO_MAXIOV)
745100384Speter		return (EINVAL);
746144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
747144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
748144450Sjhb	iov = (struct iovec *)(uio + 1);
749144450Sjhb	for (i = 0; i < iovcnt; i++) {
750144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
751144450Sjhb		if (error) {
752144450Sjhb			free(uio, M_IOV);
753144450Sjhb			return (error);
754144450Sjhb		}
755144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
756144450Sjhb		iov[i].iov_len = iov32.iov_len;
757100384Speter	}
758144450Sjhb	uio->uio_iov = iov;
759144450Sjhb	uio->uio_iovcnt = iovcnt;
760144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
761144450Sjhb	uio->uio_offset = -1;
762144450Sjhb	uio->uio_resid = 0;
763144450Sjhb	for (i = 0; i < iovcnt; i++) {
764144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
765144450Sjhb			free(uio, M_IOV);
766144450Sjhb			return (EINVAL);
767144450Sjhb		}
768144450Sjhb		uio->uio_resid += iov->iov_len;
769144450Sjhb		iov++;
770144450Sjhb	}
771144450Sjhb	*uiop = uio;
772144450Sjhb	return (0);
773144450Sjhb}
774100384Speter
775144450Sjhbint
776144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
777144450Sjhb{
778144450Sjhb	struct uio *auio;
779144450Sjhb	int error;
780100384Speter
781144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
782144450Sjhb	if (error)
783144450Sjhb		return (error);
784144450Sjhb	error = kern_readv(td, uap->fd, auio);
785144450Sjhb	free(auio, M_IOV);
786100384Speter	return (error);
787100384Speter}
788100384Speter
789100384Speterint
790119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
791100384Speter{
792144450Sjhb	struct uio *auio;
793144450Sjhb	int error;
794100384Speter
795144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
796144450Sjhb	if (error)
797144450Sjhb		return (error);
798144450Sjhb	error = kern_writev(td, uap->fd, auio);
799144450Sjhb	free(auio, M_IOV);
800100384Speter	return (error);
801100384Speter}
802100384Speter
803100384Speterint
804147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
805147813Sjhb{
806147813Sjhb	struct uio *auio;
807147813Sjhb	int error;
808147813Sjhb
809147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
810147813Sjhb	if (error)
811147813Sjhb		return (error);
812147813Sjhb	error = kern_preadv(td, uap->fd, auio, uap->offset);
813147813Sjhb	free(auio, M_IOV);
814147813Sjhb	return (error);
815147813Sjhb}
816147813Sjhb
817147813Sjhbint
818147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
819147813Sjhb{
820147813Sjhb	struct uio *auio;
821147813Sjhb	int error;
822147813Sjhb
823147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
824147813Sjhb	if (error)
825147813Sjhb		return (error);
826147813Sjhb	error = kern_pwritev(td, uap->fd, auio, uap->offset);
827147813Sjhb	free(auio, M_IOV);
828147813Sjhb	return (error);
829147813Sjhb}
830147813Sjhb
831151359Spsstatic int
832151909Spsfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
833151359Sps    int error)
834151359Sps{
835151359Sps	struct iovec32 iov32;
836151909Sps	struct iovec *iov;
837151909Sps	u_int iovlen;
838151359Sps	int i;
839151359Sps
840151909Sps	*iovp = NULL;
841151359Sps	if (iovcnt > UIO_MAXIOV)
842151359Sps		return (error);
843151359Sps	iovlen = iovcnt * sizeof(struct iovec);
844151909Sps	iov = malloc(iovlen, M_IOV, M_WAITOK);
845151359Sps	for (i = 0; i < iovcnt; i++) {
846151909Sps		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
847151359Sps		if (error) {
848151909Sps			free(iov, M_IOV);
849151359Sps			return (error);
850151359Sps		}
851151909Sps		iov[i].iov_base = PTRIN(iov32.iov_base);
852151909Sps		iov[i].iov_len = iov32.iov_len;
853151359Sps	}
854151909Sps	*iovp = iov;
855151359Sps	return (0);
856151359Sps}
857151359Sps
858151359Spsstatic int
859151359Spsfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
860151359Sps{
861151359Sps	struct msghdr32 m32;
862151359Sps	int error;
863151359Sps
864151359Sps	error = copyin(msg32, &m32, sizeof(m32));
865151359Sps	if (error)
866151359Sps		return (error);
867151359Sps	msg->msg_name = PTRIN(m32.msg_name);
868151359Sps	msg->msg_namelen = m32.msg_namelen;
869151359Sps	msg->msg_iov = PTRIN(m32.msg_iov);
870151359Sps	msg->msg_iovlen = m32.msg_iovlen;
871151359Sps	msg->msg_control = PTRIN(m32.msg_control);
872151359Sps	msg->msg_controllen = m32.msg_controllen;
873151359Sps	msg->msg_flags = m32.msg_flags;
874151909Sps	return (0);
875151359Sps}
876151359Sps
877151359Spsstatic int
878151359Spsfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
879151359Sps{
880151359Sps	struct msghdr32 m32;
881151359Sps	int error;
882151359Sps
883151359Sps	m32.msg_name = PTROUT(msg->msg_name);
884151359Sps	m32.msg_namelen = msg->msg_namelen;
885151359Sps	m32.msg_iov = PTROUT(msg->msg_iov);
886151359Sps	m32.msg_iovlen = msg->msg_iovlen;
887151359Sps	m32.msg_control = PTROUT(msg->msg_control);
888151359Sps	m32.msg_controllen = msg->msg_controllen;
889151359Sps	m32.msg_flags = msg->msg_flags;
890151359Sps	error = copyout(&m32, msg32, sizeof(m32));
891151359Sps	return (error);
892151359Sps}
893151359Sps
894151909Sps#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
895151909Sps#define FREEBSD32_ALIGN(p)	\
896151909Sps	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
897151909Sps#define	FREEBSD32_CMSG_SPACE(l)	\
898151909Sps	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
899151909Sps
900151909Sps#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
901151909Sps				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
902151909Spsstatic int
903151909Spsfreebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
904151909Sps{
905151909Sps	struct cmsghdr *cm;
906151909Sps	void *data;
907151909Sps	socklen_t clen, datalen;
908151909Sps	int error;
909151909Sps	caddr_t ctlbuf;
910151909Sps	int len, maxlen, copylen;
911151909Sps	struct mbuf *m;
912151909Sps	error = 0;
913151909Sps
914151909Sps	len    = msg->msg_controllen;
915151909Sps	maxlen = msg->msg_controllen;
916151909Sps	msg->msg_controllen = 0;
917151909Sps
918151909Sps	m = control;
919151909Sps	ctlbuf = msg->msg_control;
920151909Sps
921151909Sps	while (m && len > 0) {
922151909Sps		cm = mtod(m, struct cmsghdr *);
923151909Sps		clen = m->m_len;
924151909Sps
925151909Sps		while (cm != NULL) {
926151909Sps
927151909Sps			if (sizeof(struct cmsghdr) > clen ||
928151909Sps			    cm->cmsg_len > clen) {
929151909Sps				error = EINVAL;
930151909Sps				break;
931151909Sps			}
932151909Sps
933151909Sps			data   = CMSG_DATA(cm);
934151909Sps			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
935151909Sps
936151909Sps			/* Adjust message length */
937151909Sps			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
938151909Sps			    datalen;
939151909Sps
940151909Sps
941151909Sps			/* Copy cmsghdr */
942151909Sps			copylen = sizeof(struct cmsghdr);
943151909Sps			if (len < copylen) {
944151909Sps				msg->msg_flags |= MSG_CTRUNC;
945151909Sps				copylen = len;
946151909Sps			}
947151909Sps
948151909Sps			error = copyout(cm,ctlbuf,copylen);
949151909Sps			if (error)
950151909Sps				goto exit;
951151909Sps
952151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
953151909Sps			len    -= FREEBSD32_ALIGN(copylen);
954151909Sps
955151909Sps			if (len <= 0)
956151909Sps				break;
957151909Sps
958151909Sps			/* Copy data */
959151909Sps			copylen = datalen;
960151909Sps			if (len < copylen) {
961151909Sps				msg->msg_flags |= MSG_CTRUNC;
962151909Sps				copylen = len;
963151909Sps			}
964151909Sps
965151909Sps			error = copyout(data,ctlbuf,copylen);
966151909Sps			if (error)
967151909Sps				goto exit;
968151909Sps
969151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
970151909Sps			len    -= FREEBSD32_ALIGN(copylen);
971151909Sps
972151909Sps			if (CMSG_SPACE(datalen) < clen) {
973151909Sps				clen -= CMSG_SPACE(datalen);
974151909Sps				cm = (struct cmsghdr *)
975151909Sps					((caddr_t)cm + CMSG_SPACE(datalen));
976151909Sps			} else {
977151909Sps				clen = 0;
978151909Sps				cm = NULL;
979151909Sps			}
980151909Sps		}
981151909Sps		m = m->m_next;
982151909Sps	}
983151909Sps
984151909Sps	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
985151909Sps
986151909Spsexit:
987151909Sps	return (error);
988151909Sps
989151909Sps}
990151909Sps
991147813Sjhbint
992151359Spsfreebsd32_recvmsg(td, uap)
993151359Sps	struct thread *td;
994151359Sps	struct freebsd32_recvmsg_args /* {
995151359Sps		int	s;
996151359Sps		struct	msghdr32 *msg;
997151359Sps		int	flags;
998151359Sps	} */ *uap;
999151359Sps{
1000151359Sps	struct msghdr msg;
1001151359Sps	struct msghdr32 m32;
1002151359Sps	struct iovec *uiov, *iov;
1003151909Sps	struct mbuf *control = NULL;
1004151909Sps	struct mbuf **controlp;
1005151909Sps
1006151359Sps	int error;
1007151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1008151359Sps	if (error)
1009151359Sps		return (error);
1010151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1011151359Sps	if (error)
1012151359Sps		return (error);
1013160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1014160246Sjhb	    EMSGSIZE);
1015151359Sps	if (error)
1016151359Sps		return (error);
1017151359Sps	msg.msg_flags = uap->flags;
1018151359Sps	uiov = msg.msg_iov;
1019151359Sps	msg.msg_iov = iov;
1020151909Sps
1021151909Sps	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1022160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1023151359Sps	if (error == 0) {
1024151359Sps		msg.msg_iov = uiov;
1025151909Sps
1026151909Sps		if (control != NULL)
1027151909Sps			error = freebsd32_copy_msg_out(&msg, control);
1028151909Sps
1029151909Sps		if (error == 0)
1030151909Sps			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1031151359Sps	}
1032151359Sps	free(iov, M_IOV);
1033151909Sps
1034151909Sps	if (control != NULL)
1035151909Sps		m_freem(control);
1036151909Sps
1037151359Sps	return (error);
1038151359Sps}
1039151359Sps
1040151909Sps
1041151909Spsstatic int
1042151909Spsfreebsd32_convert_msg_in(struct mbuf **controlp)
1043151909Sps{
1044151909Sps	struct mbuf *control = *controlp;
1045151909Sps	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1046151909Sps	void *data;
1047151909Sps	socklen_t clen = control->m_len, datalen;
1048151909Sps	int error;
1049151909Sps
1050151909Sps	error = 0;
1051151909Sps	*controlp = NULL;
1052151909Sps
1053151909Sps	while (cm != NULL) {
1054151909Sps		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1055151909Sps			error = EINVAL;
1056151909Sps			break;
1057151909Sps		}
1058151909Sps
1059151909Sps		data = FREEBSD32_CMSG_DATA(cm);
1060151909Sps		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1061151909Sps
1062151909Sps		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1063151909Sps		    cm->cmsg_level);
1064151909Sps		controlp = &(*controlp)->m_next;
1065151909Sps
1066151909Sps		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1067151909Sps			clen -= FREEBSD32_CMSG_SPACE(datalen);
1068151909Sps			cm = (struct cmsghdr *)
1069151909Sps				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1070151909Sps		} else {
1071151909Sps			clen = 0;
1072151909Sps			cm = NULL;
1073151909Sps		}
1074151909Sps	}
1075151909Sps
1076151909Sps	m_freem(control);
1077151909Sps	return (error);
1078151909Sps}
1079151909Sps
1080151909Sps
1081151359Spsint
1082151359Spsfreebsd32_sendmsg(struct thread *td,
1083151359Sps		  struct freebsd32_sendmsg_args *uap)
1084151359Sps{
1085151359Sps	struct msghdr msg;
1086151359Sps	struct msghdr32 m32;
1087151359Sps	struct iovec *iov;
1088151909Sps	struct mbuf *control = NULL;
1089151909Sps	struct sockaddr *to = NULL;
1090151359Sps	int error;
1091151359Sps
1092151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1093151359Sps	if (error)
1094151359Sps		return (error);
1095151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1096151359Sps	if (error)
1097151359Sps		return (error);
1098160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1099160246Sjhb	    EMSGSIZE);
1100151359Sps	if (error)
1101151359Sps		return (error);
1102151359Sps	msg.msg_iov = iov;
1103151909Sps	if (msg.msg_name != NULL) {
1104151909Sps		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1105151909Sps		if (error) {
1106151909Sps			to = NULL;
1107151909Sps			goto out;
1108151909Sps		}
1109151909Sps		msg.msg_name = to;
1110151909Sps	}
1111151909Sps
1112151909Sps	if (msg.msg_control) {
1113151909Sps		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1114151909Sps			error = EINVAL;
1115151909Sps			goto out;
1116151909Sps		}
1117151909Sps
1118151909Sps		error = sockargs(&control, msg.msg_control,
1119151909Sps		    msg.msg_controllen, MT_CONTROL);
1120151909Sps		if (error)
1121151909Sps			goto out;
1122151909Sps
1123151909Sps		error = freebsd32_convert_msg_in(&control);
1124151909Sps		if (error)
1125151909Sps			goto out;
1126151909Sps	}
1127151909Sps
1128151909Sps	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1129151909Sps	    UIO_USERSPACE);
1130151909Sps
1131151909Spsout:
1132151359Sps	free(iov, M_IOV);
1133151909Sps	if (to)
1134151909Sps		free(to, M_SONAME);
1135151359Sps	return (error);
1136151359Sps}
1137151359Sps
1138151359Spsint
1139151359Spsfreebsd32_recvfrom(struct thread *td,
1140151359Sps		   struct freebsd32_recvfrom_args *uap)
1141151359Sps{
1142151359Sps	struct msghdr msg;
1143151359Sps	struct iovec aiov;
1144151359Sps	int error;
1145151359Sps
1146151359Sps	if (uap->fromlenaddr) {
1147160246Sjhb		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1148160246Sjhb		    sizeof(msg.msg_namelen));
1149151359Sps		if (error)
1150151359Sps			return (error);
1151151359Sps	} else {
1152151359Sps		msg.msg_namelen = 0;
1153151359Sps	}
1154151359Sps
1155160246Sjhb	msg.msg_name = PTRIN(uap->from);
1156151359Sps	msg.msg_iov = &aiov;
1157151359Sps	msg.msg_iovlen = 1;
1158160246Sjhb	aiov.iov_base = PTRIN(uap->buf);
1159151359Sps	aiov.iov_len = uap->len;
1160160246Sjhb	msg.msg_control = NULL;
1161151359Sps	msg.msg_flags = uap->flags;
1162160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1163160249Sjhb	if (error == 0 && uap->fromlenaddr)
1164160249Sjhb		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1165160249Sjhb		    sizeof (msg.msg_namelen));
1166151359Sps	return (error);
1167151359Sps}
1168151359Sps
1169151359Spsint
1170119333Speterfreebsd32_settimeofday(struct thread *td,
1171119333Speter		       struct freebsd32_settimeofday_args *uap)
1172100384Speter{
1173144450Sjhb	struct timeval32 tv32;
1174144450Sjhb	struct timeval tv, *tvp;
1175144450Sjhb	struct timezone tz, *tzp;
1176100384Speter	int error;
1177100384Speter
1178144450Sjhb	if (uap->tv) {
1179144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
1180100384Speter		if (error)
1181100384Speter			return (error);
1182144450Sjhb		CP(tv32, tv, tv_sec);
1183144450Sjhb		CP(tv32, tv, tv_usec);
1184144450Sjhb		tvp = &tv;
1185144450Sjhb	} else
1186144450Sjhb		tvp = NULL;
1187144450Sjhb	if (uap->tzp) {
1188144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
1189100384Speter		if (error)
1190100384Speter			return (error);
1191144450Sjhb		tzp = &tz;
1192144450Sjhb	} else
1193144450Sjhb		tzp = NULL;
1194144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
1195100384Speter}
1196100384Speter
1197100384Speterint
1198119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1199100384Speter{
1200142059Sjhb	struct timeval32 s32[2];
1201142059Sjhb	struct timeval s[2], *sp;
1202100384Speter	int error;
1203100384Speter
1204142059Sjhb	if (uap->tptr != NULL) {
1205142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
1206100384Speter		if (error)
1207100384Speter			return (error);
1208100384Speter		CP(s32[0], s[0], tv_sec);
1209100384Speter		CP(s32[0], s[0], tv_usec);
1210100384Speter		CP(s32[1], s[1], tv_sec);
1211100384Speter		CP(s32[1], s[1], tv_usec);
1212142059Sjhb		sp = s;
1213142059Sjhb	} else
1214142059Sjhb		sp = NULL;
1215142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1216100384Speter}
1217100384Speter
1218100384Speterint
1219154586Sambriskofreebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1220154586Sambrisko{
1221154586Sambrisko	struct timeval32 s32[2];
1222154586Sambrisko	struct timeval s[2], *sp;
1223154586Sambrisko	int error;
1224154586Sambrisko
1225154586Sambrisko	if (uap->tptr != NULL) {
1226154586Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1227154586Sambrisko		if (error)
1228154586Sambrisko			return (error);
1229154586Sambrisko		CP(s32[0], s[0], tv_sec);
1230154586Sambrisko		CP(s32[0], s[0], tv_usec);
1231154586Sambrisko		CP(s32[1], s[1], tv_sec);
1232154586Sambrisko		CP(s32[1], s[1], tv_usec);
1233154586Sambrisko		sp = s;
1234154586Sambrisko	} else
1235154586Sambrisko		sp = NULL;
1236154586Sambrisko	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1237154586Sambrisko}
1238154586Sambrisko
1239154586Sambriskoint
1240153247Sambriskofreebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1241153247Sambrisko{
1242153247Sambrisko	struct timeval32 s32[2];
1243153247Sambrisko	struct timeval s[2], *sp;
1244153247Sambrisko	int error;
1245153247Sambrisko
1246153247Sambrisko	if (uap->tptr != NULL) {
1247153247Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1248153247Sambrisko		if (error)
1249153247Sambrisko			return (error);
1250153247Sambrisko		CP(s32[0], s[0], tv_sec);
1251153247Sambrisko		CP(s32[0], s[0], tv_usec);
1252153247Sambrisko		CP(s32[1], s[1], tv_sec);
1253153247Sambrisko		CP(s32[1], s[1], tv_usec);
1254153247Sambrisko		sp = s;
1255153247Sambrisko	} else
1256153247Sambrisko		sp = NULL;
1257153247Sambrisko	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1258153247Sambrisko}
1259153247Sambrisko
1260177789Skibint
1261177789Skibfreebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
1262177789Skib{
1263177789Skib	struct timeval32 s32[2];
1264177789Skib	struct timeval s[2], *sp;
1265177789Skib	int error;
1266153247Sambrisko
1267177789Skib	if (uap->times != NULL) {
1268177789Skib		error = copyin(uap->times, s32, sizeof(s32));
1269177789Skib		if (error)
1270177789Skib			return (error);
1271177789Skib		CP(s32[0], s[0], tv_sec);
1272177789Skib		CP(s32[0], s[0], tv_usec);
1273177789Skib		CP(s32[1], s[1], tv_sec);
1274177789Skib		CP(s32[1], s[1], tv_usec);
1275177789Skib		sp = s;
1276177789Skib	} else
1277177789Skib		sp = NULL;
1278177789Skib	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
1279177789Skib		sp, UIO_SYSSPACE));
1280177789Skib}
1281177789Skib
1282153247Sambriskoint
1283119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1284100384Speter{
1285144450Sjhb	struct timeval32 tv32;
1286144450Sjhb	struct timeval delta, olddelta, *deltap;
1287100384Speter	int error;
1288100384Speter
1289144450Sjhb	if (uap->delta) {
1290144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
1291100384Speter		if (error)
1292100384Speter			return (error);
1293144450Sjhb		CP(tv32, delta, tv_sec);
1294144450Sjhb		CP(tv32, delta, tv_usec);
1295144450Sjhb		deltap = &delta;
1296144450Sjhb	} else
1297144450Sjhb		deltap = NULL;
1298144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
1299144450Sjhb	if (uap->olddelta && error == 0) {
1300144450Sjhb		CP(olddelta, tv32, tv_sec);
1301144450Sjhb		CP(olddelta, tv32, tv_usec);
1302144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1303100384Speter	}
1304100384Speter	return (error);
1305100384Speter}
1306100384Speter
1307128597Smarcel#ifdef COMPAT_FREEBSD4
1308100384Speterint
1309128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1310100384Speter{
1311142059Sjhb	struct statfs32 s32;
1312142059Sjhb	struct statfs s;
1313100384Speter	int error;
1314100384Speter
1315142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1316100384Speter	if (error)
1317100384Speter		return (error);
1318174526Sjhb	copy_statfs(&s, &s32);
1319142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1320100384Speter}
1321128597Smarcel#endif
1322100384Speter
1323128597Smarcel#ifdef COMPAT_FREEBSD4
1324100384Speterint
1325128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1326100384Speter{
1327142059Sjhb	struct statfs32 s32;
1328142059Sjhb	struct statfs s;
1329100384Speter	int error;
1330100384Speter
1331142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
1332100384Speter	if (error)
1333100384Speter		return (error);
1334174526Sjhb	copy_statfs(&s, &s32);
1335142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1336100384Speter}
1337128597Smarcel#endif
1338100384Speter
1339128597Smarcel#ifdef COMPAT_FREEBSD4
1340100384Speterint
1341128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1342128260Speter{
1343142059Sjhb	struct statfs32 s32;
1344142059Sjhb	struct statfs s;
1345142059Sjhb	fhandle_t fh;
1346128260Speter	int error;
1347128260Speter
1348142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1349142059Sjhb		return (error);
1350142059Sjhb	error = kern_fhstatfs(td, fh, &s);
1351128260Speter	if (error)
1352128260Speter		return (error);
1353174526Sjhb	copy_statfs(&s, &s32);
1354142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1355128260Speter}
1356128597Smarcel#endif
1357128260Speter
1358174381Sjhbstatic void
1359174381Sjhbfreebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1360174381Sjhb{
1361174381Sjhb
1362174381Sjhb	CP(*ip32, *ip, cuid);
1363174381Sjhb	CP(*ip32, *ip, cgid);
1364174381Sjhb	CP(*ip32, *ip, uid);
1365174381Sjhb	CP(*ip32, *ip, gid);
1366174381Sjhb	CP(*ip32, *ip, mode);
1367174381Sjhb	CP(*ip32, *ip, seq);
1368174381Sjhb	CP(*ip32, *ip, key);
1369174381Sjhb}
1370174381Sjhb
1371174381Sjhbstatic void
1372174381Sjhbfreebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1373174381Sjhb{
1374174381Sjhb
1375174381Sjhb	CP(*ip, *ip32, cuid);
1376174381Sjhb	CP(*ip, *ip32, cgid);
1377174381Sjhb	CP(*ip, *ip32, uid);
1378174381Sjhb	CP(*ip, *ip32, gid);
1379174381Sjhb	CP(*ip, *ip32, mode);
1380174381Sjhb	CP(*ip, *ip32, seq);
1381174381Sjhb	CP(*ip, *ip32, key);
1382174381Sjhb}
1383174381Sjhb
1384128260Speterint
1385119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1386100384Speter{
1387174381Sjhb
1388174381Sjhb	switch (uap->which) {
1389174381Sjhb	case 0:
1390174381Sjhb		return (freebsd32_semctl(td,
1391174381Sjhb		    (struct freebsd32_semctl_args *)&uap->a2));
1392174381Sjhb	default:
1393174381Sjhb		return (semsys(td, (struct semsys_args *)uap));
1394174381Sjhb	}
1395100384Speter}
1396100384Speter
1397100384Speterint
1398174381Sjhbfreebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1399174381Sjhb{
1400174381Sjhb	struct semid_ds32 dsbuf32;
1401174381Sjhb	struct semid_ds dsbuf;
1402174381Sjhb	union semun semun;
1403174381Sjhb	union semun32 arg;
1404174381Sjhb	register_t rval;
1405174381Sjhb	int error;
1406174381Sjhb
1407174381Sjhb	switch (uap->cmd) {
1408174381Sjhb	case SEM_STAT:
1409174381Sjhb	case IPC_SET:
1410174381Sjhb	case IPC_STAT:
1411174381Sjhb	case GETALL:
1412174381Sjhb	case SETVAL:
1413174381Sjhb	case SETALL:
1414174381Sjhb		error = copyin(uap->arg, &arg, sizeof(arg));
1415174381Sjhb		if (error)
1416174381Sjhb			return (error);
1417174381Sjhb		break;
1418174381Sjhb	}
1419174381Sjhb
1420174381Sjhb	switch (uap->cmd) {
1421174381Sjhb	case SEM_STAT:
1422174381Sjhb	case IPC_STAT:
1423174381Sjhb		semun.buf = &dsbuf;
1424174381Sjhb		break;
1425174381Sjhb	case IPC_SET:
1426174381Sjhb		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1427174381Sjhb		if (error)
1428174381Sjhb			return (error);
1429174381Sjhb		freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1430174381Sjhb		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1431174381Sjhb		CP(dsbuf32, dsbuf, sem_nsems);
1432174381Sjhb		CP(dsbuf32, dsbuf, sem_otime);
1433174381Sjhb		CP(dsbuf32, dsbuf, sem_pad1);
1434174381Sjhb		CP(dsbuf32, dsbuf, sem_ctime);
1435174381Sjhb		CP(dsbuf32, dsbuf, sem_pad2);
1436174381Sjhb		CP(dsbuf32, dsbuf, sem_pad3[0]);
1437174381Sjhb		CP(dsbuf32, dsbuf, sem_pad3[1]);
1438174381Sjhb		CP(dsbuf32, dsbuf, sem_pad3[2]);
1439174381Sjhb		CP(dsbuf32, dsbuf, sem_pad3[3]);
1440174381Sjhb		semun.buf = &dsbuf;
1441174381Sjhb		break;
1442174381Sjhb	case GETALL:
1443174381Sjhb	case SETALL:
1444174381Sjhb		semun.array = PTRIN(arg.array);
1445174381Sjhb		break;
1446174381Sjhb	case SETVAL:
1447174381Sjhb		semun.val = arg.val;
1448174381Sjhb		break;
1449174381Sjhb	}
1450174381Sjhb
1451174381Sjhb	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1452174381Sjhb	    &rval);
1453174381Sjhb	if (error)
1454174381Sjhb		return (error);
1455174381Sjhb
1456174381Sjhb	switch (uap->cmd) {
1457174381Sjhb	case SEM_STAT:
1458174381Sjhb	case IPC_STAT:
1459174381Sjhb		freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1460174381Sjhb		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1461174381Sjhb		CP(dsbuf, dsbuf32, sem_nsems);
1462174381Sjhb		CP(dsbuf, dsbuf32, sem_otime);
1463174381Sjhb		CP(dsbuf, dsbuf32, sem_pad1);
1464174381Sjhb		CP(dsbuf, dsbuf32, sem_ctime);
1465174381Sjhb		CP(dsbuf, dsbuf32, sem_pad2);
1466174381Sjhb		CP(dsbuf, dsbuf32, sem_pad3[0]);
1467174381Sjhb		CP(dsbuf, dsbuf32, sem_pad3[1]);
1468174381Sjhb		CP(dsbuf, dsbuf32, sem_pad3[2]);
1469174381Sjhb		CP(dsbuf, dsbuf32, sem_pad3[3]);
1470174381Sjhb		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1471174381Sjhb		break;
1472174381Sjhb	}
1473174381Sjhb
1474174381Sjhb	if (error == 0)
1475174381Sjhb		td->td_retval[0] = rval;
1476174381Sjhb	return (error);
1477174381Sjhb}
1478174381Sjhb
1479174381Sjhbint
1480119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1481100384Speter{
1482174381Sjhb
1483165405Sjkim	switch (uap->which) {
1484174381Sjhb	case 0:
1485174381Sjhb		return (freebsd32_msgctl(td,
1486174381Sjhb		    (struct freebsd32_msgctl_args *)&uap->a2));
1487165405Sjkim	case 2:
1488165405Sjkim		return (freebsd32_msgsnd(td,
1489165405Sjkim		    (struct freebsd32_msgsnd_args *)&uap->a2));
1490165405Sjkim	case 3:
1491165405Sjkim		return (freebsd32_msgrcv(td,
1492165405Sjkim		    (struct freebsd32_msgrcv_args *)&uap->a2));
1493165405Sjkim	default:
1494174381Sjhb		return (msgsys(td, (struct msgsys_args *)uap));
1495165405Sjkim	}
1496100384Speter}
1497100384Speter
1498100384Speterint
1499174381Sjhbfreebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1500174381Sjhb{
1501174381Sjhb	struct msqid_ds msqbuf;
1502174381Sjhb	struct msqid_ds32 msqbuf32;
1503174381Sjhb	int error;
1504174381Sjhb
1505174381Sjhb	if (uap->cmd == IPC_SET) {
1506174381Sjhb		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1507174381Sjhb		if (error)
1508174381Sjhb			return (error);
1509174381Sjhb		freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1510174381Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1511174381Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1512174381Sjhb		CP(msqbuf32, msqbuf, msg_cbytes);
1513174381Sjhb		CP(msqbuf32, msqbuf, msg_qnum);
1514174381Sjhb		CP(msqbuf32, msqbuf, msg_qbytes);
1515174381Sjhb		CP(msqbuf32, msqbuf, msg_lspid);
1516174381Sjhb		CP(msqbuf32, msqbuf, msg_lrpid);
1517174381Sjhb		CP(msqbuf32, msqbuf, msg_stime);
1518174381Sjhb		CP(msqbuf32, msqbuf, msg_pad1);
1519174381Sjhb		CP(msqbuf32, msqbuf, msg_rtime);
1520174381Sjhb		CP(msqbuf32, msqbuf, msg_pad2);
1521174381Sjhb		CP(msqbuf32, msqbuf, msg_ctime);
1522174381Sjhb		CP(msqbuf32, msqbuf, msg_pad3);
1523174381Sjhb		CP(msqbuf32, msqbuf, msg_pad4[0]);
1524174381Sjhb		CP(msqbuf32, msqbuf, msg_pad4[1]);
1525174381Sjhb		CP(msqbuf32, msqbuf, msg_pad4[2]);
1526174381Sjhb		CP(msqbuf32, msqbuf, msg_pad4[3]);
1527174381Sjhb	}
1528174381Sjhb	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1529174381Sjhb	if (error)
1530174381Sjhb		return (error);
1531174381Sjhb	if (uap->cmd == IPC_STAT) {
1532174381Sjhb		freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1533174381Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1534174381Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1535174381Sjhb		CP(msqbuf, msqbuf32, msg_cbytes);
1536174381Sjhb		CP(msqbuf, msqbuf32, msg_qnum);
1537174381Sjhb		CP(msqbuf, msqbuf32, msg_qbytes);
1538174381Sjhb		CP(msqbuf, msqbuf32, msg_lspid);
1539174381Sjhb		CP(msqbuf, msqbuf32, msg_lrpid);
1540174381Sjhb		CP(msqbuf, msqbuf32, msg_stime);
1541174381Sjhb		CP(msqbuf, msqbuf32, msg_pad1);
1542174381Sjhb		CP(msqbuf, msqbuf32, msg_rtime);
1543174381Sjhb		CP(msqbuf, msqbuf32, msg_pad2);
1544174381Sjhb		CP(msqbuf, msqbuf32, msg_ctime);
1545174381Sjhb		CP(msqbuf, msqbuf32, msg_pad3);
1546174381Sjhb		CP(msqbuf, msqbuf32, msg_pad4[0]);
1547174381Sjhb		CP(msqbuf, msqbuf32, msg_pad4[1]);
1548174381Sjhb		CP(msqbuf, msqbuf32, msg_pad4[2]);
1549174381Sjhb		CP(msqbuf, msqbuf32, msg_pad4[3]);
1550174381Sjhb		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1551174381Sjhb	}
1552174381Sjhb	return (error);
1553174381Sjhb}
1554174381Sjhb
1555174381Sjhbint
1556165405Sjkimfreebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1557165405Sjkim{
1558165405Sjkim	const void *msgp;
1559165405Sjkim	long mtype;
1560165405Sjkim	int32_t mtype32;
1561165405Sjkim	int error;
1562165405Sjkim
1563165405Sjkim	msgp = PTRIN(uap->msgp);
1564165405Sjkim	if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1565165405Sjkim		return (error);
1566165405Sjkim	mtype = mtype32;
1567165405Sjkim	return (kern_msgsnd(td, uap->msqid,
1568165405Sjkim	    (const char *)msgp + sizeof(mtype32),
1569165405Sjkim	    uap->msgsz, uap->msgflg, mtype));
1570165405Sjkim}
1571165405Sjkim
1572165405Sjkimint
1573165405Sjkimfreebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1574165405Sjkim{
1575165405Sjkim	void *msgp;
1576165405Sjkim	long mtype;
1577165405Sjkim	int32_t mtype32;
1578165405Sjkim	int error;
1579165405Sjkim
1580165405Sjkim	msgp = PTRIN(uap->msgp);
1581165405Sjkim	if ((error = kern_msgrcv(td, uap->msqid,
1582165405Sjkim	    (char *)msgp + sizeof(mtype32), uap->msgsz,
1583165405Sjkim	    uap->msgtyp, uap->msgflg, &mtype)) != 0)
1584165405Sjkim		return (error);
1585165405Sjkim	mtype32 = (int32_t)mtype;
1586165405Sjkim	return (copyout(&mtype32, msgp, sizeof(mtype32)));
1587165405Sjkim}
1588165405Sjkim
1589165405Sjkimint
1590119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1591100384Speter{
1592157285Sps
1593157285Sps	switch (uap->which) {
1594157285Sps	case 0:	{	/* shmat */
1595157285Sps		struct shmat_args ap;
1596157285Sps
1597157285Sps		ap.shmid = uap->a2;
1598157285Sps		ap.shmaddr = PTRIN(uap->a3);
1599157285Sps		ap.shmflg = uap->a4;
1600157285Sps		return (sysent[SYS_shmat].sy_call(td, &ap));
1601157285Sps	}
1602157285Sps	case 2: {	/* shmdt */
1603157285Sps		struct shmdt_args ap;
1604157285Sps
1605157285Sps		ap.shmaddr = PTRIN(uap->a2);
1606157285Sps		return (sysent[SYS_shmdt].sy_call(td, &ap));
1607157285Sps	}
1608157285Sps	case 3: {	/* shmget */
1609157285Sps		struct shmget_args ap;
1610157285Sps
1611157285Sps		ap.key = uap->a2;
1612157285Sps		ap.size = uap->a3;
1613157285Sps		ap.shmflg = uap->a4;
1614157285Sps		return (sysent[SYS_shmget].sy_call(td, &ap));
1615157285Sps	}
1616157285Sps	case 4: {	/* shmctl */
1617157285Sps		struct freebsd32_shmctl_args ap;
1618157285Sps
1619157285Sps		ap.shmid = uap->a2;
1620157285Sps		ap.cmd = uap->a3;
1621157285Sps		ap.buf = PTRIN(uap->a4);
1622157285Sps		return (freebsd32_shmctl(td, &ap));
1623157285Sps	}
1624157285Sps	case 1:		/* oshmctl */
1625157285Sps	default:
1626157285Sps		return (EINVAL);
1627157285Sps	}
1628100384Speter}
1629100384Speter
1630100384Speterint
1631157285Spsfreebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1632157285Sps{
1633157285Sps	int error = 0;
1634157285Sps	union {
1635157285Sps		struct shmid_ds shmid_ds;
1636157285Sps		struct shm_info shm_info;
1637157285Sps		struct shminfo shminfo;
1638157285Sps	} u;
1639157285Sps	union {
1640157285Sps		struct shmid_ds32 shmid_ds32;
1641157285Sps		struct shm_info32 shm_info32;
1642157285Sps		struct shminfo32 shminfo32;
1643157285Sps	} u32;
1644157285Sps	size_t sz;
1645157285Sps
1646157285Sps	if (uap->cmd == IPC_SET) {
1647157285Sps		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1648157285Sps		    sizeof(u32.shmid_ds32))))
1649157285Sps			goto done;
1650174381Sjhb		freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1651174381Sjhb		    &u.shmid_ds.shm_perm);
1652157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1653157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1654157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1655157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1656157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1657157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1658157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1659157285Sps		PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1660157285Sps	}
1661157285Sps
1662157285Sps	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1663157285Sps	if (error)
1664157285Sps		goto done;
1665157285Sps
1666157285Sps	/* Cases in which we need to copyout */
1667157285Sps	switch (uap->cmd) {
1668157285Sps	case IPC_INFO:
1669157285Sps		CP(u.shminfo, u32.shminfo32, shmmax);
1670157285Sps		CP(u.shminfo, u32.shminfo32, shmmin);
1671157285Sps		CP(u.shminfo, u32.shminfo32, shmmni);
1672157285Sps		CP(u.shminfo, u32.shminfo32, shmseg);
1673157285Sps		CP(u.shminfo, u32.shminfo32, shmall);
1674157285Sps		error = copyout(&u32.shminfo32, uap->buf,
1675157285Sps		    sizeof(u32.shminfo32));
1676157285Sps		break;
1677157285Sps	case SHM_INFO:
1678157285Sps		CP(u.shm_info, u32.shm_info32, used_ids);
1679157285Sps		CP(u.shm_info, u32.shm_info32, shm_rss);
1680157285Sps		CP(u.shm_info, u32.shm_info32, shm_tot);
1681157285Sps		CP(u.shm_info, u32.shm_info32, shm_swp);
1682157285Sps		CP(u.shm_info, u32.shm_info32, swap_attempts);
1683157285Sps		CP(u.shm_info, u32.shm_info32, swap_successes);
1684157285Sps		error = copyout(&u32.shm_info32, uap->buf,
1685157285Sps		    sizeof(u32.shm_info32));
1686157285Sps		break;
1687157285Sps	case SHM_STAT:
1688157285Sps	case IPC_STAT:
1689174381Sjhb		freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1690174381Sjhb		    &u32.shmid_ds32.shm_perm);
1691157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1692157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1693157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1694157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1695157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1696157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1697157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1698157285Sps		PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1699157285Sps		error = copyout(&u32.shmid_ds32, uap->buf,
1700157285Sps		    sizeof(u32.shmid_ds32));
1701157285Sps		break;
1702157285Sps	}
1703157285Sps
1704157285Spsdone:
1705157285Sps	if (error) {
1706157285Sps		/* Invalidate the return value */
1707157285Sps		td->td_retval[0] = -1;
1708157285Sps	}
1709157285Sps	return (error);
1710157285Sps}
1711157285Sps
1712157285Spsint
1713119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1714100384Speter{
1715100384Speter	struct pread_args ap;
1716100384Speter
1717107849Salfred	ap.fd = uap->fd;
1718107849Salfred	ap.buf = uap->buf;
1719107849Salfred	ap.nbyte = uap->nbyte;
1720119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1721100384Speter	return (pread(td, &ap));
1722100384Speter}
1723100384Speter
1724100384Speterint
1725119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1726100384Speter{
1727100384Speter	struct pwrite_args ap;
1728100384Speter
1729107849Salfred	ap.fd = uap->fd;
1730107849Salfred	ap.buf = uap->buf;
1731107849Salfred	ap.nbyte = uap->nbyte;
1732119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1733100384Speter	return (pwrite(td, &ap));
1734100384Speter}
1735100384Speter
1736100384Speterint
1737119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1738100384Speter{
1739100384Speter	int error;
1740100384Speter	struct lseek_args ap;
1741100384Speter	off_t pos;
1742100384Speter
1743107849Salfred	ap.fd = uap->fd;
1744119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1745107849Salfred	ap.whence = uap->whence;
1746100384Speter	error = lseek(td, &ap);
1747100384Speter	/* Expand the quad return into two parts for eax and edx */
1748100384Speter	pos = *(off_t *)(td->td_retval);
1749100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1750100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1751100384Speter	return error;
1752100384Speter}
1753100384Speter
1754100384Speterint
1755119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1756100384Speter{
1757100384Speter	struct truncate_args ap;
1758100384Speter
1759107849Salfred	ap.path = uap->path;
1760119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1761100384Speter	return (truncate(td, &ap));
1762100384Speter}
1763100384Speter
1764100384Speterint
1765119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1766100384Speter{
1767100384Speter	struct ftruncate_args ap;
1768100384Speter
1769107849Salfred	ap.fd = uap->fd;
1770119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1771100384Speter	return (ftruncate(td, &ap));
1772100384Speter}
1773100384Speter
1774184183Sjhbint
1775184183Sjhbfreebsd32_getdirentries(struct thread *td,
1776184183Sjhb    struct freebsd32_getdirentries_args *uap)
1777184183Sjhb{
1778184183Sjhb	long base;
1779184183Sjhb	int32_t base32;
1780184183Sjhb	int error;
1781184183Sjhb
1782184183Sjhb	error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
1783184183Sjhb	if (error)
1784184183Sjhb		return (error);
1785184183Sjhb	if (uap->basep != NULL) {
1786184183Sjhb		base32 = base;
1787184183Sjhb		error = copyout(&base32, uap->basep, sizeof(int32_t));
1788184183Sjhb	}
1789184183Sjhb	return (error);
1790184183Sjhb}
1791184183Sjhb
1792171215Speter#ifdef COMPAT_FREEBSD6
1793171215Speter/* versions with the 'int pad' argument */
1794171215Speterint
1795171215Speterfreebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
1796171215Speter{
1797171215Speter	struct pread_args ap;
1798171215Speter
1799171215Speter	ap.fd = uap->fd;
1800171215Speter	ap.buf = uap->buf;
1801171215Speter	ap.nbyte = uap->nbyte;
1802171215Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1803171215Speter	return (pread(td, &ap));
1804171215Speter}
1805171215Speter
1806171215Speterint
1807171215Speterfreebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
1808171215Speter{
1809171215Speter	struct pwrite_args ap;
1810171215Speter
1811171215Speter	ap.fd = uap->fd;
1812171215Speter	ap.buf = uap->buf;
1813171215Speter	ap.nbyte = uap->nbyte;
1814171215Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1815171215Speter	return (pwrite(td, &ap));
1816171215Speter}
1817171215Speter
1818171215Speterint
1819171215Speterfreebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
1820171215Speter{
1821171215Speter	int error;
1822171215Speter	struct lseek_args ap;
1823171215Speter	off_t pos;
1824171215Speter
1825171215Speter	ap.fd = uap->fd;
1826171215Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1827171215Speter	ap.whence = uap->whence;
1828171215Speter	error = lseek(td, &ap);
1829171215Speter	/* Expand the quad return into two parts for eax and edx */
1830171215Speter	pos = *(off_t *)(td->td_retval);
1831171215Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1832171215Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1833171215Speter	return error;
1834171215Speter}
1835171215Speter
1836171215Speterint
1837171215Speterfreebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
1838171215Speter{
1839171215Speter	struct truncate_args ap;
1840171215Speter
1841171215Speter	ap.path = uap->path;
1842171215Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1843171215Speter	return (truncate(td, &ap));
1844171215Speter}
1845171215Speter
1846171215Speterint
1847171215Speterfreebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
1848171215Speter{
1849171215Speter	struct ftruncate_args ap;
1850171215Speter
1851171215Speter	ap.fd = uap->fd;
1852171215Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1853171215Speter	return (ftruncate(td, &ap));
1854171215Speter}
1855171215Speter#endif /* COMPAT_FREEBSD6 */
1856171215Speter
1857156114Spsstruct sf_hdtr32 {
1858156114Sps	uint32_t headers;
1859156114Sps	int hdr_cnt;
1860156114Sps	uint32_t trailers;
1861156114Sps	int trl_cnt;
1862156114Sps};
1863156114Sps
1864156114Spsstatic int
1865156114Spsfreebsd32_do_sendfile(struct thread *td,
1866156114Sps    struct freebsd32_sendfile_args *uap, int compat)
1867104738Speter{
1868156114Sps	struct sendfile_args ap;
1869156114Sps	struct sf_hdtr32 hdtr32;
1870156114Sps	struct sf_hdtr hdtr;
1871156114Sps	struct uio *hdr_uio, *trl_uio;
1872156114Sps	struct iovec32 *iov32;
1873156114Sps	int error;
1874104738Speter
1875156114Sps	hdr_uio = trl_uio = NULL;
1876156114Sps
1877107849Salfred	ap.fd = uap->fd;
1878107849Salfred	ap.s = uap->s;
1879119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1880156114Sps	ap.nbytes = uap->nbytes;
1881156114Sps	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1882156114Sps	ap.sbytes = uap->sbytes;
1883107849Salfred	ap.flags = uap->flags;
1884156114Sps
1885156114Sps	if (uap->hdtr != NULL) {
1886156114Sps		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1887156114Sps		if (error)
1888156114Sps			goto out;
1889156114Sps		PTRIN_CP(hdtr32, hdtr, headers);
1890156114Sps		CP(hdtr32, hdtr, hdr_cnt);
1891156114Sps		PTRIN_CP(hdtr32, hdtr, trailers);
1892156114Sps		CP(hdtr32, hdtr, trl_cnt);
1893156114Sps
1894156114Sps		if (hdtr.headers != NULL) {
1895160246Sjhb			iov32 = PTRIN(hdtr32.headers);
1896156114Sps			error = freebsd32_copyinuio(iov32,
1897156114Sps			    hdtr32.hdr_cnt, &hdr_uio);
1898156114Sps			if (error)
1899156114Sps				goto out;
1900156114Sps		}
1901156114Sps		if (hdtr.trailers != NULL) {
1902160246Sjhb			iov32 = PTRIN(hdtr32.trailers);
1903156114Sps			error = freebsd32_copyinuio(iov32,
1904156114Sps			    hdtr32.trl_cnt, &trl_uio);
1905156114Sps			if (error)
1906156114Sps				goto out;
1907156114Sps		}
1908156114Sps	}
1909156114Sps
1910156114Sps	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1911156114Spsout:
1912156114Sps	if (hdr_uio)
1913156114Sps		free(hdr_uio, M_IOV);
1914156114Sps	if (trl_uio)
1915156114Sps		free(trl_uio, M_IOV);
1916156114Sps	return (error);
1917104738Speter}
1918156114Sps
1919156114Sps#ifdef COMPAT_FREEBSD4
1920156114Spsint
1921156114Spsfreebsd4_freebsd32_sendfile(struct thread *td,
1922156114Sps    struct freebsd4_freebsd32_sendfile_args *uap)
1923156114Sps{
1924156114Sps	return (freebsd32_do_sendfile(td,
1925156114Sps	    (struct freebsd32_sendfile_args *)uap, 1));
1926156114Sps}
1927104738Speter#endif
1928104738Speter
1929104738Speterint
1930119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1931100384Speter{
1932100384Speter
1933156114Sps	return (freebsd32_do_sendfile(td, uap, 0));
1934100384Speter}
1935100384Speter
1936100384Speterstatic void
1937100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1938100384Speter{
1939100384Speter	CP(*in, *out, st_dev);
1940100384Speter	CP(*in, *out, st_ino);
1941100384Speter	CP(*in, *out, st_mode);
1942100384Speter	CP(*in, *out, st_nlink);
1943100384Speter	CP(*in, *out, st_uid);
1944100384Speter	CP(*in, *out, st_gid);
1945100384Speter	CP(*in, *out, st_rdev);
1946100384Speter	TS_CP(*in, *out, st_atimespec);
1947100384Speter	TS_CP(*in, *out, st_mtimespec);
1948100384Speter	TS_CP(*in, *out, st_ctimespec);
1949100384Speter	CP(*in, *out, st_size);
1950100384Speter	CP(*in, *out, st_blocks);
1951100384Speter	CP(*in, *out, st_blksize);
1952100384Speter	CP(*in, *out, st_flags);
1953100384Speter	CP(*in, *out, st_gen);
1954100384Speter}
1955100384Speter
1956100384Speterint
1957119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1958100384Speter{
1959123746Speter	struct stat sb;
1960123746Speter	struct stat32 sb32;
1961100384Speter	int error;
1962100384Speter
1963142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1964100384Speter	if (error)
1965100384Speter		return (error);
1966123746Speter	copy_stat(&sb, &sb32);
1967123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1968100384Speter	return (error);
1969100384Speter}
1970100384Speter
1971100384Speterint
1972119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1973100384Speter{
1974123746Speter	struct stat ub;
1975123746Speter	struct stat32 ub32;
1976100384Speter	int error;
1977100384Speter
1978142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1979100384Speter	if (error)
1980100384Speter		return (error);
1981123746Speter	copy_stat(&ub, &ub32);
1982123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1983100384Speter	return (error);
1984100384Speter}
1985100384Speter
1986100384Speterint
1987177789Skibfreebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
1988177789Skib{
1989177789Skib	struct stat ub;
1990177789Skib	struct stat32 ub32;
1991177789Skib	int error;
1992177789Skib
1993177789Skib	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
1994177789Skib	if (error)
1995177789Skib		return (error);
1996177789Skib	copy_stat(&ub, &ub32);
1997177789Skib	error = copyout(&ub32, uap->buf, sizeof(ub32));
1998177789Skib	return (error);
1999177789Skib}
2000177789Skib
2001177789Skibint
2002119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
2003100384Speter{
2004123746Speter	struct stat sb;
2005123746Speter	struct stat32 sb32;
2006142059Sjhb	int error;
2007100384Speter
2008142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2009100384Speter	if (error)
2010100384Speter		return (error);
2011123746Speter	copy_stat(&sb, &sb32);
2012123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
2013100384Speter	return (error);
2014100384Speter}
2015100384Speter
2016100384Speter/*
2017100384Speter * MPSAFE
2018100384Speter */
2019100384Speterint
2020119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
2021100384Speter{
2022100384Speter	int error, name[CTL_MAXNAME];
2023100384Speter	size_t j, oldlen;
2024100384Speter
2025100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2026100384Speter		return (EINVAL);
2027136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
2028100384Speter 	if (error)
2029100384Speter		return (error);
2030100384Speter	if (uap->oldlenp)
2031100384Speter		oldlen = fuword32(uap->oldlenp);
2032100384Speter	else
2033100384Speter		oldlen = 0;
2034100384Speter	error = userland_sysctl(td, name, uap->namelen,
2035100384Speter		uap->old, &oldlen, 1,
2036136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
2037100384Speter	if (error && error != ENOMEM)
2038186564Sed		return (error);
2039136404Speter	if (uap->oldlenp)
2040100384Speter		suword32(uap->oldlenp, j);
2041186564Sed	return (0);
2042100384Speter}
2043100384Speter
2044100384Speterint
2045185435Sbzfreebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2046185435Sbz{
2047191673Sjamie	struct iovec optiov[10];
2048191673Sjamie	struct uio opt;
2049191673Sjamie	char *u_path, *u_hostname, *u_name;
2050191673Sjamie#ifdef INET
2051191673Sjamie	struct in_addr *u_ip4;
2052191673Sjamie#endif
2053191673Sjamie#ifdef INET6
2054191673Sjamie	struct in6_addr *u_ip6;
2055191673Sjamie#endif
2056185435Sbz	uint32_t version;
2057185435Sbz	int error;
2058185435Sbz
2059185435Sbz	error = copyin(uap->jail, &version, sizeof(uint32_t));
2060185435Sbz	if (error)
2061185435Sbz		return (error);
2062190466Sjamie
2063185435Sbz	switch (version) {
2064190466Sjamie	case 0:
2065185435Sbz	{
2066185435Sbz		/* FreeBSD single IPv4 jails. */
2067185435Sbz		struct jail32_v0 j32_v0;
2068185435Sbz
2069185435Sbz		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2070185435Sbz		if (error)
2071185435Sbz			return (error);
2072191673Sjamie		u_path = malloc(MAXPATHLEN + MAXHOSTNAMELEN, M_TEMP, M_WAITOK);
2073191673Sjamie		u_hostname = u_path + MAXPATHLEN;
2074191673Sjamie		opt.uio_iov = optiov;
2075191673Sjamie		opt.uio_iovcnt = 4;
2076191673Sjamie		opt.uio_offset = -1;
2077191673Sjamie		opt.uio_resid = -1;
2078191673Sjamie		opt.uio_segflg = UIO_SYSSPACE;
2079191673Sjamie		opt.uio_rw = UIO_READ;
2080191673Sjamie		opt.uio_td = td;
2081191673Sjamie		optiov[0].iov_base = "path";
2082191673Sjamie		optiov[0].iov_len = sizeof("path");
2083191673Sjamie		optiov[1].iov_base = u_path;
2084191673Sjamie		error = copyinstr(PTRIN(j32_v0.path), u_path, MAXPATHLEN,
2085191673Sjamie		    &optiov[1].iov_len);
2086191673Sjamie		if (error) {
2087191673Sjamie			free(u_path, M_TEMP);
2088191673Sjamie			return (error);
2089191673Sjamie		}
2090191673Sjamie		optiov[2].iov_base = "host.hostname";
2091191673Sjamie		optiov[2].iov_len = sizeof("host.hostname");
2092191673Sjamie		optiov[3].iov_base = u_hostname;
2093191673Sjamie		error = copyinstr(PTRIN(j32_v0.hostname), u_hostname,
2094191673Sjamie		    MAXHOSTNAMELEN, &optiov[3].iov_len);
2095191673Sjamie		if (error) {
2096191673Sjamie			free(u_path, M_TEMP);
2097191673Sjamie			return (error);
2098191673Sjamie		}
2099191673Sjamie#ifdef INET
2100191673Sjamie		optiov[opt.uio_iovcnt].iov_base = "ip4.addr";
2101191673Sjamie		optiov[opt.uio_iovcnt].iov_len = sizeof("ip4.addr");
2102191673Sjamie		opt.uio_iovcnt++;
2103191673Sjamie		optiov[opt.uio_iovcnt].iov_base = &j32_v0.ip_number;
2104191673Sjamie		j32_v0.ip_number = htonl(j32_v0.ip_number);
2105191673Sjamie		optiov[opt.uio_iovcnt].iov_len = sizeof(j32_v0.ip_number);
2106191673Sjamie		opt.uio_iovcnt++;
2107191673Sjamie#endif
2108185435Sbz		break;
2109185435Sbz	}
2110185435Sbz
2111185435Sbz	case 1:
2112185435Sbz		/*
2113185435Sbz		 * Version 1 was used by multi-IPv4 jail implementations
2114185435Sbz		 * that never made it into the official kernel.
2115185435Sbz		 */
2116185435Sbz		return (EINVAL);
2117185435Sbz
2118185435Sbz	case 2:	/* JAIL_API_VERSION */
2119185435Sbz	{
2120185435Sbz		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
2121185435Sbz		struct jail32 j32;
2122191673Sjamie		size_t tmplen;
2123185435Sbz
2124185435Sbz		error = copyin(uap->jail, &j32, sizeof(struct jail32));
2125185435Sbz		if (error)
2126185435Sbz			return (error);
2127191673Sjamie		tmplen = MAXPATHLEN + MAXHOSTNAMELEN + MAXHOSTNAMELEN;
2128191673Sjamie#ifdef INET
2129191673Sjamie		if (j32.ip4s > jail_max_af_ips)
2130191673Sjamie			return (EINVAL);
2131191673Sjamie		tmplen += j32.ip4s * sizeof(struct in_addr);
2132191673Sjamie#else
2133191673Sjamie		if (j32.ip4s > 0)
2134191673Sjamie			return (EINVAL);
2135191673Sjamie#endif
2136191673Sjamie#ifdef INET6
2137191673Sjamie		if (j32.ip6s > jail_max_af_ips)
2138191673Sjamie			return (EINVAL);
2139191673Sjamie		tmplen += j32.ip6s * sizeof(struct in6_addr);
2140191673Sjamie#else
2141191673Sjamie		if (j32.ip6s > 0)
2142191673Sjamie			return (EINVAL);
2143191673Sjamie#endif
2144191673Sjamie		u_path = malloc(tmplen, M_TEMP, M_WAITOK);
2145191673Sjamie		u_hostname = u_path + MAXPATHLEN;
2146191673Sjamie		u_name = u_hostname + MAXHOSTNAMELEN;
2147191673Sjamie#ifdef INET
2148191673Sjamie		u_ip4 =  (struct in_addr *)(u_name + MAXHOSTNAMELEN);
2149191673Sjamie#endif
2150191673Sjamie#ifdef INET6
2151191673Sjamie#ifdef INET
2152191673Sjamie		u_ip6 = (struct in6_addr *)(u_ip4 + j32.ip4s);
2153191673Sjamie#else
2154191673Sjamie		u_ip6 = (struct in6_addr *)(u_name + MAXHOSTNAMELEN);
2155191673Sjamie#endif
2156191673Sjamie#endif
2157191673Sjamie		opt.uio_iov = optiov;
2158191673Sjamie		opt.uio_iovcnt = 4;
2159191673Sjamie		opt.uio_offset = -1;
2160191673Sjamie		opt.uio_resid = -1;
2161191673Sjamie		opt.uio_segflg = UIO_SYSSPACE;
2162191673Sjamie		opt.uio_rw = UIO_READ;
2163191673Sjamie		opt.uio_td = td;
2164191673Sjamie		optiov[0].iov_base = "path";
2165191673Sjamie		optiov[0].iov_len = sizeof("path");
2166191673Sjamie		optiov[1].iov_base = u_path;
2167191673Sjamie		error = copyinstr(PTRIN(j32.path), u_path, MAXPATHLEN,
2168191673Sjamie		    &optiov[1].iov_len);
2169191673Sjamie		if (error) {
2170191673Sjamie			free(u_path, M_TEMP);
2171191673Sjamie			return (error);
2172191673Sjamie		}
2173191673Sjamie		optiov[2].iov_base = "host.hostname";
2174191673Sjamie		optiov[2].iov_len = sizeof("host.hostname");
2175191673Sjamie		optiov[3].iov_base = u_hostname;
2176191673Sjamie		error = copyinstr(PTRIN(j32.hostname), u_hostname,
2177191673Sjamie		    MAXHOSTNAMELEN, &optiov[3].iov_len);
2178191673Sjamie		if (error) {
2179191673Sjamie			free(u_path, M_TEMP);
2180191673Sjamie			return (error);
2181191673Sjamie		}
2182191673Sjamie		if (PTRIN(j32.jailname) != NULL) {
2183191673Sjamie			optiov[opt.uio_iovcnt].iov_base = "name";
2184191673Sjamie			optiov[opt.uio_iovcnt].iov_len = sizeof("name");
2185191673Sjamie			opt.uio_iovcnt++;
2186191673Sjamie			optiov[opt.uio_iovcnt].iov_base = u_name;
2187191673Sjamie			error = copyinstr(PTRIN(j32.jailname), u_name,
2188191673Sjamie			    MAXHOSTNAMELEN, &optiov[opt.uio_iovcnt].iov_len);
2189191673Sjamie			if (error) {
2190191673Sjamie				free(u_path, M_TEMP);
2191191673Sjamie				return (error);
2192191673Sjamie			}
2193191673Sjamie			opt.uio_iovcnt++;
2194191673Sjamie		}
2195191673Sjamie#ifdef INET
2196191673Sjamie		optiov[opt.uio_iovcnt].iov_base = "ip4.addr";
2197191673Sjamie		optiov[opt.uio_iovcnt].iov_len = sizeof("ip4.addr");
2198191673Sjamie		opt.uio_iovcnt++;
2199191673Sjamie		optiov[opt.uio_iovcnt].iov_base = u_ip4;
2200191673Sjamie		optiov[opt.uio_iovcnt].iov_len =
2201191673Sjamie		    j32.ip4s * sizeof(struct in_addr);
2202191673Sjamie		error = copyin(PTRIN(j32.ip4), u_ip4,
2203191673Sjamie		    optiov[opt.uio_iovcnt].iov_len);
2204191673Sjamie		if (error) {
2205191673Sjamie			free(u_path, M_TEMP);
2206191673Sjamie			return (error);
2207191673Sjamie		}
2208191673Sjamie		opt.uio_iovcnt++;
2209191673Sjamie#endif
2210191673Sjamie#ifdef INET6
2211191673Sjamie		optiov[opt.uio_iovcnt].iov_base = "ip6.addr";
2212191673Sjamie		optiov[opt.uio_iovcnt].iov_len = sizeof("ip6.addr");
2213191673Sjamie		opt.uio_iovcnt++;
2214191673Sjamie		optiov[opt.uio_iovcnt].iov_base = u_ip6;
2215191673Sjamie		optiov[opt.uio_iovcnt].iov_len =
2216191673Sjamie		    j32.ip6s * sizeof(struct in6_addr);
2217191673Sjamie		error = copyin(PTRIN(j32.ip6), u_ip6,
2218191673Sjamie		    optiov[opt.uio_iovcnt].iov_len);
2219191673Sjamie		if (error) {
2220191673Sjamie			free(u_path, M_TEMP);
2221191673Sjamie			return (error);
2222191673Sjamie		}
2223191673Sjamie		opt.uio_iovcnt++;
2224191673Sjamie#endif
2225185435Sbz		break;
2226185435Sbz	}
2227185435Sbz
2228185435Sbz	default:
2229185435Sbz		/* Sci-Fi jails are not supported, sorry. */
2230185435Sbz		return (EINVAL);
2231185435Sbz	}
2232191673Sjamie	error = kern_jail_set(td, &opt, JAIL_CREATE | JAIL_ATTACH);
2233191673Sjamie	free(u_path, M_TEMP);
2234191673Sjamie	return (error);
2235185435Sbz}
2236185435Sbz
2237185435Sbzint
2238191673Sjamiefreebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2239191673Sjamie{
2240191673Sjamie	struct uio *auio;
2241191673Sjamie	int error;
2242191673Sjamie
2243191673Sjamie	/* Check that we have an even number of iovecs. */
2244191673Sjamie	if (uap->iovcnt & 1)
2245191673Sjamie		return (EINVAL);
2246191673Sjamie
2247191673Sjamie	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2248191673Sjamie	if (error)
2249191673Sjamie		return (error);
2250191673Sjamie	error = kern_jail_set(td, auio, uap->flags);
2251191673Sjamie	free(auio, M_IOV);
2252191673Sjamie	return (error);
2253191673Sjamie}
2254191673Sjamie
2255191673Sjamieint
2256191673Sjamiefreebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2257191673Sjamie{
2258191673Sjamie	struct iovec32 iov32;
2259191673Sjamie	struct uio *auio;
2260191673Sjamie	int error, i;
2261191673Sjamie
2262191673Sjamie	/* Check that we have an even number of iovecs. */
2263191673Sjamie	if (uap->iovcnt & 1)
2264191673Sjamie		return (EINVAL);
2265191673Sjamie
2266191673Sjamie	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2267191673Sjamie	if (error)
2268191673Sjamie		return (error);
2269191673Sjamie	error = kern_jail_get(td, auio, uap->flags);
2270191673Sjamie	if (error == 0)
2271191673Sjamie		for (i = 0; i < uap->iovcnt; i++) {
2272191673Sjamie			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2273191673Sjamie			CP(auio->uio_iov[i], iov32, iov_len);
2274191673Sjamie			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2275191673Sjamie			if (error != 0)
2276191673Sjamie				break;
2277191673Sjamie		}
2278191673Sjamie	free(auio, M_IOV);
2279191673Sjamie	return (error);
2280191673Sjamie}
2281191673Sjamie
2282191673Sjamieint
2283119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
2284100384Speter{
2285113859Sjhb	struct sigaction32 s32;
2286113859Sjhb	struct sigaction sa, osa, *sap;
2287100384Speter	int error;
2288100384Speter
2289113859Sjhb	if (uap->act) {
2290113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
2291100384Speter		if (error)
2292100384Speter			return (error);
2293113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
2294113859Sjhb		CP(s32, sa, sa_flags);
2295113859Sjhb		CP(s32, sa, sa_mask);
2296113859Sjhb		sap = &sa;
2297113859Sjhb	} else
2298113859Sjhb		sap = NULL;
2299113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2300146583Sps	if (error == 0 && uap->oact != NULL) {
2301113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
2302113859Sjhb		CP(osa, s32, sa_flags);
2303113859Sjhb		CP(osa, s32, sa_mask);
2304113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
2305100384Speter	}
2306100384Speter	return (error);
2307100384Speter}
2308100384Speter
2309114987Speter#ifdef COMPAT_FREEBSD4
2310114987Speterint
2311119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
2312119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
2313114987Speter{
2314114987Speter	struct sigaction32 s32;
2315114987Speter	struct sigaction sa, osa, *sap;
2316114987Speter	int error;
2317114987Speter
2318114987Speter	if (uap->act) {
2319114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
2320114987Speter		if (error)
2321114987Speter			return (error);
2322114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
2323114987Speter		CP(s32, sa, sa_flags);
2324114987Speter		CP(s32, sa, sa_mask);
2325114987Speter		sap = &sa;
2326114987Speter	} else
2327114987Speter		sap = NULL;
2328114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2329146583Sps	if (error == 0 && uap->oact != NULL) {
2330114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
2331114987Speter		CP(osa, s32, sa_flags);
2332114987Speter		CP(osa, s32, sa_mask);
2333114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
2334114987Speter	}
2335114987Speter	return (error);
2336114987Speter}
2337114987Speter#endif
2338114987Speter
2339151582Sps#ifdef COMPAT_43
2340151720Speterstruct osigaction32 {
2341151582Sps	u_int32_t	sa_u;
2342151582Sps	osigset_t	sa_mask;
2343151582Sps	int		sa_flags;
2344151582Sps};
2345151582Sps
2346151582Sps#define	ONSIG	32
2347151582Sps
2348140481Spsint
2349151720Speterofreebsd32_sigaction(struct thread *td,
2350151720Speter			     struct ofreebsd32_sigaction_args *uap)
2351151582Sps{
2352151720Speter	struct osigaction32 s32;
2353151582Sps	struct sigaction sa, osa, *sap;
2354151582Sps	int error;
2355151582Sps
2356151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
2357151582Sps		return (EINVAL);
2358151582Sps
2359151582Sps	if (uap->nsa) {
2360151582Sps		error = copyin(uap->nsa, &s32, sizeof(s32));
2361151582Sps		if (error)
2362151582Sps			return (error);
2363151582Sps		sa.sa_handler = PTRIN(s32.sa_u);
2364151582Sps		CP(s32, sa, sa_flags);
2365151582Sps		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2366151582Sps		sap = &sa;
2367151582Sps	} else
2368151582Sps		sap = NULL;
2369151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2370151582Sps	if (error == 0 && uap->osa != NULL) {
2371151582Sps		s32.sa_u = PTROUT(osa.sa_handler);
2372151582Sps		CP(osa, s32, sa_flags);
2373151582Sps		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2374151582Sps		error = copyout(&s32, uap->osa, sizeof(s32));
2375151582Sps	}
2376151582Sps	return (error);
2377151582Sps}
2378151582Sps
2379151582Spsint
2380151720Speterofreebsd32_sigprocmask(struct thread *td,
2381151720Speter			       struct ofreebsd32_sigprocmask_args *uap)
2382151582Sps{
2383151582Sps	sigset_t set, oset;
2384151582Sps	int error;
2385151582Sps
2386151582Sps	OSIG2SIG(uap->mask, set);
2387151582Sps	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
2388151582Sps	SIG2OSIG(oset, td->td_retval[0]);
2389151582Sps	return (error);
2390151582Sps}
2391151582Sps
2392151582Spsint
2393151720Speterofreebsd32_sigpending(struct thread *td,
2394151720Speter			      struct ofreebsd32_sigpending_args *uap)
2395151582Sps{
2396151582Sps	struct proc *p = td->td_proc;
2397151582Sps	sigset_t siglist;
2398151582Sps
2399151582Sps	PROC_LOCK(p);
2400151582Sps	siglist = p->p_siglist;
2401151582Sps	SIGSETOR(siglist, td->td_siglist);
2402151582Sps	PROC_UNLOCK(p);
2403151582Sps	SIG2OSIG(siglist, td->td_retval[0]);
2404151582Sps	return (0);
2405151582Sps}
2406151582Sps
2407151582Spsstruct sigvec32 {
2408151582Sps	u_int32_t	sv_handler;
2409151582Sps	int		sv_mask;
2410151582Sps	int		sv_flags;
2411151582Sps};
2412151582Sps
2413151582Spsint
2414151720Speterofreebsd32_sigvec(struct thread *td,
2415151720Speter			  struct ofreebsd32_sigvec_args *uap)
2416151582Sps{
2417151582Sps	struct sigvec32 vec;
2418151582Sps	struct sigaction sa, osa, *sap;
2419151582Sps	int error;
2420151582Sps
2421151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
2422151582Sps		return (EINVAL);
2423151582Sps
2424151582Sps	if (uap->nsv) {
2425151582Sps		error = copyin(uap->nsv, &vec, sizeof(vec));
2426151582Sps		if (error)
2427151582Sps			return (error);
2428151582Sps		sa.sa_handler = PTRIN(vec.sv_handler);
2429151582Sps		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2430151582Sps		sa.sa_flags = vec.sv_flags;
2431151582Sps		sa.sa_flags ^= SA_RESTART;
2432151582Sps		sap = &sa;
2433151582Sps	} else
2434151582Sps		sap = NULL;
2435151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2436151582Sps	if (error == 0 && uap->osv != NULL) {
2437151582Sps		vec.sv_handler = PTROUT(osa.sa_handler);
2438151582Sps		SIG2OSIG(osa.sa_mask, vec.sv_mask);
2439151582Sps		vec.sv_flags = osa.sa_flags;
2440151582Sps		vec.sv_flags &= ~SA_NOCLDWAIT;
2441151582Sps		vec.sv_flags ^= SA_RESTART;
2442151582Sps		error = copyout(&vec, uap->osv, sizeof(vec));
2443151582Sps	}
2444151582Sps	return (error);
2445151582Sps}
2446151582Sps
2447151582Spsint
2448151720Speterofreebsd32_sigblock(struct thread *td,
2449151720Speter			    struct ofreebsd32_sigblock_args *uap)
2450151582Sps{
2451151582Sps	struct proc *p = td->td_proc;
2452151582Sps	sigset_t set;
2453151582Sps
2454151582Sps	OSIG2SIG(uap->mask, set);
2455151582Sps	SIG_CANTMASK(set);
2456151582Sps	PROC_LOCK(p);
2457151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2458151582Sps	SIGSETOR(td->td_sigmask, set);
2459151582Sps	PROC_UNLOCK(p);
2460151582Sps	return (0);
2461151582Sps}
2462151582Sps
2463151582Spsint
2464151720Speterofreebsd32_sigsetmask(struct thread *td,
2465151720Speter			      struct ofreebsd32_sigsetmask_args *uap)
2466151582Sps{
2467151582Sps	struct proc *p = td->td_proc;
2468151582Sps	sigset_t set;
2469151582Sps
2470151582Sps	OSIG2SIG(uap->mask, set);
2471151582Sps	SIG_CANTMASK(set);
2472151582Sps	PROC_LOCK(p);
2473151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2474151582Sps	SIGSETLO(td->td_sigmask, set);
2475151582Sps	signotify(td);
2476151582Sps	PROC_UNLOCK(p);
2477151582Sps	return (0);
2478151582Sps}
2479151582Sps
2480151582Spsint
2481151720Speterofreebsd32_sigsuspend(struct thread *td,
2482151720Speter			      struct ofreebsd32_sigsuspend_args *uap)
2483151582Sps{
2484151582Sps	struct proc *p = td->td_proc;
2485151582Sps	sigset_t mask;
2486151582Sps
2487151582Sps	PROC_LOCK(p);
2488151582Sps	td->td_oldsigmask = td->td_sigmask;
2489151582Sps	td->td_pflags |= TDP_OLDMASK;
2490151582Sps	OSIG2SIG(uap->mask, mask);
2491151582Sps	SIG_CANTMASK(mask);
2492151582Sps	SIGSETLO(td->td_sigmask, mask);
2493151582Sps	signotify(td);
2494151582Sps	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2495151582Sps		/* void */;
2496151582Sps	PROC_UNLOCK(p);
2497151582Sps	/* always return EINTR rather than ERESTART... */
2498151582Sps	return (EINTR);
2499151582Sps}
2500151582Sps
2501151582Spsstruct sigstack32 {
2502151582Sps	u_int32_t	ss_sp;
2503151582Sps	int		ss_onstack;
2504151582Sps};
2505151582Sps
2506151582Spsint
2507151720Speterofreebsd32_sigstack(struct thread *td,
2508151720Speter			    struct ofreebsd32_sigstack_args *uap)
2509151582Sps{
2510151582Sps	struct sigstack32 s32;
2511151582Sps	struct sigstack nss, oss;
2512170870Smjacob	int error = 0, unss;
2513151582Sps
2514151582Sps	if (uap->nss != NULL) {
2515151582Sps		error = copyin(uap->nss, &s32, sizeof(s32));
2516151582Sps		if (error)
2517151582Sps			return (error);
2518151582Sps		nss.ss_sp = PTRIN(s32.ss_sp);
2519151582Sps		CP(s32, nss, ss_onstack);
2520170870Smjacob		unss = 1;
2521170870Smjacob	} else {
2522170870Smjacob		unss = 0;
2523151582Sps	}
2524151582Sps	oss.ss_sp = td->td_sigstk.ss_sp;
2525151582Sps	oss.ss_onstack = sigonstack(cpu_getstack(td));
2526170870Smjacob	if (unss) {
2527151582Sps		td->td_sigstk.ss_sp = nss.ss_sp;
2528151582Sps		td->td_sigstk.ss_size = 0;
2529170870Smjacob		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2530151582Sps		td->td_pflags |= TDP_ALTSTACK;
2531151582Sps	}
2532151582Sps	if (uap->oss != NULL) {
2533151582Sps		s32.ss_sp = PTROUT(oss.ss_sp);
2534151582Sps		CP(oss, s32, ss_onstack);
2535151582Sps		error = copyout(&s32, uap->oss, sizeof(s32));
2536151582Sps	}
2537151582Sps	return (error);
2538151582Sps}
2539151582Sps#endif
2540151582Sps
2541151582Spsint
2542140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2543140481Sps{
2544140481Sps	struct timespec32 rmt32, rqt32;
2545140481Sps	struct timespec rmt, rqt;
2546140481Sps	int error;
2547140481Sps
2548151355Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2549140481Sps	if (error)
2550140481Sps		return (error);
2551140481Sps
2552140481Sps	CP(rqt32, rqt, tv_sec);
2553140481Sps	CP(rqt32, rqt, tv_nsec);
2554140481Sps
2555140481Sps	if (uap->rmtp &&
2556140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2557140481Sps		return (EFAULT);
2558140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
2559140481Sps	if (error && uap->rmtp) {
2560140481Sps		int error2;
2561140481Sps
2562140481Sps		CP(rmt, rmt32, tv_sec);
2563140481Sps		CP(rmt, rmt32, tv_nsec);
2564140481Sps
2565151355Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2566140481Sps		if (error2)
2567140481Sps			error = error2;
2568140481Sps	}
2569140481Sps	return (error);
2570140481Sps}
2571140481Sps
2572151357Spsint
2573151357Spsfreebsd32_clock_gettime(struct thread *td,
2574151357Sps			struct freebsd32_clock_gettime_args *uap)
2575151357Sps{
2576151357Sps	struct timespec	ats;
2577151357Sps	struct timespec32 ats32;
2578151357Sps	int error;
2579151357Sps
2580151357Sps	error = kern_clock_gettime(td, uap->clock_id, &ats);
2581151357Sps	if (error == 0) {
2582151357Sps		CP(ats, ats32, tv_sec);
2583151357Sps		CP(ats, ats32, tv_nsec);
2584151357Sps		error = copyout(&ats32, uap->tp, sizeof(ats32));
2585151357Sps	}
2586151357Sps	return (error);
2587151357Sps}
2588151357Sps
2589151357Spsint
2590151357Spsfreebsd32_clock_settime(struct thread *td,
2591151357Sps			struct freebsd32_clock_settime_args *uap)
2592151357Sps{
2593151357Sps	struct timespec	ats;
2594151357Sps	struct timespec32 ats32;
2595151357Sps	int error;
2596151357Sps
2597151357Sps	error = copyin(uap->tp, &ats32, sizeof(ats32));
2598151357Sps	if (error)
2599151357Sps		return (error);
2600151357Sps	CP(ats32, ats, tv_sec);
2601151357Sps	CP(ats32, ats, tv_nsec);
2602151357Sps
2603151357Sps	return (kern_clock_settime(td, uap->clock_id, &ats));
2604151357Sps}
2605151357Sps
2606151357Spsint
2607151357Spsfreebsd32_clock_getres(struct thread *td,
2608151357Sps		       struct freebsd32_clock_getres_args *uap)
2609151357Sps{
2610151357Sps	struct timespec	ts;
2611151357Sps	struct timespec32 ts32;
2612151357Sps	int error;
2613151357Sps
2614151357Sps	if (uap->tp == NULL)
2615151357Sps		return (0);
2616151357Sps	error = kern_clock_getres(td, uap->clock_id, &ts);
2617151357Sps	if (error == 0) {
2618151357Sps		CP(ts, ts32, tv_sec);
2619151357Sps		CP(ts, ts32, tv_nsec);
2620151357Sps		error = copyout(&ts32, uap->tp, sizeof(ts32));
2621151357Sps	}
2622151357Sps	return (error);
2623151357Sps}
2624151357Sps
2625162551Sdavidxuint
2626162551Sdavidxufreebsd32_thr_new(struct thread *td,
2627162551Sdavidxu		  struct freebsd32_thr_new_args *uap)
2628162551Sdavidxu{
2629162551Sdavidxu	struct thr_param32 param32;
2630162551Sdavidxu	struct thr_param param;
2631162551Sdavidxu	int error;
2632162551Sdavidxu
2633162551Sdavidxu	if (uap->param_size < 0 ||
2634162551Sdavidxu	    uap->param_size > sizeof(struct thr_param32))
2635162551Sdavidxu		return (EINVAL);
2636162551Sdavidxu	bzero(&param, sizeof(struct thr_param));
2637162551Sdavidxu	bzero(&param32, sizeof(struct thr_param32));
2638162551Sdavidxu	error = copyin(uap->param, &param32, uap->param_size);
2639162551Sdavidxu	if (error != 0)
2640162551Sdavidxu		return (error);
2641162551Sdavidxu	param.start_func = PTRIN(param32.start_func);
2642162551Sdavidxu	param.arg = PTRIN(param32.arg);
2643162551Sdavidxu	param.stack_base = PTRIN(param32.stack_base);
2644162551Sdavidxu	param.stack_size = param32.stack_size;
2645162551Sdavidxu	param.tls_base = PTRIN(param32.tls_base);
2646162551Sdavidxu	param.tls_size = param32.tls_size;
2647162551Sdavidxu	param.child_tid = PTRIN(param32.child_tid);
2648162551Sdavidxu	param.parent_tid = PTRIN(param32.parent_tid);
2649162551Sdavidxu	param.flags = param32.flags;
2650162551Sdavidxu	param.rtp = PTRIN(param32.rtp);
2651162551Sdavidxu	param.spare[0] = PTRIN(param32.spare[0]);
2652162551Sdavidxu	param.spare[1] = PTRIN(param32.spare[1]);
2653162551Sdavidxu	param.spare[2] = PTRIN(param32.spare[2]);
2654162551Sdavidxu
2655162551Sdavidxu	return (kern_thr_new(td, &param));
2656162551Sdavidxu}
2657162551Sdavidxu
2658162551Sdavidxuint
2659162551Sdavidxufreebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2660162551Sdavidxu{
2661162551Sdavidxu	struct timespec32 ts32;
2662162551Sdavidxu	struct timespec ts, *tsp;
2663162551Sdavidxu	int error;
2664162551Sdavidxu
2665162551Sdavidxu	error = 0;
2666162551Sdavidxu	tsp = NULL;
2667162551Sdavidxu	if (uap->timeout != NULL) {
2668162551Sdavidxu		error = copyin((const void *)uap->timeout, (void *)&ts32,
2669162551Sdavidxu		    sizeof(struct timespec32));
2670162551Sdavidxu		if (error != 0)
2671162551Sdavidxu			return (error);
2672162551Sdavidxu		ts.tv_sec = ts32.tv_sec;
2673162551Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2674162551Sdavidxu		tsp = &ts;
2675162551Sdavidxu	}
2676162551Sdavidxu	return (kern_thr_suspend(td, tsp));
2677162551Sdavidxu}
2678162551Sdavidxu
2679163018Sdavidxuvoid
2680163018Sdavidxusiginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2681163018Sdavidxu{
2682163018Sdavidxu	bzero(dst, sizeof(*dst));
2683163018Sdavidxu	dst->si_signo = src->si_signo;
2684163018Sdavidxu	dst->si_errno = src->si_errno;
2685163018Sdavidxu	dst->si_code = src->si_code;
2686163018Sdavidxu	dst->si_pid = src->si_pid;
2687163018Sdavidxu	dst->si_uid = src->si_uid;
2688163018Sdavidxu	dst->si_status = src->si_status;
2689184829Speter	dst->si_addr = (uintptr_t)src->si_addr;
2690163018Sdavidxu	dst->si_value.sigval_int = src->si_value.sival_int;
2691163018Sdavidxu	dst->si_timerid = src->si_timerid;
2692163018Sdavidxu	dst->si_overrun = src->si_overrun;
2693163018Sdavidxu}
2694163018Sdavidxu
2695163018Sdavidxuint
2696163018Sdavidxufreebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2697163018Sdavidxu{
2698163018Sdavidxu	struct timespec32 ts32;
2699163018Sdavidxu	struct timespec ts;
2700163018Sdavidxu	struct timespec *timeout;
2701163018Sdavidxu	sigset_t set;
2702163018Sdavidxu	ksiginfo_t ksi;
2703163018Sdavidxu	struct siginfo32 si32;
2704163018Sdavidxu	int error;
2705163018Sdavidxu
2706163018Sdavidxu	if (uap->timeout) {
2707163018Sdavidxu		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2708163018Sdavidxu		if (error)
2709163018Sdavidxu			return (error);
2710163018Sdavidxu		ts.tv_sec = ts32.tv_sec;
2711163018Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2712163018Sdavidxu		timeout = &ts;
2713163018Sdavidxu	} else
2714163018Sdavidxu		timeout = NULL;
2715163018Sdavidxu
2716163018Sdavidxu	error = copyin(uap->set, &set, sizeof(set));
2717163018Sdavidxu	if (error)
2718163018Sdavidxu		return (error);
2719163018Sdavidxu
2720163018Sdavidxu	error = kern_sigtimedwait(td, set, &ksi, timeout);
2721163018Sdavidxu	if (error)
2722163018Sdavidxu		return (error);
2723163018Sdavidxu
2724163018Sdavidxu	if (uap->info) {
2725163018Sdavidxu		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2726163018Sdavidxu		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2727163018Sdavidxu	}
2728163018Sdavidxu
2729163018Sdavidxu	if (error == 0)
2730163018Sdavidxu		td->td_retval[0] = ksi.ksi_signo;
2731163018Sdavidxu	return (error);
2732163018Sdavidxu}
2733163018Sdavidxu
2734163018Sdavidxu/*
2735163018Sdavidxu * MPSAFE
2736163018Sdavidxu */
2737163018Sdavidxuint
2738163018Sdavidxufreebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2739163018Sdavidxu{
2740163018Sdavidxu	ksiginfo_t ksi;
2741163018Sdavidxu	struct siginfo32 si32;
2742163018Sdavidxu	sigset_t set;
2743163018Sdavidxu	int error;
2744163018Sdavidxu
2745163018Sdavidxu	error = copyin(uap->set, &set, sizeof(set));
2746163018Sdavidxu	if (error)
2747163018Sdavidxu		return (error);
2748163018Sdavidxu
2749163018Sdavidxu	error = kern_sigtimedwait(td, set, &ksi, NULL);
2750163018Sdavidxu	if (error)
2751163018Sdavidxu		return (error);
2752163018Sdavidxu
2753163018Sdavidxu	if (uap->info) {
2754163018Sdavidxu		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2755163018Sdavidxu		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2756163018Sdavidxu	}
2757163018Sdavidxu	if (error == 0)
2758163018Sdavidxu		td->td_retval[0] = ksi.ksi_signo;
2759163018Sdavidxu	return (error);
2760163018Sdavidxu}
2761163018Sdavidxu
2762180433Sbrooksint
2763180433Sbrooksfreebsd32_cpuset_setid(struct thread *td,
2764180433Sbrooks    struct freebsd32_cpuset_setid_args *uap)
2765180433Sbrooks{
2766180433Sbrooks	struct cpuset_setid_args ap;
2767180433Sbrooks
2768180433Sbrooks	ap.which = uap->which;
2769180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2770180433Sbrooks	ap.setid = uap->setid;
2771180433Sbrooks
2772180436Sbrooks	return (cpuset_setid(td, &ap));
2773180433Sbrooks}
2774180433Sbrooks
2775180433Sbrooksint
2776180433Sbrooksfreebsd32_cpuset_getid(struct thread *td,
2777180433Sbrooks    struct freebsd32_cpuset_getid_args *uap)
2778180433Sbrooks{
2779180433Sbrooks	struct cpuset_getid_args ap;
2780180433Sbrooks
2781180433Sbrooks	ap.level = uap->level;
2782180433Sbrooks	ap.which = uap->which;
2783180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2784180433Sbrooks	ap.setid = uap->setid;
2785180433Sbrooks
2786180436Sbrooks	return (cpuset_getid(td, &ap));
2787180433Sbrooks}
2788180433Sbrooks
2789180433Sbrooksint
2790180433Sbrooksfreebsd32_cpuset_getaffinity(struct thread *td,
2791180433Sbrooks    struct freebsd32_cpuset_getaffinity_args *uap)
2792180433Sbrooks{
2793180433Sbrooks	struct cpuset_getaffinity_args ap;
2794180433Sbrooks
2795180433Sbrooks	ap.level = uap->level;
2796180433Sbrooks	ap.which = uap->which;
2797180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2798180433Sbrooks	ap.cpusetsize = uap->cpusetsize;
2799180433Sbrooks	ap.mask = uap->mask;
2800180433Sbrooks
2801180436Sbrooks	return (cpuset_getaffinity(td, &ap));
2802180433Sbrooks}
2803180433Sbrooks
2804180433Sbrooksint
2805180433Sbrooksfreebsd32_cpuset_setaffinity(struct thread *td,
2806180433Sbrooks    struct freebsd32_cpuset_setaffinity_args *uap)
2807180433Sbrooks{
2808180433Sbrooks	struct cpuset_setaffinity_args ap;
2809180433Sbrooks
2810180433Sbrooks	ap.level = uap->level;
2811180433Sbrooks	ap.which = uap->which;
2812180433Sbrooks	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2813180433Sbrooks	ap.cpusetsize = uap->cpusetsize;
2814180433Sbrooks	ap.mask = uap->mask;
2815180433Sbrooks
2816180436Sbrooks	return (cpuset_setaffinity(td, &ap));
2817180433Sbrooks}
2818180433Sbrooks
2819183188Sobrienint
2820183188Sobrienfreebsd32_nmount(struct thread *td,
2821183188Sobrien    struct freebsd32_nmount_args /* {
2822183188Sobrien    	struct iovec *iovp;
2823183188Sobrien    	unsigned int iovcnt;
2824183188Sobrien    	int flags;
2825183188Sobrien    } */ *uap)
2826183188Sobrien{
2827183188Sobrien	struct uio *auio;
2828189290Sjamie	int error;
2829183188Sobrien
2830183188Sobrien	AUDIT_ARG(fflags, uap->flags);
2831183188Sobrien
2832183188Sobrien	/*
2833183188Sobrien	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2834183188Sobrien	 * userspace to set this flag, but we must filter it out if we want
2835183188Sobrien	 * MNT_UPDATE on the root file system to work.
2836183188Sobrien	 * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
2837183188Sobrien	 */
2838183188Sobrien	uap->flags &= ~MNT_ROOTFS;
2839183188Sobrien
2840183188Sobrien	/*
2841183188Sobrien	 * check that we have an even number of iovec's
2842183188Sobrien	 * and that we have at least two options.
2843183188Sobrien	 */
2844183188Sobrien	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2845183188Sobrien		return (EINVAL);
2846183188Sobrien
2847183188Sobrien	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2848183188Sobrien	if (error)
2849183188Sobrien		return (error);
2850189290Sjamie	error = vfs_donmount(td, uap->flags, auio);
2851183188Sobrien
2852183188Sobrien	free(auio, M_IOV);
2853183188Sobrien	return error;
2854183188Sobrien}
2855183188Sobrien
2856100384Speter#if 0
2857100384Speterint
2858119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2859100384Speter{
2860100384Speter	struct yyy32 *p32, s32;
2861100384Speter	struct yyy *p = NULL, s;
2862183044Sobrien	struct xxx_arg ap;
2863183044Sobrien	int error;
2864100384Speter
2865147654Sjhb	if (uap->zzz) {
2866147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
2867100384Speter		if (error)
2868100384Speter			return (error);
2869100384Speter		/* translate in */
2870147654Sjhb		p = &s;
2871100384Speter	}
2872147654Sjhb	error = kern_xxx(td, p);
2873100384Speter	if (error)
2874100384Speter		return (error);
2875147654Sjhb	if (uap->zzz) {
2876100384Speter		/* translate out */
2877100384Speter		error = copyout(&s32, p32, sizeof(s32));
2878100384Speter	}
2879100384Speter	return (error);
2880100384Speter}
2881100384Speter#endif
2882183365Sjhb
2883183365Sjhbint
2884183365Sjhbsyscall32_register(int *offset, struct sysent *new_sysent,
2885183365Sjhb    struct sysent *old_sysent)
2886183365Sjhb{
2887183365Sjhb	if (*offset == NO_SYSCALL) {
2888183365Sjhb		int i;
2889183365Sjhb
2890183365Sjhb		for (i = 1; i < SYS_MAXSYSCALL; ++i)
2891183365Sjhb			if (freebsd32_sysent[i].sy_call ==
2892183365Sjhb			    (sy_call_t *)lkmnosys)
2893183365Sjhb				break;
2894183365Sjhb		if (i == SYS_MAXSYSCALL)
2895183365Sjhb			return (ENFILE);
2896183365Sjhb		*offset = i;
2897183365Sjhb	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
2898183365Sjhb		return (EINVAL);
2899183365Sjhb	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
2900183365Sjhb	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
2901183365Sjhb		return (EEXIST);
2902183365Sjhb
2903183365Sjhb	*old_sysent = freebsd32_sysent[*offset];
2904183365Sjhb	freebsd32_sysent[*offset] = *new_sysent;
2905183365Sjhb	return 0;
2906183365Sjhb}
2907183365Sjhb
2908183365Sjhbint
2909183365Sjhbsyscall32_deregister(int *offset, struct sysent *old_sysent)
2910183365Sjhb{
2911183365Sjhb
2912183365Sjhb	if (*offset)
2913183365Sjhb		freebsd32_sysent[*offset] = *old_sysent;
2914183365Sjhb	return 0;
2915183365Sjhb}
2916183365Sjhb
2917183365Sjhbint
2918183365Sjhbsyscall32_module_handler(struct module *mod, int what, void *arg)
2919183365Sjhb{
2920183365Sjhb	struct syscall_module_data *data = (struct syscall_module_data*)arg;
2921183365Sjhb	modspecific_t ms;
2922183365Sjhb	int error;
2923183365Sjhb
2924183365Sjhb	switch (what) {
2925183365Sjhb	case MOD_LOAD:
2926183365Sjhb		error = syscall32_register(data->offset, data->new_sysent,
2927183365Sjhb		    &data->old_sysent);
2928183365Sjhb		if (error) {
2929183365Sjhb			/* Leave a mark so we know to safely unload below. */
2930183365Sjhb			data->offset = NULL;
2931183365Sjhb			return error;
2932183365Sjhb		}
2933183365Sjhb		ms.intval = *data->offset;
2934183365Sjhb		MOD_XLOCK;
2935183365Sjhb		module_setspecific(mod, &ms);
2936183365Sjhb		MOD_XUNLOCK;
2937183365Sjhb		if (data->chainevh)
2938183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
2939183365Sjhb		return (error);
2940183365Sjhb	case MOD_UNLOAD:
2941183365Sjhb		/*
2942183365Sjhb		 * MOD_LOAD failed, so just return without calling the
2943183365Sjhb		 * chained handler since we didn't pass along the MOD_LOAD
2944183365Sjhb		 * event.
2945183365Sjhb		 */
2946183365Sjhb		if (data->offset == NULL)
2947183365Sjhb			return (0);
2948183365Sjhb		if (data->chainevh) {
2949183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
2950183365Sjhb			if (error)
2951183365Sjhb				return (error);
2952183365Sjhb		}
2953185589Sjhb		error = syscall32_deregister(data->offset, &data->old_sysent);
2954183365Sjhb		return (error);
2955183365Sjhb	default:
2956183365Sjhb		error = EOPNOTSUPP;
2957183365Sjhb		if (data->chainevh)
2958183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
2959183365Sjhb		return (error);
2960183365Sjhb	}
2961183365Sjhb}
2962