code:
/*	$OpenBSD: linux_sched.h,v 1.4 2011/04/05 22:54:31 pirofti Exp $	*/
/*	$NetBSD: linux_sched.h,v 1.1 1999/05/12 19:49:09 thorpej Exp $	*/

/*-
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SCHED_H_
#define	_LINUX_SCHED_H_

/*
 * Flags passed to the Linux __clone(2) system call.
 */
#define	LINUX_CLONE_CSIGNAL	0x000000ff	/* signal to be sent at exit */
#define	LINUX_CLONE_VM		0x00000100	/* share address space */
#define	LINUX_CLONE_FS		0x00000200	/* share "file system" info */
#define	LINUX_CLONE_FILES	0x00000400	/* share file descriptors */
#define	LINUX_CLONE_SIGHAND	0x00000800	/* share signal actions */
#define	LINUX_CLONE_PID		0x00001000	/* no longer supported */
#define	LINUX_CLONE_PTRACE	0x00002000	/* ptrace(2) continues on
						   child */
#define	LINUX_CLONE_VFORK	0x00004000	/* parent blocks until child
						   exits */
#define	LINUX_CLONE_PARENT	0x00008000	/* create sibling, not child */
#define	LINUX_CLONE_THREAD	0x00010000	/* new thread */
#define	LINUX_CLONE_NEWNS	0x00020000	/* don't share mount changes */
#define	LINUX_CLONE_SYSVSEM	0x00040000	/* share sysV SEM_UNDO */
#define	LINUX_CLONE_SETTLS	0x00080000	/* new thread-local-storage? */
#define	LINUX_CLONE_PARENT_SETTID  0x00100000	/* set the TID in the parent */
#define	LINUX_CLONE_CHILD_CLEARTID 0x00200000	/* clear the TID in the child */
#define	LINUX_CLONE_DETACHED	0x00400000	/* Unused, ignored */
#define	LINUX_CLONE_UNTRACED	0x00800000	/* undo LINUX_CLONE_PTRACE */
#define	LINUX_CLONE_CHILD_SETTID 0x01000000	/* set the TID in the child */
#define	LINUX_CLONE_STOPPED	0x02000000	/* Start in stopped state */

struct linux_sched_param {
	int	sched_priority;
};

#define LINUX_SCHED_OTHER	0
#define LINUX_SCHED_FIFO	1
#define LINUX_SCHED_RR		2

#endif /* _LINUX_SCHED_H_ */


code:
/*	$OpenBSD: linux_sem.h,v 1.3 2011/04/05 22:54:31 pirofti Exp $	*/
/*	$NetBSD: linux_sem.h,v 1.1 1995/08/15 21:14:35 fvdl Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SEM_H_
#define _LINUX_SEM_H_

/*
 * Operations for semctl(2), in addition to IPC_STAT and IPC_SET
 */
#define LINUX_GETPID  11
#define LINUX_GETVAL  12
#define LINUX_GETALL  13
#define LINUX_GETNCNT 14
#define LINUX_GETZCNT 15
#define LINUX_SETVAL  16
#define LINUX_SETALL  17

/*
 * Linux semid_ds structure. Internally used pointer fields are not
 * important to us and have been changed to void *
 */

struct linux_semid_ds {
	struct linux_ipc_perm	 l_sem_perm;
	linux_time_t		 l_sem_otime;
	linux_time_t		 l_sem_ctime;
	void 			*l_sem_base;
	void			*l_eventn;
	void			*l_eventz;
	void			*l_undo;
	ushort			 l_sem_nsems;
};

union linux_semun {
	int			 l_val;
	struct linux_semid_ds	*l_buf;
	ushort			*l_array;
	void			*l___buf;	/* For unsupported IPC_INFO */
	void			*l___pad;
};

#endif /* _LINUX_SEM_H_ */

license: unknown


code:
/*	$OpenBSD: linux_shm.h,v 1.3 2011/04/05 22:54:31 pirofti Exp $	*/
/*	$NetBSD: linux_shm.h,v 1.1 1995/02/28 23:25:57 fvdl Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SHM_H_
#define _LINUX_SHM_H_

/*
 * shm segment control structure
 */
struct linux_shmid_ds {
	struct linux_ipc_perm	l_shm_perm;
	int			l_shm_segsz;
	linux_time_t		l_shm_atime;
	linux_time_t		l_shm_dtime;
	linux_time_t		l_shm_ctime;
	ushort			l_shm_cpid;
	ushort			l_shm_lpid;
	short			l_shm_nattch;
	ushort			l_private1;
	void			*l_private2;
	void			*l_private3;
};

#define LINUX_SHM_RDONLY	0x1000
#define LINUX_SHM_RND		0x2000
#define LINUX_SHM_REMAP		0x4000

#define LINUX_SHM_LOCK		11
#define LINUX_SHM_UNLOCK	12
#define LINUX_SHM_STAT		13
#define LINUX_SHM_INFO		14

#endif /* _LINUX_SHM_H_ */


code:
/*	$OpenBSD: linux_signal.c,v 1.18 2015/02/09 13:41:24 pelikan Exp $	*/
/*	$NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/kernel.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
#include <sys/malloc.h>

#include <sys/syscallargs.h>

#include <compat/linux/linux_types.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_syscallargs.h>
#include <compat/linux/linux_util.h>

#define	sigemptyset(s)		memset((s), 0, sizeof(*(s)))
#define	sigismember(s, n)	(*(s) & sigmask(n))
#define	sigaddset(s, n)		(*(s) |= sigmask(n))

/* Locally used defines (in bsd<->linux conversion functions): */
#define	linux_sigmask(n)	(1 << ((n) - 1))
#define	linux_sigemptyset(s)	memset((s), 0, sizeof(*(s)))
#define	linux_sigismember(s, n)	((s)->sig[((n) - 1) / LINUX__NSIG_BPW]	\
					& (1 << ((n) - 1) % LINUX__NSIG_BPW))
#define	linux_sigaddset(s, n)	((s)->sig[((n) - 1) / LINUX__NSIG_BPW]	\
					|= (1 << ((n) - 1) % LINUX__NSIG_BPW))

int bsd_to_linux_sig[NSIG] = {
	0,
	LINUX_SIGHUP,
	LINUX_SIGINT,
	LINUX_SIGQUIT,
	LINUX_SIGILL,
	LINUX_SIGTRAP,
	LINUX_SIGABRT,
	LINUX_NSIG,		/* XXX Kludge to get RT signal #32 to work */
	LINUX_SIGFPE,
	LINUX_SIGKILL,
	LINUX_SIGBUS,
	LINUX_SIGSEGV,
	LINUX_NSIG + 1,			/* XXX Kludge to get RT signal #32 to work */
	LINUX_SIGPIPE,
	LINUX_SIGALRM,
	LINUX_SIGTERM,
	LINUX_SIGURG,
	LINUX_SIGSTOP,
	LINUX_SIGTSTP,
	LINUX_SIGCONT,
	LINUX_SIGCHLD,
	LINUX_SIGTTIN,
	LINUX_SIGTTOU,
	LINUX_SIGIO,
	LINUX_SIGXCPU,
	LINUX_SIGXFSZ,
	LINUX_SIGVTALRM,
	LINUX_SIGPROF,
	LINUX_SIGWINCH,
	0,			/* SIGINFO */
	LINUX_SIGUSR1,
	LINUX_SIGUSR2,
	0,			/* SIGTHR */
};

int linux_to_bsd_sig[LINUX__NSIG] = {
	0,
	SIGHUP,
	SIGINT,
	SIGQUIT,
	SIGILL,
	SIGTRAP,
	SIGABRT,
	SIGBUS,
	SIGFPE,
	SIGKILL,
	SIGUSR1,
	SIGSEGV,
	SIGUSR2,
	SIGPIPE,
	SIGALRM,
	SIGTERM,
	0,			/* SIGSTKFLT */
	SIGCHLD,
	SIGCONT,
	SIGSTOP,
	SIGTSTP,
	SIGTTIN,
	SIGTTOU,
	SIGURG,
	SIGXCPU,
	SIGXFSZ,
	SIGVTALRM,
	SIGPROF,
	SIGWINCH,
	SIGIO,
	0,			/* SIGUNUSED */
	0,
	SIGEMT,			/* XXX Gruesome hack for linuxthreads:       */
	SIGSYS,			/* Map 1st 2 RT signals onto ones we handle. */
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
};

/*
 * Convert between Linux and BSD signal sets.
 */
void
linux_old_to_bsd_sigset(lss, bss)
	const linux_old_sigset_t *lss;
	sigset_t *bss;
{
	linux_old_extra_to_bsd_sigset(lss, (const unsigned long *) 0, bss);
}

void
bsd_to_linux_old_sigset(bss, lss)
	const sigset_t *bss;
	linux_old_sigset_t *lss;
{
	bsd_to_linux_old_extra_sigset(bss, lss, (unsigned long *) 0);
}

void
linux_old_extra_to_bsd_sigset(lss, extra, bss)
	const linux_old_sigset_t *lss;
	const unsigned long *extra;
	sigset_t *bss;
{
	linux_sigset_t lsnew;

	/* convert old sigset to new sigset */
	linux_sigemptyset(&lsnew);
	lsnew.sig[0] = *lss;
	if (extra)
		bcopy(extra, &lsnew.sig[1],
			sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));

	linux_to_bsd_sigset(&lsnew, bss);
}

void
bsd_to_linux_old_extra_sigset(bss, lss, extra)
	const sigset_t *bss;
	linux_old_sigset_t *lss;
	unsigned long *extra;
{
	linux_sigset_t lsnew;

	bsd_to_linux_sigset(bss, &lsnew);

	/* convert new sigset to old sigset */
	*lss = lsnew.sig[0];
	if (extra)
		bcopy(&lsnew.sig[1], extra,
			sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
}

void
linux_to_bsd_sigset(lss, bss)
	const linux_sigset_t *lss;
	sigset_t *bss;
{
	int i, newsig;

	sigemptyset(bss);
	for (i = 1; i < LINUX__NSIG; i++) {
		if (linux_sigismember(lss, i)) {
			newsig = linux_to_bsd_sig[i];
			if (newsig)
				sigaddset(bss, newsig);
		}
	}
}

void
bsd_to_linux_sigset(bss, lss)
	const sigset_t *bss;
	linux_sigset_t *lss;
{
	int i, newsig;

	linux_sigemptyset(lss);
	for (i = 1; i < NSIG; i++) {
		if (sigismember(bss, i)) {
			newsig = bsd_to_linux_sig[i];
			if (newsig)
				linux_sigaddset(lss, newsig);
		}
	}
}

/*
 * Convert between Linux and BSD sigaction structures. Linux has
 * one extra field (sa_restorer) which we don't support.
 */
void
linux_old_to_bsd_sigaction(lsa, bsa)
	struct linux_old_sigaction *lsa;
	struct sigaction *bsa;
{

	bsa->sa_handler = lsa->sa__handler;
	linux_old_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
	bsa->sa_flags = 0;
	if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
		bsa->sa_flags |= SA_ONSTACK;
	if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
		bsa->sa_flags |= SA_RESTART;
	if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
		bsa->sa_flags |= SA_RESETHAND;
	if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
		bsa->sa_flags |= SA_NOCLDSTOP;
	if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
		bsa->sa_flags |= SA_NODEFER;
}

void
bsd_to_linux_old_sigaction(bsa, lsa)
	struct sigaction *bsa;
	struct linux_old_sigaction *lsa;
{

	lsa->sa__handler = bsa->sa_handler;
	bsd_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask);
	lsa->sa_flags = 0;
	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
		lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
	if ((bsa->sa_flags & SA_ONSTACK) != 0)
		lsa->sa_flags |= LINUX_SA_ONSTACK;
	if ((bsa->sa_flags & SA_RESTART) != 0)
		lsa->sa_flags |= LINUX_SA_RESTART;
	if ((bsa->sa_flags & SA_NODEFER) != 0)
		lsa->sa_flags |= LINUX_SA_NOMASK;
	if ((bsa->sa_flags & SA_RESETHAND) != 0)
		lsa->sa_flags |= LINUX_SA_ONESHOT;
	lsa->sa_restorer = NULL;
}

void
linux_to_bsd_sigaction(lsa, bsa)
	struct linux_sigaction *lsa;
	struct sigaction *bsa;
{

	bsa->sa_handler = lsa->sa__handler;
	linux_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
	bsa->sa_flags = 0;
	if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
		bsa->sa_flags |= SA_NOCLDSTOP;
	if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
		bsa->sa_flags |= SA_ONSTACK;
	if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
		bsa->sa_flags |= SA_RESTART;
	if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
		bsa->sa_flags |= SA_RESETHAND;
	if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
		bsa->sa_flags |= SA_NODEFER;
	if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
		bsa->sa_flags |= SA_SIGINFO;
}

void
bsd_to_linux_sigaction(bsa, lsa)
	struct sigaction *bsa;
	struct linux_sigaction *lsa;
{

	/* Clear sa_flags and sa_restorer (if it exists) */
	memset(lsa, 0, sizeof(struct linux_sigaction));

	/* ...and fill in the mask and flags */
	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
		lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
	if ((bsa->sa_flags & SA_ONSTACK) != 0)
		lsa->sa_flags |= LINUX_SA_ONSTACK;
	if ((bsa->sa_flags & SA_RESTART) != 0)
		lsa->sa_flags |= LINUX_SA_RESTART;
	if ((bsa->sa_flags & SA_NODEFER) != 0)
		lsa->sa_flags |= LINUX_SA_NOMASK;
	if ((bsa->sa_flags & SA_RESETHAND) != 0)
		lsa->sa_flags |= LINUX_SA_ONESHOT;
	if ((bsa->sa_flags & SA_SIGINFO) != 0)
		lsa->sa_flags |= LINUX_SA_SIGINFO;
	lsa->sa__handler = bsa->sa_handler;
}

int
linux_to_bsd_signal(int linuxsig, int *bsdsig)
{
	if (linuxsig < 0 || linuxsig >= LINUX__NSIG)
		return (EINVAL);

	*bsdsig = linux_to_bsd_sig[linuxsig];
	return (0);
}

int
bsd_to_linux_signal(int bsdsig, int *linuxsig)
{
	if (bsdsig < 0 || bsdsig >= NSIG)
		return (EINVAL);

	*linuxsig = bsd_to_linux_sig[bsdsig];
	return (0);
}

/*
 * The Linux sigaction() system call. Do the usual conversions,
 * and just call sigaction(). Some flags and values are silently
 * ignored (see above).
 */
int
linux_sys_sigaction(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_sigaction_args /* {
		syscallarg(int) signum;
		syscallarg(struct linux_old_sigaction *) nsa;
		syscallarg(struct linux_old_sigaction *) osa;
	} */ *uap = v;
	struct linux_old_sigaction *nlsa, *olsa, tmplsa;
	struct sigaction *nbsa, *obsa, tmpbsa;
	struct sys_sigaction_args sa;
	caddr_t sg;
	int error;

	if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
		return (EINVAL);

	sg = stackgap_init(p);
	nlsa = SCARG(uap, nsa);
	olsa = SCARG(uap, osa);

	if (olsa != NULL)
		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
	else
		obsa = NULL;

	if (nlsa != NULL) {
		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
		if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
			return (error);
		linux_old_to_bsd_sigaction(&tmplsa, &tmpbsa);
		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
			return (error);
	} else
		nbsa = NULL;

	SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
	SCARG(&sa, nsa) = nbsa;
	SCARG(&sa, osa) = obsa;

	/* Silently ignore unknown signals */
	if (SCARG(&sa, signum) == 0) {
		if (obsa != NULL) {
			obsa->sa_handler = SIG_IGN;
			sigemptyset(&obsa->sa_mask);
			obsa->sa_flags = 0;
		}
	}
	else {
		if ((error = sys_sigaction(p, &sa, retval)) != 0)
			return (error);
	}

	if (olsa != NULL) {
		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
			return (error);
		bsd_to_linux_old_sigaction(&tmpbsa, &tmplsa);
		if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
			return (error);
	}

	return (0);
}

int
linux_sys_rt_sigaction(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_rt_sigaction_args /* {
		syscallarg(int) signum;
		syscallarg(struct linux_sigaction *) nsa;
		syscallarg(struct linux_sigaction *) osa;
		syscallarg(size_t) sigsetsize;
	} */ *uap = v;
	struct linux_sigaction *nlsa, *olsa, tmplsa;
	struct sigaction *nbsa, *obsa, tmpbsa;
	struct sys_sigaction_args sa;
	caddr_t sg;
	int error;

	if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
		return (EINVAL);

	if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
		return (EINVAL);

	sg = stackgap_init(p);
	nlsa = SCARG(uap, nsa);
	olsa = SCARG(uap, osa);

	if (olsa != NULL)
		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
	else
		obsa = NULL;

	if (nlsa != NULL) {
		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
		if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
			return (error);
		linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
			return (error);
	}
	else
		nbsa = NULL;

	SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
	SCARG(&sa, nsa) = nbsa;
	SCARG(&sa, osa) = obsa;

	/* Silently ignore unknown signals */
	if (SCARG(&sa, signum) == 0) {
		if (obsa != NULL) {
			obsa->sa_handler = SIG_IGN;
			sigemptyset(&obsa->sa_mask);
			obsa->sa_flags = 0;
		}
	}
	else {
		if ((error = sys_sigaction(p, &sa, retval)) != 0)
			return (error);
	}

	if (olsa != NULL) {
		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
			return (error);
		bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
		if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
			return (error);
	}

	return (0);
}

/*
 * The Linux signal() system call. I think that the signal() in the C
 * library actually calls sigaction, so I doubt this one is ever used.
 * But hey, it can't hurt having it here. The same restrictions as for
 * sigaction() apply.
 */
int
linux_sys_signal(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_signal_args /* {
		syscallarg(int) sig;
		syscallarg(linux_handler_t) handler;
	} */ *uap = v;
	caddr_t sg;
	struct sys_sigaction_args sa_args;
	struct sigaction *osa, *nsa, tmpsa;
	int error;

	if (SCARG(uap, sig) < 0 || SCARG(uap, sig) >= LINUX__NSIG)
		return (EINVAL);

	sg = stackgap_init(p);
	nsa = stackgap_alloc(&sg, sizeof *nsa);
	osa = stackgap_alloc(&sg, sizeof *osa);

	tmpsa.sa_handler = SCARG(uap, handler);
	tmpsa.sa_mask = (sigset_t) 0;
	tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
	if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
		return (error);

	SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
	SCARG(&sa_args, osa) = osa;
	SCARG(&sa_args, nsa) = nsa;

	/* Silently ignore unknown signals */
	if (SCARG(&sa_args, signum) != 0) {
		if ((error = sys_sigaction(p, &sa_args, retval)))
			return (error);
	}

	if ((error = copyin(osa, &tmpsa, sizeof *osa)))
		return (error);
	retval[0] = (register_t) tmpsa.sa_handler;

	return (0);
}

/*
 * This is just a copy of the svr4 compat one. I feel so creative now.
 */
int
linux_sys_sigprocmask(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_sigprocmask_args /* {
		syscallarg(int) how;
		syscallarg(linux_old_sigset_t *) set;
		syscallarg(linux_old_sigset_t *) oset;
	} */ *uap = v;
	linux_old_sigset_t ss;
	sigset_t bs;
	int error = 0;

	*retval = 0;

	if (SCARG(uap, oset) != NULL) {
		/* Fix the return value first if needed */
		bsd_to_linux_old_sigset(&p->p_sigmask, &ss);
		if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
			return (error);
	}

	if (SCARG(uap, set) == NULL)
		/* Just examine */
		return (0);

	if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
		return (error);

	linux_old_to_bsd_sigset(&ss, &bs);

	bs &= ~sigcantmask;
	switch (SCARG(uap, how)) {
	case LINUX_SIG_BLOCK:
		atomic_setbits_int(&p->p_sigmask, bs);
		break;

	case LINUX_SIG_UNBLOCK:
		atomic_clearbits_int(&p->p_sigmask, bs);
		break;

	case LINUX_SIG_SETMASK:
		p->p_sigmask = bs;
		break;

	default:
		error = EINVAL;
		break;
	}

	return (error);
}

int
linux_sys_rt_sigprocmask(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_rt_sigprocmask_args /* {
		syscallarg(int) how;
		syscallarg(const linux_sigset_t *) set;
		syscallarg(linux_sigset_t *) oset;
		syscallarg(size_t) sigsetsize;
	} */ *uap = v;
	linux_sigset_t ls;
	sigset_t bs;
	int error = 0;

	if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
		return (EINVAL);

	*retval = 0;

	if (SCARG(uap, oset) != NULL) {
		/* Fix the return value first if needed */
		bsd_to_linux_sigset(&p->p_sigmask, &ls);
		if ((error = copyout(&ls, SCARG(uap, oset), sizeof(ls))) != 0)
			return (error);
	}

	if (SCARG(uap, set) == NULL)
		/* Just examine */
		return (0);

	if ((error = copyin(SCARG(uap, set), &ls, sizeof(ls))) != 0)
		return (error);

	linux_to_bsd_sigset(&ls, &bs);

	bs &= ~sigcantmask;
	switch (SCARG(uap, how)) {
	case LINUX_SIG_BLOCK:
		atomic_setbits_int(&p->p_sigmask, bs);
		break;

	case LINUX_SIG_UNBLOCK:
		atomic_clearbits_int(&p->p_sigmask, bs);
		break;

	case LINUX_SIG_SETMASK:
		p->p_sigmask = bs;
		break;

	default:
		error = EINVAL;
		break;
	}

	return (error);
}

/*
 * The functions below really make no distinction between an int
 * and [linux_]sigset_t. This is ok for now, but it might break
 * sometime. Then again, sigset_t is trusted to be an int everywhere
 * else in the kernel too.
 */
/* ARGSUSED */
int
linux_sys_siggetmask(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{

	bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
	return (0);
}

/*
 * The following three functions fiddle with a process' signal mask.
 * Convert the signal masks because of the different signal
 * values for Linux. The need for this is the reason why
 * they are here, and have not been mapped directly.
 */
int
linux_sys_sigsetmask(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_sigsetmask_args /* {
		syscallarg(linux_old_sigset_t) mask;
	} */ *uap = v;
	linux_old_sigset_t mask;
	sigset_t bsdsig;

	bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);

	mask = SCARG(uap, mask);
	bsd_to_linux_old_sigset(&bsdsig, &mask);

	p->p_sigmask = bsdsig & ~sigcantmask;

	return (0);
}

int
linux_sys_sigpending(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_sigpending_args /* {
		syscallarg(linux_old_sigset_t *) mask;
	} */ *uap = v;
	sigset_t bs;
	linux_old_sigset_t ls;

	bs = p->p_siglist & p->p_sigmask;
	bsd_to_linux_old_sigset(&bs, &ls);

	return (copyout(&ls, SCARG(uap, mask), sizeof ls));
}

int
linux_sys_rt_sigpending(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_rt_sigpending_args /* {
		syscallarg(linux_sigset_t *) set;
		syscallarg(size_t) sigsetsize;
	} */ *uap = v;
	sigset_t bs;
	linux_sigset_t ls;

	if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
		return (EINVAL);

	bs = p->p_siglist & p->p_sigmask;
	bsd_to_linux_sigset(&bs, &ls);

	return (copyout(&ls, SCARG(uap, set), sizeof ls));
}

int
linux_sys_sigsuspend(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_sigsuspend_args /* {
		syscallarg(caddr_t) restart;
		syscallarg(int) oldmask;
		syscallarg(int) mask;
	} */ *uap = v;
	struct sys_sigsuspend_args sa;
	linux_old_sigset_t mask = SCARG(uap, mask);

	linux_old_to_bsd_sigset(&mask, &SCARG(&sa, mask));
	return (sys_sigsuspend(p, &sa, retval));
}

int
linux_sys_rt_sigsuspend(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_rt_sigsuspend_args /* {
		syscallarg(sigset_t *) unewset;
		syscallarg(size_t) sigsetsize;
	} */ *uap = v;
	struct sys_sigsuspend_args sa;
	linux_sigset_t mask;
	int error;

	if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
		return (EINVAL);

	error = copyin(SCARG(uap, unewset), &mask, sizeof mask);
	if (error)
		return (error);

	linux_to_bsd_sigset(&mask, &SCARG(&sa, mask));
	return (sys_sigsuspend(p, &sa, retval));
}

/*
 * Linux' sigaltstack structure is just of a different order than BSD's
 * so just shuffle the fields around and call our version.
 */
int
linux_sys_sigaltstack(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_sigaltstack_args /* {
		syscallarg(const struct linux_sigaltstack *) nss;
		syscallarg(struct linux_sigaltstack *) oss;
	} */ *uap = v;
	struct linux_sigaltstack linux_ss;
	struct sigaltstack *bsd_nss, *bsd_oss;
	struct sys_sigaltstack_args sa;
	int error;
	caddr_t sg;

	sg = stackgap_init(p);

	if (SCARG(uap, nss) != NULL) {
		bsd_nss = stackgap_alloc(&sg, sizeof *bsd_nss);

		error = copyin(SCARG(uap, nss), &linux_ss, sizeof linux_ss);
		if (error)
			return (error);

		bsd_nss->ss_sp = linux_ss.ss_sp;
		bsd_nss->ss_size = linux_ss.ss_size;
		bsd_nss->ss_flags = (linux_ss.ss_flags & LINUX_SS_DISABLE) ?
		    SS_DISABLE : 0;

		SCARG(&sa, nss) = bsd_nss;
	} else
		SCARG(&sa, nss) = NULL;

	if (SCARG(uap, oss) == NULL) {
		SCARG(&sa, oss) = NULL;
		return (sys_sigaltstack(p, &sa, retval));
	}
	SCARG(&sa, oss) = bsd_oss = stackgap_alloc(&sg, sizeof *bsd_oss);

	error = sys_sigaltstack(p, &sa, retval);
	if (error)
		return (error);

	linux_ss.ss_sp = bsd_oss->ss_sp;
	linux_ss.ss_size = bsd_oss->ss_size;
	linux_ss.ss_flags = 0;
	if (bsd_oss->ss_flags & SS_ONSTACK)
		linux_ss.ss_flags |= LINUX_SS_ONSTACK;
	if (bsd_oss->ss_flags & SS_DISABLE)
		linux_ss.ss_flags |= LINUX_SS_DISABLE;
	return (copyout(&linux_ss, SCARG(uap, oss), sizeof linux_ss));
}

/*
 * The deprecated pause(2), which is really just an instance
 * of sigsuspend(2).
 */
int
linux_sys_pause(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct sys_sigsuspend_args bsa;

	SCARG(&bsa, mask) = p->p_sigmask;
	return (sys_sigsuspend(p, &bsa, retval));
}

/*
 * Once more: only a signal conversion is needed.
 */
int
linux_sys_kill(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_kill_args /* {
		syscallarg(int) pid;
		syscallarg(int) signum;
	} */ *uap = v;
	struct sys_kill_args ka;

	SCARG(&ka, pid) = SCARG(uap, pid);
	if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
		return (EINVAL);
	SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
	return (sys_kill(p, &ka, retval));
}

int
linux_sys_tgkill(struct proc *p, void *v, register_t *retval)
{
	struct linux_sys_tgkill_args /* {
		syscallarg(int) tgid;
		syscallarg(int) tid;
		syscallarg(int) sig;
	}; */ *uap = v;

	int error;
	int sig;
	struct sys_kill_args ka;

	if (SCARG(uap, tgid) < 0 || SCARG(uap, tid) < 0)
		return (EINVAL);

	if ((error = linux_to_bsd_signal(SCARG(uap, sig), &sig)))
		return (error);

	/* XXX: Ignoring tgid, behaving like the obsolete linux_sys_tkill */
	SCARG(&ka, pid) = SCARG(uap, tid);
	SCARG(&ka, signum) = sig;
	return (sys_kill(p, &ka, retval));
}


code:
/*	$OpenBSD: linux_signal.h,v 1.9 2011/04/05 22:54:31 pirofti Exp $	*/
/* 	$NetBSD: linux_signal.h,v 1.4 1995/08/27 20:51:51 fvdl Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SIGNAL_H_
#define _LINUX_SIGNAL_H_

#define LINUX_SIGHUP	 1
#define LINUX_SIGINT	 2
#define LINUX_SIGQUIT	 3
#define LINUX_SIGILL	 4
#define LINUX_SIGTRAP	 5
#define LINUX_SIGABRT	 6
#define LINUX_SIGIOT	 6
#define LINUX_SIGBUS	 7
#define LINUX_SIGFPE	 8
#define LINUX_SIGKILL	 9
#define LINUX_SIGUSR1	10
#define LINUX_SIGSEGV	11
#define LINUX_SIGUSR2	12
#define LINUX_SIGPIPE	13
#define LINUX_SIGALRM	14
#define LINUX_SIGTERM	15
#define LINUX_SIGSTKFLT	16
#define LINUX_SIGCHLD	17
#define LINUX_SIGCONT	18
#define LINUX_SIGSTOP	19
#define LINUX_SIGTSTP	20
#define LINUX_SIGTTIN	21
#define LINUX_SIGTTOU	22
#define LINUX_SIGURG	23
#define LINUX_SIGXCPU	24
#define LINUX_SIGXFSZ	25
#define LINUX_SIGVTALRM	26
#define LINUX_SIGPROF	27
#define LINUX_SIGWINCH	28
#define LINUX_SIGIO	29
#define LINUX_SIGPWR	30
#define LINUX_SIGUNUSED	31
#define LINUX_NSIG	32

#define LINUX__NSIG 		64
#define LINUX__NSIG_BPW		32
#define LINUX__NSIG_WORDS	(LINUX__NSIG / LINUX__NSIG_BPW)

#define LINUX_SIG_BLOCK		0
#define LINUX_SIG_UNBLOCK	1
#define LINUX_SIG_SETMASK	2

typedef u_long	linux_old_sigset_t;
typedef struct {
	u_long sig[LINUX__NSIG_WORDS];
} linux_sigset_t;

typedef void	(*linux_handler_t)(int);

struct linux_old_sigaction {
	linux_handler_t		sa__handler;
	linux_old_sigset_t	sa_mask;
	u_long			sa_flags;
	void			(*sa_restorer)(void);
};

struct linux_sigaction {
	linux_handler_t		sa__handler;
	u_long			sa_flags;
	void			(*sa_restorer)(void);
	linux_sigset_t		sa_mask;
};

/* sa_flags */
#define LINUX_SA_NOCLDSTOP	0x00000001
#define LINUX_SA_SIGINFO	0x00000004
#define LINUX_SA_ONSTACK	0x08000000
#define LINUX_SA_RESTART	0x10000000
#define LINUX_SA_INTERRUPT	0x20000000
#define LINUX_SA_NOMASK		0x40000000
#define LINUX_SA_ONESHOT	0x80000000
#define LINUX_SA_ALLBITS	0xf8000001

struct linux_sigaltstack {
	void	*ss_sp;
	int	ss_flags;
	size_t	ss_size;
};

/* ss_flags */
#define LINUX_SS_ONSTACK	0x00000001
#define LINUX_SS_DISABLE	0x00000002

extern int bsd_to_linux_sig[];
extern int linux_to_bsd_sig[];

void linux_old_to_bsd_sigset(const linux_old_sigset_t *, sigset_t *);
void bsd_to_linux_old_sigset(const sigset_t *, linux_old_sigset_t *);

void linux_old_extra_to_bsd_sigset(const linux_old_sigset_t *,
    const unsigned long *, sigset_t *);
void bsd_to_linux_old_extra_sigset(const sigset_t *,
    linux_old_sigset_t *, unsigned long *);

void linux_to_bsd_sigset(const linux_sigset_t *, sigset_t *);
void bsd_to_linux_sigset(const sigset_t *, linux_sigset_t *);

void linux_old_to_bsd_sigaction(struct linux_old_sigaction *,
    struct sigaction *);
void bsd_to_linux_old_sigaction(struct sigaction *,
    struct linux_old_sigaction *);

void linux_to_bsd_sigaction(struct linux_sigaction *,
    struct sigaction *);
void bsd_to_linux_sigaction(struct sigaction *,
    struct linux_sigaction *);

int  linux_to_bsd_signal (int, int *);
int  bsd_to_linux_signal (int, int *);

#endif /* !_LINUX_SIGNAL_H_ */


code:
/*	$OpenBSD: linux_socket.c,v 1.61 2015/05/06 08:52:17 mpi Exp $	*/
/*	$NetBSD: linux_socket.c,v 1.14 1996/04/05 00:01:50 christos Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/domain.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/mbuf.h>
#include <sys/selinfo.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/un.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/device.h>

#include <sys/syscallargs.h>

#include <compat/linux/linux_types.h>
#include <compat/linux/linux_util.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_syscallargs.h>
#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_socket.h>
#include <compat/linux/linux_socketcall.h>
#include <compat/linux/linux_sockio.h>

/*
 * All the calls in this file are entered via one common system
 * call in Linux, represented here by linux_socketcall().
 * Arguments for the various calls are on the user stack. A pointer
 * to them is the only thing that is passed. It is up to the various
 * calls to copy them in themselves. To make it look better, they
 * are copied to structures.
 */

static int linux_to_bsd_domain (int);
static int bsd_to_linux_domain(int);

static int linux_to_bsd_msg_flags(int);

int linux_socket(struct proc *, void *, register_t *);
int linux_bind(struct proc *, void *, register_t *);
int linux_connect(struct proc *, void *, register_t *);
int linux_listen(struct proc *, void *, register_t *);
int linux_accept(struct proc *, void *, register_t *);
int linux_getsockname(struct proc *, void *, register_t *);
int linux_getpeername(struct proc *, void *, register_t *);
int linux_socketpair(struct proc *, void *, register_t *);
int linux_send(struct proc *, void *, register_t *);
int linux_recv(struct proc *, void *, register_t *);
int linux_sendto(struct proc *, void *, register_t *);
int linux_recvfrom(struct proc *, void *, register_t *);
int linux_shutdown(struct proc *, void *, register_t *);
int linux_to_bsd_sopt_level(int);
int linux_to_bsd_so_sockopt(int);
int linux_to_bsd_ip_sockopt(int);
int linux_to_bsd_tcp_sockopt(int);
int linux_to_bsd_udp_sockopt(int);
int linux_setsockopt(struct proc *, void *, register_t *);
int linux_getsockopt(struct proc *, void *, register_t *);
int linux_recvmsg(struct proc *, void *, register_t *);
int linux_sendmsg(struct proc *, void *, register_t *);

int linux_check_hdrincl(struct proc *, int, register_t *, caddr_t *);
int linux_sendto_hdrincl(struct proc *, struct sys_sendto_args *,
    register_t *, caddr_t *);

int linux_sa_get(struct proc *, caddr_t *, struct sockaddr **,
    const struct linux_sockaddr *, int *);
int linux_sa_put(struct sockaddr *);

static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
	AF_UNSPEC,
	AF_UNIX,
	AF_INET,
	-1,		/* LINUX_AF_AX25 */
	-1,		/* IPX */
	-1		/* APPLETALK */
	-1,		/* LINUX_AF_NETROM */
	-1,		/* LINUX_AF_BRIDGE */
	-1,		/* LINUX_AF_ATMPVC */
	-1,		/* LINUX_AF_X25 */
	AF_INET6,
	-1,		/* LINUX_AF_ROSE */
	AF_DECnet,
	-1,		/* LINUX_AF_NETBEUI */
	-1,		/* LINUX_AF_SECURITY */
	-1,		/* pseudo_AF_KEY */
	AF_ROUTE,	/* LINUX_AF_NETLINK */
	-1,		/* LINUX_AF_PACKET */
	-1,		/* LINUX_AF_ASH */
	-1,		/* LINUX_AF_ECONET */
	-1,		/* LINUX_AF_ATMSVC */
	AF_SNA,
	/* rest up to LINUX_AF_MAX-1 is not allocated */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};

static const int bsd_to_linux_domain_[AF_MAX] = {
	LINUX_AF_UNSPEC,
	LINUX_AF_UNIX,
	LINUX_AF_INET,
	-1,		/* AF_IMPLINK */
	-1,		/* AF_PUP */
	-1,		/* AF_CHAOS */
	-1,		/* AF_NS */
	-1,		/* AF_ISO */
	-1,		/* AF_ECMA */
	-1,		/* AF_DATAKIT */
	-1,		/* AF_CCITT */
	-1,		/* LINUX_AF_SNA */
	-1,		/* LINUX_AF_DECnet */
	-1,		/* AF_DLI */
	-1,		/* AF_LAT */
	-1,		/* AF_HYLINK */
	LINUX_AF_APPLETALK,
	-1,		/* LINUX_AF_NETLINK */
	-1,		/* AF_LINK */
	-1,		/* AF_XTP */
	-1,		/* AF_COIP */
	-1,		/* AF_CNT */
	-1,		/* pseudo_AF_RTIP */
	LINUX_AF_IPX,
	LINUX_AF_INET6,
	-1,		/* pseudo_AF_PIP */
	-1,		/* AF_ISDN */
	-1,		/* AF_NATM */
	-1,		/* AF_ARP */
	-1,		/* LINUX_pseudo_AF_KEY */
	-1,		/* pseudo_AF_HDRCMPLT */
};

/*
 * Convert from Linux to BSD socket domain values
 */
static int
linux_to_bsd_domain(ldom)
	int ldom;
{
	if (ldom < 0 || ldom >= LINUX_AF_MAX)
		return (-1);

	return linux_to_bsd_domain_[ldom];
}

/*
 * Convert from BSD to Linux socket domain values
 */
static int
bsd_to_linux_domain(bdom)
	int bdom;
{
	if (bdom < 0 || bdom >= AF_MAX)
		return (-1);

	return bsd_to_linux_domain_[bdom];
}

/*
 * Convert from Linux to BSD MSG_XXX flags
 */
static int
linux_to_bsd_msg_flags(int lflags)
{
	int flags = 0;

	if (lflags & LINUX_MSG_OOB)
		flags |= MSG_OOB;
	if (lflags & LINUX_MSG_PEEK)
		flags |= MSG_PEEK;
	if (lflags & LINUX_MSG_DONTWAIT)
		flags |= MSG_DONTWAIT;
	if (lflags & LINUX_MSG_WAITALL)
		flags |= MSG_WAITALL;
	if (lflags & LINUX_MSG_NOSIGNAL)
		flags |= MSG_NOSIGNAL;
	return (flags);
}

int
linux_socket(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_socket_args /* {
		syscallarg(int)	domain;
		syscallarg(int)	type;
		syscallarg(int) protocol;
	} */ *uap = v;
	struct linux_socket_args lsa;
	struct sys_socket_args bsa;
	int error;

	if ((error = copyin(uap, &lsa, sizeof lsa)))
		return error;

	SCARG(&bsa, protocol) = lsa.protocol;
	SCARG(&bsa, type) = lsa.type & LINUX_SOCKET_TYPE_MASK;
	SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
	if (SCARG(&bsa, domain) == -1)
		return (EINVAL);

	if (lsa.type & ~(LINUX_SOCKET_TYPE_MASK | LINUX_SOCK_CLOEXEC |
	    LINUX_SOCK_NONBLOCK))
		return (EINVAL);
	if (lsa.type & LINUX_SOCK_CLOEXEC)
		SCARG(&bsa, type) |= SOCK_CLOEXEC;
	if (lsa.type & LINUX_SOCK_NONBLOCK)
		SCARG(&bsa, type) |= SOCK_NONBLOCK;

	return (sys_socket(p, &bsa, retval));
}

int
linux_bind(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_bind_args /* {
		syscallarg(int)	s;
		syscallarg(struct linux_sockaddr *) name;
		syscallarg(int)	namelen;
	} */ *uap = v;
	struct linux_bind_args lba;
	struct sys_bind_args bba;
	int error;
	int namlen;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lba, sizeof lba)))
		return error;

	SCARG(&bba, s) = lba.s;
	namlen = lba.namelen;
	if (lba.name) {
		struct sockaddr *sa;
		caddr_t sg = stackgap_init(p);

		error = linux_sa_get(p, &sg, &sa, lba.name, &namlen);
		if (error)
			return (error);
		SCARG(&bba, name) = sa;
	} else
		SCARG(&bba, name) = NULL;
	SCARG(&bba, namelen) = namlen;

	return sys_bind(p, &bba, retval);
}

int
linux_connect(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_connect_args /* {
		syscallarg(int)	s;
		syscallarg(struct linux_sockaddr *) name;
		syscallarg(int)	namelen;
	} */ *uap = v;
	struct linux_connect_args lca;
	struct sys_connect_args bca;
	struct sockaddr *sa;
	caddr_t sg = stackgap_init(p);
	int namlen;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lca, sizeof lca)))
		return error;

	namlen = lca.namelen;
	error = linux_sa_get(p, &sg, &sa, lca.name, &namlen);
	if (error)
		return (error);

	SCARG(&bca, s) = lca.s;
	SCARG(&bca, name) = sa;
	SCARG(&bca, namelen) = (unsigned int)namlen;

	error = sys_connect(p, &bca, retval);

	if (error == EISCONN) {
		struct sys_getsockopt_args bga;
#if 0
		struct sys_fcntl_args fca;
#endif
		void *status, *statusl;
		int stat, statl = sizeof stat;

#if 0
		SCARG(&fca, fd) = lca.s;
		SCARG(&fca, cmd) = F_GETFL;
		SCARG(&fca, arg) = 0;
		if (sys_fcntl(p, &fca, retval) == -1 ||
		    (*retval & O_NONBLOCK) == 0)
			return error;
#endif

		status = stackgap_alloc(&sg, sizeof stat);
		statusl = stackgap_alloc(&sg, sizeof statl);

		if ((error = copyout(&statl, statusl, sizeof statl)))
			return error;

		SCARG(&bga, s) = lca.s;
		SCARG(&bga, level) = SOL_SOCKET;
		SCARG(&bga, name) = SO_ERROR;
		SCARG(&bga, val) = status;
		SCARG(&bga, avalsize) = statusl;

		error = sys_getsockopt(p, &bga, retval);
		if (error)
			return error;
		if ((error = copyin(status, &stat, sizeof stat)))
			return error;
		return stat;
	}
	return error;
}

int
linux_listen(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_listen_args /* {
		syscallarg(int) s;
		syscallarg(int) backlog;
	} */ *uap = v;
	struct linux_listen_args lla;
	struct sys_listen_args bla;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
		return error;

	SCARG(&bla, s) = lla.s;
	SCARG(&bla, backlog) = lla.backlog;

	return sys_listen(p, &bla, retval);
}

int
linux_accept(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_accept_args /* {
		syscallarg(int) s;
		syscallarg(struct sockaddr *) addr;
		syscallarg(int *) namelen;
	} */ *uap = v;
	struct linux_accept_args laa;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &laa, sizeof laa)))
		return error;

	if ((error = doaccept(p, laa.s, laa.addr, laa.namelen, 0, retval)))
		return (error);

	return (linux_sa_put(laa.addr));
}

int
linux_getsockname(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_getsockname_args /* {
		syscallarg(int) s;
		syscallarg(struct sockaddr *) addr;
		syscallarg(int *) namelen;
	} */ *uap = v;
	struct linux_getsockname_args lga;
	struct sys_getsockname_args bga;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
		return error;

	SCARG(&bga, fdes) = lga.s;
	SCARG(&bga, asa)  = lga.addr;
	SCARG(&bga, alen) = lga.namelen;

	error = sys_getsockname(p, &bga, retval);
	if (error)
		return (error);

	return (linux_sa_put(lga.addr));
}

int
linux_getpeername(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_getpeername_args /* {
		syscallarg(int) s;
		syscallarg(struct sockaddr *) addr;
		syscallarg(int *) namelen;
	} */ *uap = v;
	struct linux_getpeername_args lga;
	struct sys_getpeername_args bga;
	int error;

	if ((error = copyin(uap, &lga, sizeof lga)))
		return error;

	SCARG(&bga, fdes) = lga.s;
	SCARG(&bga, asa)  = lga.addr;
	SCARG(&bga, alen) = lga.namelen;

	error = sys_getpeername(p, &bga, retval);
	if (error)
		return (error);

	return (linux_sa_put(lga.addr));
}

int
linux_socketpair(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_socketpair_args /* {
		syscallarg(int) domain;
		syscallarg(int) type;
		syscallarg(int) protocol;
		syscallarg(int *) rsv;
	} */ *uap = v;
	struct linux_socketpair_args lsa;
	struct sys_socketpair_args bsa;
	int error;

	if ((error = copyin((caddr_t) uap, &lsa, sizeof lsa)))
		return error;

	SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
	if (SCARG(&bsa, domain) == -1)
		return EINVAL;
	SCARG(&bsa, type) = lsa.type;
	SCARG(&bsa, protocol) = lsa.protocol;
	SCARG(&bsa, rsv) = lsa.rsv;

	return sys_socketpair(p, &bsa, retval);
}

int
linux_send(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_send_args /* {
		syscallarg(int) s;
		syscallarg(void *) msg;
		syscallarg(int) len;
		syscallarg(int) flags;
	} */ *uap = v;
	struct linux_send_args lsa;
	struct msghdr msg;
	struct iovec aiov;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
		return error;

	msg.msg_name = 0;
	msg.msg_namelen = 0;
	msg.msg_iov = &aiov;
	msg.msg_iovlen = 1;
	aiov.iov_base = lsa.msg;
	aiov.iov_len = lsa.len;
	msg.msg_control = 0;
	msg.msg_flags = 0;

	return (sendit(p, lsa.s, &msg, linux_to_bsd_msg_flags(lsa.flags),
	    retval));
}

int
linux_recv(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_recv_args /* {
		syscallarg(int) s;
		syscallarg(void *) msg;
		syscallarg(int) len;
		syscallarg(int) flags;
	} */ *uap = v;
	struct linux_recv_args lra;
	struct msghdr msg;
	struct iovec aiov;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
		return error;

	msg.msg_name = 0;
	msg.msg_namelen = 0;
	msg.msg_iov = &aiov;
	msg.msg_iovlen = 1;
	aiov.iov_base = lra.msg;
	aiov.iov_len = lra.len;
	msg.msg_control = 0;
	msg.msg_flags = linux_to_bsd_msg_flags(lra.flags);

	return (recvit(p, lra.s, &msg, NULL, retval));
}

int
linux_check_hdrincl(p, fd, retval, sgp)
	struct proc *p;
	int fd;
	register_t *retval;
	caddr_t *sgp;
{
	struct sys_getsockopt_args /* {
		int s;
		int level;
		int name;
		caddr_t val;
		int *avalsize;
	} */ gsa;
	int error;
	caddr_t val;
	int *valsize;
	int size_val = sizeof val;
	int optval;

	val = stackgap_alloc(sgp, sizeof(optval));
	valsize = stackgap_alloc(sgp, sizeof(size_val));

	if ((error = copyout(&size_val, valsize, sizeof(size_val))))
		return (error);
	SCARG(&gsa, s) = fd;
	SCARG(&gsa, level) = IPPROTO_IP;
	SCARG(&gsa, name) = IP_HDRINCL;
	SCARG(&gsa, val) = val;
	SCARG(&gsa, avalsize) = valsize;

	if ((error = sys_getsockopt(p, &gsa, retval)))
		return (error);
	if ((error = copyin(val, &optval, sizeof(optval))))
		return (error);
	return (optval == 0);
}

/*
 * linux_ip_copysize defines how many bytes we should copy
 * from the beginning of the IP packet before we customize it for BSD.
 * It should include all the fields we modify (ip_len and ip_off)
 * and be as small as possible to minimize copying overhead.
 */
#define linux_ip_copysize      8

int
linux_sendto_hdrincl(p, bsa, retval, sgp)
	struct proc *p;
	struct sys_sendto_args *bsa;
	register_t *retval;
	caddr_t *sgp;
{
	struct sys_sendmsg_args ssa;
	struct ip *packet, rpacket;
	struct msghdr *msg, rmsg;
	struct iovec *iov, riov[2];
	int error;

	/* Check the packet isn't too small before we mess with it */
	if (SCARG(bsa, len) < linux_ip_copysize)
		return EINVAL;

	/*
	 * Tweaking the user buffer in place would be bad manners.
	 * We create a corrected IP header with just the needed length,
	 * then use an iovec to glue it to the rest of the user packet
	 * when calling sendmsg().
	 */
	packet = (struct ip *)stackgap_alloc(sgp, linux_ip_copysize);
	msg = (struct msghdr *)stackgap_alloc(sgp, sizeof(*msg));
	iov = (struct iovec *)stackgap_alloc(sgp, sizeof(*iov)*2);

	/* Make a copy of the beginning of the packet to be sent */
	if ((error = copyin(SCARG(bsa, buf), (caddr_t)&rpacket,
	    linux_ip_copysize)))
		return error;

	/* Convert fields from Linux to BSD raw IP socket format */
	rpacket.ip_len = SCARG(bsa, len);
	error = copyout(&rpacket, packet, linux_ip_copysize);
	if (error)
		return (error);

	riov[0].iov_base = (char *)packet;
	riov[0].iov_len = linux_ip_copysize;
	riov[1].iov_base = (caddr_t)SCARG(bsa, buf) + linux_ip_copysize;
	riov[1].iov_len = SCARG(bsa, len) - linux_ip_copysize;

	error = copyout(&riov[0], iov, sizeof(riov));
	if (error)
		return (error);

	/* Prepare the msghdr and iovec structures describing the new packet */
	rmsg.msg_name = (void *)SCARG(bsa, to);
	rmsg.msg_namelen = SCARG(bsa, tolen);
	rmsg.msg_iov = iov;
	rmsg.msg_iovlen = 2;
	rmsg.msg_control = NULL;
	rmsg.msg_controllen = 0;
	rmsg.msg_flags = 0;

	error = copyout(&riov[0], iov, sizeof(riov));
	if (error)
		return (error);

	SCARG(&ssa, s) = SCARG(bsa, s);
	SCARG(&ssa, msg) = msg;
	SCARG(&ssa, flags) = SCARG(bsa, flags);
	return sys_sendmsg(p, &ssa, retval);
}

int
linux_sendto(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sendto_args /* {
		syscallarg(int) s;
		syscallarg(void *) msg;
		syscallarg(int) len;
		syscallarg(int) flags;
		syscallarg(linux_sockaddr *) to;
		syscallarg(int) tolen;
	} */ *uap = v;
	struct linux_sendto_args lsa;
	struct sys_sendto_args bsa;
	int error;
	int tolen;
	caddr_t sg = stackgap_init(p);

	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
		return error;

	SCARG(&bsa, s) = lsa.s;
	SCARG(&bsa, buf) = lsa.msg;
	SCARG(&bsa, len) = lsa.len;
	SCARG(&bsa, flags) = linux_to_bsd_msg_flags(lsa.flags);
	tolen = lsa.tolen;
	if (lsa.to) {
		struct sockaddr *sa;

		if ((error = linux_sa_get(p, &sg, &sa, lsa.to, &tolen)))
			return (error);
		SCARG(&bsa, to) = sa;
	} else
		SCARG(&bsa, to) = NULL;
	SCARG(&bsa, tolen) = tolen;

	if (linux_check_hdrincl(p, lsa.s, retval, &sg) == 0)
		return linux_sendto_hdrincl(p, &bsa, retval, &sg);
	return sys_sendto(p, &bsa, retval);
}

int
linux_recvfrom(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_recvfrom_args /* {
		syscallarg(int) s;
		syscallarg(void *) buf;
		syscallarg(int) len;
		syscallarg(int) flags;
		syscallarg(struct sockaddr *) from;
		syscallarg(int *) fromlen;
	} */ *uap = v;
	struct linux_recvfrom_args lra;
	struct sys_recvfrom_args bra;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
		return error;

	SCARG(&bra, s) = lra.s;
	SCARG(&bra, buf) = lra.buf;
	SCARG(&bra, len) = lra.len;
	SCARG(&bra, flags) = linux_to_bsd_msg_flags(lra.flags);
	SCARG(&bra, from) = lra.from;
	SCARG(&bra, fromlenaddr) = lra.fromlen;

	if ((error = sys_recvfrom(p, &bra, retval)))
		return (error);

	if (lra.from && (error = linux_sa_put(lra.from)))
		return (error);

	return (0);
}

int
linux_shutdown(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_shutdown_args /* {
		syscallarg(int) s;
		syscallarg(int) how;
	} */ *uap = v;
	struct linux_shutdown_args lsa;
	struct sys_shutdown_args bsa;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
		return error;

	SCARG(&bsa, s) = lsa.s;
	SCARG(&bsa, how) = lsa.how;

	return sys_shutdown(p, &bsa, retval);
}

/*
 * Convert socket option level from Linux to OpenBSD value. Only SOL_SOCKET
 * is different, the rest matches IPPROTO_* on both systems.
 */
int
linux_to_bsd_sopt_level(llevel)
	int llevel;
{

	switch (llevel) {
	case LINUX_SOL_SOCKET:
		return SOL_SOCKET;
	case LINUX_SOL_IP:
		return IPPROTO_IP;
	case LINUX_SOL_TCP:
		return IPPROTO_TCP;
	case LINUX_SOL_UDP:
		return IPPROTO_UDP;
	default:
		return -1;
	}
}

/*
 * Convert Linux socket level socket option numbers to OpenBSD values.
 */
int
linux_to_bsd_so_sockopt(lopt)
	int lopt;
{

	switch (lopt) {
	case LINUX_SO_DEBUG:
		return SO_DEBUG;
	case LINUX_SO_REUSEADDR:
		/*
		 * Linux does not implement SO_REUSEPORT, but allows reuse
		 * of a host:port pair through SO_REUSEADDR even if the
		 * address is not a multicast-address.  Effectively, this
		 * means that we should use SO_REUSEPORT to allow Linux
		 * applications to not receive EADDRINUSE.
		 */
		return SO_REUSEPORT;
	case LINUX_SO_TYPE:
		return SO_TYPE;
	case LINUX_SO_ERROR:
		return SO_ERROR;
	case LINUX_SO_DONTROUTE:
		return SO_DONTROUTE;
	case LINUX_SO_BROADCAST:
		return SO_BROADCAST;
	case LINUX_SO_SNDBUF:
		return SO_SNDBUF;
	case LINUX_SO_RCVBUF:
		return SO_RCVBUF;
	case LINUX_SO_KEEPALIVE:
		return SO_KEEPALIVE;
	case LINUX_SO_OOBINLINE:
		return SO_OOBINLINE;
	case LINUX_SO_LINGER:
		return SO_LINGER;
	case LINUX_SO_PRIORITY:
	case LINUX_SO_NO_CHECK:
	default:
		return -1;
	}
}

/*
 * Convert Linux IP level socket option number to OpenBSD values.
 */
int
linux_to_bsd_ip_sockopt(lopt)
	int lopt;
{

	switch (lopt) {
	case LINUX_IP_TOS:
		return IP_TOS;
	case LINUX_IP_TTL:
		return IP_TTL;
	case LINUX_IP_MULTICAST_TTL:
		return IP_MULTICAST_TTL;
	case LINUX_IP_MULTICAST_LOOP:
		return IP_MULTICAST_LOOP;
	case LINUX_IP_MULTICAST_IF:
		return IP_MULTICAST_IF;
	case LINUX_IP_ADD_MEMBERSHIP:
		return IP_ADD_MEMBERSHIP;
	case LINUX_IP_DROP_MEMBERSHIP:
		return IP_DROP_MEMBERSHIP;
	case LINUX_IP_HDRINCL:
		return IP_HDRINCL;
	default:
		return -1;
	}
}

/*
 * Convert Linux TCP level socket option number to OpenBSD values.
 */
int
linux_to_bsd_tcp_sockopt(lopt)
	int lopt;
{

	switch (lopt) {
	case LINUX_TCP_NODELAY:
		return TCP_NODELAY;
	case LINUX_TCP_MAXSEG:
		return TCP_MAXSEG;
	default:
		return -1;
	}
}

/*
 * Convert Linux UDP level socket option number to OpenBSD values.
 */
int
linux_to_bsd_udp_sockopt(lopt)
	int lopt;
{

	switch (lopt) {
	default:
		return -1;
	}
}

/*
 * Another reasonably straightforward function: setsockopt(2).
 * The level and option numbers are converted; the values passed
 * are not (yet) converted, the ones currently implemented don't
 * need conversion, as they are the same on both systems.
 */
int
linux_setsockopt(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_setsockopt_args /* {
		syscallarg(int) s;
		syscallarg(int) level;
		syscallarg(int) optname;
		syscallarg(void *) optval;
		syscallarg(int) optlen;
	} */ *uap = v;
	struct linux_setsockopt_args lsa;
	struct file *fp;
	struct mbuf *m = NULL;
	struct socket *so;
	int error, level, name;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
		return error;

	if ((error = getsock(p, lsa.s, &fp)) != 0)
		return error;

	level = linux_to_bsd_sopt_level(lsa.level);
	switch (level) {
	case SOL_SOCKET:
		name = linux_to_bsd_so_sockopt(lsa.optname);
		break;
	case IPPROTO_IP:
		name = linux_to_bsd_ip_sockopt(lsa.optname);
		break;
	case IPPROTO_TCP:
		name = linux_to_bsd_tcp_sockopt(lsa.optname);
		break;
	case IPPROTO_UDP:
		name = linux_to_bsd_udp_sockopt(lsa.optname);
		break;
	default:
		error = EINVAL;
		goto bad;
	}
	if (name == -1) {
		error = EINVAL;
		goto bad;
	}
	if (lsa.optlen > MLEN) {
		error = EINVAL;
		goto bad;
	}
	if (lsa.optval != NULL) {
		m = m_get(M_WAIT, MT_SOOPTS);
		error = copyin(lsa.optval, mtod(m, caddr_t), lsa.optlen);
		if (error)
			goto bad;
		m->m_len = lsa.optlen;
	}
	so = (struct socket *)fp->f_data;
	if (so->so_proto && level == IPPROTO_TCP && name == TCP_NODELAY &&
	    so->so_proto->pr_domain->dom_family == AF_LOCAL &&
	    so->so_proto->pr_protocol == PF_LOCAL) {
		/* ignore it */
		error = 0;
		goto bad;
	}
	error = sosetopt(so, level, name, m);
	m = NULL;
bad:
	if (m)
		m_free(m);
	FRELE(fp, p);
	return (error);
}

/*
 * getsockopt(2) is very much the same as setsockopt(2) (see above)
 */
int
linux_getsockopt(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_getsockopt_args /* {
		syscallarg(int) s;
		syscallarg(int) level;
		syscallarg(int) optname;
		syscallarg(void *) optval;
		syscallarg(int) *optlen;
	} */ *uap = v;
	struct linux_getsockopt_args lga;
	struct sys_getsockopt_args bga;
	int error, name;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
		return error;

	SCARG(&bga, s) = lga.s;
	SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
	SCARG(&bga, val) = lga.optval;
	SCARG(&bga, avalsize) = lga.optlen;

	switch (SCARG(&bga, level)) {
	case SOL_SOCKET:
		name = linux_to_bsd_so_sockopt(lga.optname);
		break;
	case IPPROTO_IP:
		name = linux_to_bsd_ip_sockopt(lga.optname);
		break;
	case IPPROTO_TCP:
		name = linux_to_bsd_tcp_sockopt(lga.optname);
		break;
	case IPPROTO_UDP:
		name = linux_to_bsd_udp_sockopt(lga.optname);
		break;
	default:
		return EINVAL;
	}

	if (name == -1)
		return EINVAL;
	SCARG(&bga, name) = name;

	return sys_getsockopt(p, &bga, retval);
}

int
linux_recvmsg(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_recvmsg_args /* {
		syscallarg(int) s;
		syscallarg(caddr_t) msg;
		syscallarg(int) flags;
	} */ *uap = v;
	struct linux_recvmsg_args lla;
	struct sys_recvmsg_args bla;
	struct msghdr msg;
	int error;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
		return error;

	SCARG(&bla, s) = lla.s;
	SCARG(&bla, msg) = (struct msghdr *)lla.msg;
	SCARG(&bla, flags) = linux_to_bsd_msg_flags(lla.flags);

	error = sys_recvmsg(p, &bla, retval);
	if (error)
		return (error);

	error = copyin(lla.msg, (caddr_t)&msg, sizeof(msg));

	if (!error && msg.msg_name && msg.msg_namelen > 2)
		error = linux_sa_put(msg.msg_name);

	return (error);
}

int
linux_sendmsg(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sendmsg_args /* {
		syscallarg(int) s;
		syscallarg(struct msghdr *) msg;
		syscallarg(int) flags;
	} */ *uap = v;
	struct linux_sendmsg_args lla;
	struct sys_sendmsg_args bla;
	struct msghdr msg, *nmsg = NULL;
	int error;
	caddr_t control;
	int level = -1;

	if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
		return error;

	if ((error = copyin(lla.msg, (caddr_t) &msg, sizeof(msg))))
		return (error);

	if (msg.msg_name) {
		struct sockaddr *sa;
		caddr_t sg = stackgap_init(p);

		nmsg = (struct msghdr *)stackgap_alloc(&sg,
		    sizeof(struct msghdr));
		if (!nmsg)
			return (ENOMEM);

		error = linux_sa_get(p, &sg, &sa,
		    (struct linux_sockaddr *)msg.msg_name, &msg.msg_namelen);
		if (error)
			return (error);

		msg.msg_name = sa;
		if ((error = copyout(&msg, nmsg, sizeof(struct msghdr))))
			return (error);
		lla.msg = nmsg;
	}

	SCARG(&bla, s) = lla.s;
	SCARG(&bla, msg) = lla.msg;
	SCARG(&bla, flags) = linux_to_bsd_msg_flags(lla.flags);

	error = copyin(lla.msg->msg_control, &control, sizeof(caddr_t));
	if (error)
		return error;
	if (control == NULL)
		goto done;
	error = copyin(&((struct cmsghdr *)control)->cmsg_level,
	    &level, sizeof(int));
	if (error)
		return error;
	if (level == 1) {
		/*
		 * Linux thinks that SOL_SOCKET is 1; we know that it's really
		 * 0xffff, of course.
		 */
		level = SOL_SOCKET;
		/*
		 * XXX should use stack gap!
		 * We don't because the control header is variable length
		 * up to 2048 bytes, and there's only 512 bytes of gap.
		 */
		error = copyout(&level, &((struct cmsghdr *)control)->
		    cmsg_level, sizeof(int));
		if (error)
			return error;
	}
done:
	error = sys_sendmsg(p, &bla, retval);
	/* replace level, just in case somebody cares. */
	if (level == SOL_SOCKET) {
		level = 1;
		/* don't worry about the error */
		copyout(&level, &((struct cmsghdr *)control)->cmsg_level,
		    sizeof(int));
	}
	return (error);
}

/*
 * Copy the linux_sockaddr structure pointed to by osa to kernel, adjust
 * family and convert to sockaddr, allocate stackgap and put the
 * the converted structure there.  Address on stackgap returned in sap.
 */
int
linux_sa_get(struct proc *p, caddr_t *sgp, struct sockaddr **sap,
    const struct linux_sockaddr *osa, int *osalen)
{
	int error, bdom;
	struct sockaddr *sa, *usa;
	struct linux_sockaddr *kosa;
	int alloclen;
#ifdef INET6
	int oldv6size;
	struct sockaddr_in6 *sin6;
#endif

	if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
		return (EINVAL);
	}

	if (osa->sa_family == AF_UNIX && *osalen > sizeof(struct sockaddr_un))
		alloclen = sizeof(struct sockaddr_un);
	else
		alloclen = *osalen;
#ifdef INET6
	oldv6size = 0;
	/*
	 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
	 * if it's a v4-mapped address, so reserve the proper space
	 * for it.
	 */
	if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
		alloclen = sizeof (struct sockaddr_in6);
		oldv6size = 1;
	}
#endif

	kosa = malloc(alloclen, M_TEMP, M_WAITOK);

	if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
		goto out;
	}

	bdom = linux_to_bsd_domain(kosa->sa_family);
	if (bdom == -1) {
		error = EINVAL;
		goto out;
	}

#ifdef INET6
	/*
	 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
	 * which lacks the scope id compared with RFC2553 one. If we detect
	 * the situation, reject the address.
	 *
	 * Still accept addresses for which the scope id is not used.
	 */
	if (oldv6size && bdom == AF_INET6) {
		sin6 = (struct sockaddr_in6 *)kosa;
		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
		    (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
		     !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
		     !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
		     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
		     !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
			sin6->sin6_scope_id = 0;
		} else {
			error = EINVAL;
			goto out;
		}
	} else
#endif
	if (bdom == AF_INET) {
		alloclen = sizeof(struct sockaddr_in);
	}

	sa = (struct sockaddr *) kosa;
	sa->sa_family = bdom;
	sa->sa_len = alloclen;

	usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen);
	if (!usa) {
		error = ENOMEM;
		goto out;
	}

	if ((error = copyout(sa, usa, alloclen))) {
		goto out;
	}

	*sap = usa;

    out:
	*osalen = alloclen;
	free(kosa, M_TEMP, 0);
	return (error);
}

int
linux_sa_put(struct sockaddr *osa)
{
	struct sockaddr sa;
	struct linux_sockaddr *kosa;
	int error, bdom, len;

	/*
	 * Only read/write the sockaddr family and length part, the rest is
	 * not changed.
	 */
	len = sizeof(sa.sa_len) + sizeof(sa.sa_family);

	error = copyin((caddr_t) osa, (caddr_t) &sa, len);
	if (error)
		return (error);

	bdom = bsd_to_linux_domain(sa.sa_family);
	if (bdom == -1)
		return (EINVAL);

	/* Note: we convert from sockaddr to linux_sockaddr here, too */
	kosa = (struct linux_sockaddr *) &sa;
	kosa->sa_family = bdom;
	error = copyout(kosa, osa, len);
	if (error)
		return (error);

	return (0);
}

/*
 * Entry point to all Linux socket calls. Just check which call to
 * make and take appropriate action.
 */
int
linux_sys_socketcall(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_socketcall_args /* {
		syscallarg(int) what;
		syscallarg(void *) args;
	} */ *uap = v;

	switch (SCARG(uap, what)) {
	case LINUX_SYS_socket:
		return linux_socket(p, SCARG(uap, args), retval);
	case LINUX_SYS_bind:
		return linux_bind(p, SCARG(uap, args), retval);
	case LINUX_SYS_connect:
		return linux_connect(p, SCARG(uap, args), retval);
	case LINUX_SYS_listen:
		return linux_listen(p, SCARG(uap, args), retval);
	case LINUX_SYS_accept:
		return linux_accept(p, SCARG(uap, args), retval);
	case LINUX_SYS_getsockname:
		return linux_getsockname(p, SCARG(uap, args), retval);
	case LINUX_SYS_getpeername:
		return linux_getpeername(p, SCARG(uap, args), retval);
	case LINUX_SYS_socketpair:
		return linux_socketpair(p, SCARG(uap, args), retval);
	case LINUX_SYS_send:
		return linux_send(p, SCARG(uap, args), retval);
	case LINUX_SYS_recv:
		return linux_recv(p, SCARG(uap, args), retval);
	case LINUX_SYS_sendto:
		return linux_sendto(p, SCARG(uap, args), retval);
	case LINUX_SYS_recvfrom:
		return linux_recvfrom(p, SCARG(uap, args), retval);
	case LINUX_SYS_shutdown:
		return linux_shutdown(p, SCARG(uap, args), retval);
	case LINUX_SYS_setsockopt:
		return linux_setsockopt(p, SCARG(uap, args), retval);
	case LINUX_SYS_getsockopt:
		return linux_getsockopt(p, SCARG(uap, args), retval);
	case LINUX_SYS_sendmsg:
		return linux_sendmsg(p, SCARG(uap, args), retval);
	case LINUX_SYS_recvmsg:
		return linux_recvmsg(p, SCARG(uap, args), retval);
	default:
		return ENOSYS;
	}
}

int
linux_ioctl_socket(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
{
	struct linux_sys_ioctl_args /* {
		syscallarg(int) fd;
		syscallarg(u_long) com;
		syscallarg(caddr_t) data;
	} */ *uap = v;
	u_long com;
	struct sys_ioctl_args ia;
	struct file *fp;
	struct filedesc *fdp;
	struct vnode *vp;
	int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
	struct ioctl_pt pt;
	void *data = SCARG(uap, data);
	int error = 0, isdev = 0, dosys = 1;

	fdp = p->p_fd;
	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
		return (EBADF);
	FREF(fp);

	if (fp->f_type == DTYPE_VNODE) {
		vp = (struct vnode *)fp->f_data;
		isdev = vp->v_type == VCHR;
	}

	/*
	 * Don't try to interpret socket ioctl calls that are done
	 * on a device file descriptor, just pass them through, to
	 * emulate Linux behaviour. Use PTIOCLINUX so that the
	 * device will only handle these if it's prepared to do
	 * so, to avoid unexpected things from happening.
	 */
	if (isdev) {
		dosys = 0;
		ioctlf = fp->f_ops->fo_ioctl;
		pt.com = SCARG(uap, com);
		pt.data = data;
		error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
		/*
		 * XXX hack: if the function returns EJUSTRETURN,
		 * it has stuffed a sysctl return value in pt.data.
		 */
		if (error == EJUSTRETURN) {
			retval[0] = (register_t)pt.data;
			error = 0;
		}
		goto out;
	}

	com = SCARG(uap, com);
	retval[0] = 0;

	switch (com) {
	case LINUX_FIOSETOWN:
		SCARG(&ia, com) = FIOSETOWN;
		break;
	case LINUX_SIOCSPGRP:
		SCARG(&ia, com) = SIOCSPGRP;
		break;
	case LINUX_FIOGETOWN:
		SCARG(&ia, com) = FIOGETOWN;
		break;
	case LINUX_SIOCGPGRP:
		SCARG(&ia, com) = SIOCGPGRP;
		break;
	case LINUX_SIOCATMARK:
		SCARG(&ia, com) = SIOCATMARK;
		break;
#if 0
	case LINUX_SIOCGSTAMP:
		SCARG(&ia, com) = SIOCGSTAMP;
		break;
#endif
	case LINUX_SIOCGIFCONF:
		SCARG(&ia, com) = OSIOCGIFCONF;
		break;
	case LINUX_SIOCGIFFLAGS:
		SCARG(&ia, com) = SIOCGIFFLAGS;
		break;
	case LINUX_SIOCGIFADDR:
		SCARG(&ia, com) = SIOCGIFADDR;
		break;
	case LINUX_SIOCGIFDSTADDR:
		SCARG(&ia, com) = SIOCGIFDSTADDR;
		break;
	case LINUX_SIOCGIFBRDADDR:
		SCARG(&ia, com) = SIOCGIFBRDADDR;
		break;
	case LINUX_SIOCGIFNETMASK:
		SCARG(&ia, com) = SIOCGIFNETMASK;
		break;
	case LINUX_SIOCGIFMETRIC:
		SCARG(&ia, com) = SIOCGIFMETRIC;
		break;
	case LINUX_SIOCGIFMTU:
		SCARG(&ia, com) = SIOCGIFMTU;
		break;
	case LINUX_SIOCADDMULTI:
		SCARG(&ia, com) = SIOCADDMULTI;
		break;
	case LINUX_SIOCDELMULTI:
		SCARG(&ia, com) = SIOCDELMULTI;
		break;
	case LINUX_SIOCGIFHWADDR: {
		struct linux_ifreq *ifr = data;
		struct sockaddr_dl *sdl;
		struct ifnet *ifp;

		/*
		 * Note that we don't actually respect the name in the ifreq
		 * structure, as Linux interface names are all different.
		 */
		TAILQ_FOREACH(ifp, &ifnet, if_list) {
			if (ifp->if_type != IFT_ETHER)
				continue;
			if ((sdl = ifp->if_sadl) &&
			    (sdl->sdl_family == AF_LINK) &&
			    (sdl->sdl_type == IFT_ETHER)) {
				error = copyout(LLADDR(sdl),
				    &ifr->ifr_hwaddr.sa_data,
				    LINUX_IFHWADDRLEN);
				dosys = 0;
				goto out;
			}
		}
		error = ENOENT;
		break;
	    }
	default:
		error = EINVAL;
	}

out:
	if (error == 0 && dosys) {
		SCARG(&ia, fd) = SCARG(uap, fd);
		SCARG(&ia, data) = data;
		error = sys_ioctl(p, &ia, retval);

		if (error == 0) {
			struct ifreq *ifr = data;

			switch (com) {
			case LINUX_SIOCGIFADDR:
			case LINUX_SIOCGIFDSTADDR:
			case LINUX_SIOCGIFBRDADDR:
			case LINUX_SIOCGIFNETMASK:
				error = linux_sa_put(&ifr->ifr_addr);
				break;
			}
		}
	}

	FRELE(fp, p);
	return (error);
}


code:
/*	$OpenBSD: linux_socket.h,v 1.12 2015/01/19 23:30:20 guenther Exp $	*/
/*	$NetBSD: linux_socket.h,v 1.3 1995/05/28 10:16:34 mycroft Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SOCKET_H_
#define _LINUX_SOCKET_H_

/*
 * Various Linux socket defines. Everything that is not re-defined here
 * is the same as in OpenBSD.
 *
 * Linux uses the old-style sockaddr, called linux_sockaddr here,
 * without sa_len member.  linux_sa_{get,put}() handle mapping from/to that.
 */

/*
 * Address families. There are fewer of them, and they're numbered
 * a bit different
 */

#define LINUX_AF_UNSPEC		0
#define LINUX_AF_UNIX		1
#define LINUX_AF_INET		2
#define LINUX_AF_AX25		3
#define LINUX_AF_IPX		4
#define LINUX_AF_APPLETALK	5
#define LINUX_AF_INET6		10
#define LINUX_AF_MAX		32

/*
 * Option levels for [gs]etsockopt(2). Only SOL_SOCKET is different,
 * the rest matches IPPROTO_XXX
 */

#define LINUX_SOL_SOCKET	1
#define LINUX_SOL_IP		0
#define LINUX_SOL_IPX		256
#define LINUX_SOL_AX25		257
#define LINUX_SOL_TCP		6
#define LINUX_SOL_UDP		17

/*
 * Options for [gs]etsockopt(2), socket level. For Linux, they
 * are not masks, but just increasing numbers.
 */

#define LINUX_SO_DEBUG		1
#define LINUX_SO_REUSEADDR	2
#define LINUX_SO_TYPE		3
#define LINUX_SO_ERROR		4
#define LINUX_SO_DONTROUTE	5
#define LINUX_SO_BROADCAST	6
#define LINUX_SO_SNDBUF		7
#define LINUX_SO_RCVBUF		8
#define LINUX_SO_KEEPALIVE	9
#define LINUX_SO_OOBINLINE	10
#define LINUX_SO_NO_CHECK	11
#define LINUX_SO_PRIORITY	12
#define LINUX_SO_LINGER		13

/*
 * Options for [gs]etsockopt(2), IP level.
 */

#define	LINUX_IP_TOS		1
#define	LINUX_IP_TTL		2
#define	LINUX_IP_HDRINCL	3
#define	LINUX_IP_MULTICAST_IF	32
#define	LINUX_IP_MULTICAST_TTL	33
#define	LINUX_IP_MULTICAST_LOOP	34
#define	LINUX_IP_ADD_MEMBERSHIP	35
#define	LINUX_IP_DROP_MEMBERSHIP 36

/*
 * Options for [gs]etsockopt(2), TCP level.
 */

#define	LINUX_TCP_NODELAY	1
#define	LINUX_TCP_MAXSEG	2

/*
 * Flags for recv(2) and send(2) family functions.
 * The first 3 match MSG_XXX.
 */

#define	LINUX_MSG_OOB		1
#define	LINUX_MSG_PEEK		2
#define	LINUX_MSG_DONTROUTE	4
#define	LINUX_MSG_DONTWAIT	0x40
#define	LINUX_MSG_WAITALL	0x100
#define	LINUX_MSG_NOSIGNAL	0x4000

/* Mask out extra type-related options */
#define LINUX_SOCKET_TYPE_MASK	0xf
#define LINUX_SOCK_CLOEXEC	02000000
#define LINUX_SOCK_NONBLOCK	00004000

struct linux_sockaddr {
	unsigned short	sa_family;
	char		sa_data[14];
};

struct linux_ifmap {
	unsigned long	mem_start;
	unsigned long	mem_end;
	unsigned short	base_addr;
	unsigned char	irq;
	unsigned char	dma;
	unsigned char	port;
};

struct linux_ifreq {
#define LINUX_IFHWADDRLEN     6
#define LINUX_IFNAMSIZ        16
	union {
		char ifrn_name[LINUX_IFNAMSIZ];		/* if name, e.g. "en0" */
	} ifr_ifrn;

	union {
		struct linux_sockaddr	ifru_addr;
		struct linux_sockaddr	ifru_dstaddr;
		struct linux_sockaddr	ifru_broadaddr;
		struct linux_sockaddr	ifru_netmask;
		struct linux_sockaddr	ifru_hwaddr;
		short			ifru_flags;
		int			ifru_metric;
		int			ifru_mtu;
		struct linux_ifmap	ifru_map;
		char			ifru_slave[LINUX_IFNAMSIZ];
		caddr_t			ifru_data;
	} ifr_ifru;
};

#define ifr_name	ifr_ifrn.ifrn_name		/* interface name */
#define ifr_hwaddr	ifr_ifru.ifru_hwaddr		/* MAC address */

#endif /* _LINUX_SOCKET_H_ */


code:
/*	$OpenBSD: linux_socketcall.h,v 1.6 2015/01/19 23:30:20 guenther Exp $	*/
/*	$NetBSD: linux_socketcall.h,v 1.1 1995/02/28 23:26:05 fvdl Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SOCKETCALL_H_
#define _LINUX_SOCKETCALL_H_

/*
 * Values passed to the Linux socketcall() syscall, determining the actual
 * action to take.
 */
#define LINUX_SYS_socket	1
#define LINUX_SYS_bind		2
#define LINUX_SYS_connect	3
#define LINUX_SYS_listen	4
#define LINUX_SYS_accept	5
#define LINUX_SYS_getsockname	6
#define LINUX_SYS_getpeername	7
#define LINUX_SYS_socketpair	8
#define LINUX_SYS_send		9
#define LINUX_SYS_recv		10
#define LINUX_SYS_sendto	11
#define LINUX_SYS_recvfrom	12
#define LINUX_SYS_shutdown	13
#define LINUX_SYS_setsockopt	14
#define LINUX_SYS_getsockopt	15
#define LINUX_SYS_sendmsg	16
#define LINUX_SYS_recvmsg	17

/*
 * Structures for the arguments of the different system calls. This looks
 * a little better than copyin() of all values one by one.
 */
struct linux_socket_args {
	int domain;
	int type;
	int protocol;
};

struct linux_bind_args {
	int s;
	struct linux_sockaddr *name;
	int namelen;
};

struct linux_connect_args {
	int s;
	struct linux_sockaddr *name;
	int namelen;
};

struct linux_listen_args {
	int s;
	int backlog;
};

struct linux_accept_args {
	int s;
	struct sockaddr *addr;
	int *namelen;
};

struct linux_getsockname_args {
	int s;
	struct sockaddr *addr;
	int *namelen;
};

struct linux_getpeername_args {
	int s;
	struct sockaddr *addr;
	int *namelen;
};

struct linux_socketpair_args {
	int domain;
	int type;
	int protocol;
	int *rsv;
};

struct linux_send_args {
	int s;
	void *msg;
	int len;
	int flags;
};

struct linux_recv_args {
	int s;
	void *msg;
	int len;
	int flags;
};

struct linux_sendto_args {
	int s;
	void *msg;
	int len;
	int flags;
	struct linux_sockaddr *to;
	int tolen;
};

struct linux_recvfrom_args {
	int s;
	void *buf;
	int len;
	int flags;
	struct sockaddr *from;
	int *fromlen;
};

struct linux_shutdown_args {
	int s;
	int how;
};

struct linux_getsockopt_args {
	int s;
	int level;
	int optname;
	void *optval;
	int *optlen;
};

struct linux_setsockopt_args {
	int s;
	int level;
	int optname;
	void *optval;
	int optlen;
};

struct linux_sendmsg_args {
	int s;
	struct msghdr *msg;
	int flags;
};

struct linux_recvmsg_args {
	int s;
	struct msghdr *msg;
	int flags;
};

#endif /* _LINUX_SOCKETCALL_H_ */


code:
/*	$OpenBSD: linux_sockio.h,v 1.9 2011/04/05 22:54:31 pirofti Exp $ */
/*	$NetBSD: linux_sockio.h,v 1.5 1996/03/08 04:56:07 mycroft Exp $	*/

/*
 * Copyright (c) 1995 Frank van der Linden
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed for the NetBSD Project
 *      by Frank van der Linden
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_SOCKIO_H_
#define _LINUX_SOCKIO_H_

#define	LINUX_FIOSETOWN		_LINUX_IO(0x89, 1)
#define	LINUX_SIOCSPGRP		_LINUX_IO(0x89, 2)
#define	LINUX_FIOGETOWN		_LINUX_IO(0x89, 3)
#define	LINUX_SIOCGPGRP		_LINUX_IO(0x89, 4)
#define	LINUX_SIOCATMARK	_LINUX_IO(0x89, 5)
#define	LINUX_SIOCGSTAMP	_LINUX_IO(0x89, 6)
#define	LINUX_SIOCGIFCONF	_LINUX_IO(0x89, 18)
#define	LINUX_SIOCGIFFLAGS	_LINUX_IO(0x89, 19)
#define LINUX_SIOCSIFFLAGS	_LINUX_IO(0x89, 20)
#define	LINUX_SIOCGIFADDR	_LINUX_IO(0x89, 21)
#define LINUX_SIOCSIFADDR	_LINUX_IO(0x89, 22)
#define	LINUX_SIOCGIFDSTADDR	_LINUX_IO(0x89, 23)
#define	LINUX_SIOCGIFBRDADDR	_LINUX_IO(0x89, 25)
#define	LINUX_SIOCGIFNETMASK	_LINUX_IO(0x89, 27)
#define	LINUX_SIOCGIFMETRIC	_LINUX_IO(0x89, 29)
#define	LINUX_SIOCGIFMTU	_LINUX_IO(0x89, 33)
#define	LINUX_SIOCGIFHWADDR	_LINUX_IO(0x89, 39)
#define LINUX_SIOCADDMULTI	_LINUX_IO(0x89, 49)
#define LINUX_SIOCDELMULTI	_LINUX_IO(0x89, 50)
#define LINUX_SIOCGIFBR		_LINUX_IO(0x89, 64)
#define LINUX_SIOCDEVPRIVATE	_LINUX_IO(0x89, 0xf0)

#endif /* _LINUX_SOCKIO_H_ */