svr4_stream.c revision 139743
1139743Simp/*-
243412Snewton * Copyright (c) 1998 Mark Newton.  All rights reserved.
343412Snewton * Copyright (c) 1994, 1996 Christos Zoulas.  All rights reserved.
443412Snewton *
543412Snewton * Redistribution and use in source and binary forms, with or without
643412Snewton * modification, are permitted provided that the following conditions
743412Snewton * are met:
843412Snewton * 1. Redistributions of source code must retain the above copyright
943412Snewton *    notice, this list of conditions and the following disclaimer.
1043412Snewton * 2. Redistributions in binary form must reproduce the above copyright
1143412Snewton *    notice, this list of conditions and the following disclaimer in the
1243412Snewton *    documentation and/or other materials provided with the distribution.
1343412Snewton * 3. All advertising materials mentioning features or use of this software
1443412Snewton *    must display the following acknowledgement:
1543412Snewton *	This product includes software developed by Christos Zoulas.
1643412Snewton * 4. The name of the author may not be used to endorse or promote products
1743412Snewton *    derived from this software without specific prior written permission.
1843412Snewton *
1943412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2043412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2143412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2243412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2343412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2443412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2543412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2643412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2743412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2843412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2943412Snewton */
3043412Snewton
3143412Snewton/*
3243412Snewton * Pretend that we have streams...
3343412Snewton * Yes, this is gross.
3443412Snewton *
3543412Snewton * ToDo: The state machine for getmsg needs re-thinking
3643412Snewton */
3743412Snewton
38116174Sobrien#include <sys/cdefs.h>
39116174Sobrien__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_stream.c 139743 2005-01-05 22:34:37Z imp $");
40116174Sobrien
4143412Snewton#define COMPAT_43 1
4243412Snewton
43104571Srwatson#include "opt_mac.h"
44104571Srwatson
4543412Snewton#include <sys/param.h>
4643412Snewton#include <sys/systm.h>
4776166Smarkm#include <sys/fcntl.h>
4843412Snewton#include <sys/filedesc.h>
4943412Snewton#include <sys/filio.h>
5076166Smarkm#include <sys/lock.h>
5176166Smarkm#include <sys/malloc.h>
5276166Smarkm#include <sys/file.h> 		/* Must come after sys/malloc.h */
53104571Srwatson#include <sys/mac.h>
5443412Snewton#include <sys/mbuf.h>
5576166Smarkm#include <sys/mutex.h>
5676166Smarkm#include <sys/proc.h>
5743412Snewton#include <sys/protosw.h>
5843412Snewton#include <sys/signal.h>
5943412Snewton#include <sys/signalvar.h>
6076166Smarkm#include <sys/socket.h>
6176166Smarkm#include <sys/socketvar.h>
6243412Snewton#include <sys/stat.h>
63134266Sjhb#include <sys/syscallsubr.h>
6443412Snewton#include <sys/sysproto.h>
6576166Smarkm#include <sys/uio.h>
6676166Smarkm#include <sys/ktrace.h>		/* Must come after sys/uio.h */
6776166Smarkm#include <sys/un.h>
6843412Snewton
6976166Smarkm#include <netinet/in.h>
7076166Smarkm
7165302Sobrien#include <compat/svr4/svr4.h>
7265302Sobrien#include <compat/svr4/svr4_types.h>
7365302Sobrien#include <compat/svr4/svr4_util.h>
7465302Sobrien#include <compat/svr4/svr4_signal.h>
7565302Sobrien#include <compat/svr4/svr4_proto.h>
7665302Sobrien#include <compat/svr4/svr4_stropts.h>
7765302Sobrien#include <compat/svr4/svr4_timod.h>
7865302Sobrien#include <compat/svr4/svr4_sockmod.h>
7965302Sobrien#include <compat/svr4/svr4_ioctl.h>
8065302Sobrien#include <compat/svr4/svr4_socket.h>
8143412Snewton
8243412Snewton/* Utils */
8392761Salfredstatic int clean_pipe(struct thread *, const char *);
8492761Salfredstatic void getparm(struct file *, struct svr4_si_sockparms *);
8592761Salfredstatic int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
8692761Salfred			       struct file *);
8792761Salfredstatic int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
8892761Salfred			       struct file *);
8943412Snewton
9043412Snewton/* Address Conversions */
9192761Salfredstatic void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
9292761Salfred					const struct sockaddr_in *);
9392761Salfredstatic void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
9492761Salfred					const struct sockaddr_un *);
9592761Salfredstatic void netaddr_to_sockaddr_in(struct sockaddr_in *,
9692761Salfred					const struct svr4_strmcmd *);
9792761Salfredstatic void netaddr_to_sockaddr_un(struct sockaddr_un *,
9892761Salfred					const struct svr4_strmcmd *);
9943412Snewton
10043412Snewton/* stream ioctls */
10192761Salfredstatic int i_nread(struct file *, struct thread *, register_t *, int,
10292761Salfred			u_long, caddr_t);
10392761Salfredstatic int i_fdinsert(struct file *, struct thread *, register_t *, int,
10492761Salfred			   u_long, caddr_t);
10592761Salfredstatic int i_str(struct file *, struct thread *, register_t *, int,
10692761Salfred			u_long, caddr_t);
10792761Salfredstatic int i_setsig(struct file *, struct thread *, register_t *, int,
10892761Salfred			u_long, caddr_t);
10992761Salfredstatic int i_getsig(struct file *, struct thread *, register_t *, int,
11092761Salfred			u_long, caddr_t);
11192761Salfredstatic int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
11292761Salfred			     u_long, caddr_t);
11392761Salfredstatic int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
11492761Salfred			     u_long, caddr_t);
11543412Snewton
11643412Snewton/* i_str sockmod calls */
11792761Salfredstatic int sockmod(struct file *, int, struct svr4_strioctl *,
11892761Salfred			      struct thread *);
11992761Salfredstatic int si_listen(struct file *, int, struct svr4_strioctl *,
12092761Salfred			      struct thread *);
12192761Salfredstatic int si_ogetudata(struct file *, int, struct svr4_strioctl *,
12292761Salfred			      struct thread *);
12392761Salfredstatic int si_sockparams(struct file *, int, struct svr4_strioctl *,
12492761Salfred			      struct thread *);
12592761Salfredstatic int si_shutdown	(struct file *, int, struct svr4_strioctl *,
12692761Salfred			      struct thread *);
12792761Salfredstatic int si_getudata(struct file *, int, struct svr4_strioctl *,
12892761Salfred			      struct thread *);
12943412Snewton
13043412Snewton/* i_str timod calls */
13192761Salfredstatic int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
13292761Salfredstatic int ti_getinfo(struct file *, int, struct svr4_strioctl *,
13392761Salfred			      struct thread *);
13492761Salfredstatic int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
13543412Snewton
13643412Snewton/* infrastructure */
13792761Salfredstatic int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
13843412Snewton
13992761Salfredstatic int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
14092761Salfred			    caddr_t namelenp);
14143412Snewton
14243412Snewton/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
14343412Snewton * it isn't part of a "public" interface;  We're supposed to use
14443412Snewton * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
14543412Snewton * that matter.  Solution:  Suck sendit()/recvit() into here where we
14643412Snewton * can do what we like.
14743412Snewton *
14843412Snewton * I hate code duplication.
14943412Snewton *
15043412Snewton * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
15143412Snewton */
15243412Snewtonstatic int
15383366Sjuliansvr4_sendit(td, s, mp, flags)
15483366Sjulian	register struct thread *td;
15543412Snewton	int s;
15643412Snewton	register struct msghdr *mp;
15743412Snewton	int flags;
15843412Snewton{
15943412Snewton	struct uio auio;
16043412Snewton	register struct iovec *iov;
16143412Snewton	register int i;
16243412Snewton	struct mbuf *control;
16343412Snewton	struct sockaddr *to;
16443412Snewton	int len, error;
16543412Snewton	struct socket *so;
16643412Snewton#ifdef KTRACE
167131897Sphk	struct uio *ktruio = NULL;
16843412Snewton#endif
16943412Snewton
17086487Sdillon	if ((error = fgetsock(td, s, &so, NULL)) != 0)
17143412Snewton		return (error);
172104571Srwatson
173104571Srwatson#ifdef MAC
174130398Srwatson	SOCK_LOCK(so);
175104571Srwatson	error = mac_check_socket_send(td->td_ucred, so);
176130398Srwatson	SOCK_UNLOCK(so);
177104571Srwatson	if (error)
178104571Srwatson		goto done1;
179104571Srwatson#endif
180104571Srwatson
18143412Snewton	auio.uio_iov = mp->msg_iov;
18243412Snewton	auio.uio_iovcnt = mp->msg_iovlen;
18343412Snewton	auio.uio_segflg = UIO_USERSPACE;
18443412Snewton	auio.uio_rw = UIO_WRITE;
18583366Sjulian	auio.uio_td = td;
18643412Snewton	auio.uio_offset = 0;			/* XXX */
18743412Snewton	auio.uio_resid = 0;
18843412Snewton	iov = mp->msg_iov;
18943412Snewton	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
19069084Sdillon		if ((auio.uio_resid += iov->iov_len) < 0) {
19186487Sdillon			error = EINVAL;
19286487Sdillon			goto done1;
19369084Sdillon		}
19443412Snewton	}
19543412Snewton	if (mp->msg_name) {
19643412Snewton		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
19786487Sdillon		if (error)
19886487Sdillon			goto done1;
19969084Sdillon	} else {
20043412Snewton		to = 0;
20169084Sdillon	}
20243412Snewton	if (mp->msg_control) {
20343412Snewton		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
20443412Snewton			error = EINVAL;
20543412Snewton			goto bad;
20643412Snewton		}
20743412Snewton		error = sockargs(&control, mp->msg_control,
20843412Snewton		    mp->msg_controllen, MT_CONTROL);
20943412Snewton		if (error)
21043412Snewton			goto bad;
21169084Sdillon	} else {
21243412Snewton		control = 0;
21369084Sdillon	}
21443412Snewton#ifdef KTRACE
215131897Sphk	if (KTRPOINT(td, KTR_GENIO))
216131897Sphk		ktruio = cloneuio(&auio);
21743412Snewton#endif
21843412Snewton	len = auio.uio_resid;
21943412Snewton	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
22083366Sjulian						     flags, td);
22143412Snewton	if (error) {
22243412Snewton		if (auio.uio_resid != len && (error == ERESTART ||
22343412Snewton		    error == EINTR || error == EWOULDBLOCK))
22443412Snewton			error = 0;
22573929Sjhb		if (error == EPIPE) {
22683366Sjulian			PROC_LOCK(td->td_proc);
22783366Sjulian			psignal(td->td_proc, SIGPIPE);
22883366Sjulian			PROC_UNLOCK(td->td_proc);
22973929Sjhb		}
23043412Snewton	}
23143412Snewton	if (error == 0)
23283366Sjulian		td->td_retval[0] = len - auio.uio_resid;
23343412Snewton#ifdef KTRACE
234131897Sphk	if (ktruio != NULL) {
235131897Sphk		ktruio->uio_resid = td->td_retval[0];
236131897Sphk		ktrgenio(s, UIO_WRITE, ktruio, error);
23743412Snewton	}
23843412Snewton#endif
23943412Snewtonbad:
24043412Snewton	if (to)
24143412Snewton		FREE(to, M_SONAME);
24286487Sdillondone1:
24386487Sdillon	fputsock(so);
24443412Snewton	return (error);
24543412Snewton}
24643412Snewton
24743412Snewtonstatic int
24883366Sjuliansvr4_recvit(td, s, mp, namelenp)
24983366Sjulian	register struct thread *td;
25043412Snewton	int s;
25143412Snewton	register struct msghdr *mp;
25243412Snewton	caddr_t namelenp;
25343412Snewton{
25443412Snewton	struct uio auio;
25543412Snewton	register struct iovec *iov;
25643412Snewton	register int i;
25743412Snewton	int len, error;
25843412Snewton	struct mbuf *m, *control = 0;
25943412Snewton	caddr_t ctlbuf;
26043412Snewton	struct socket *so;
26143412Snewton	struct sockaddr *fromsa = 0;
26243412Snewton#ifdef KTRACE
263131897Sphk	struct uio *ktruio = NULL;
26443412Snewton#endif
26543412Snewton
26686487Sdillon	if ((error = fgetsock(td, s, &so, NULL)) != 0)
26743412Snewton		return (error);
268104571Srwatson
269104571Srwatson#ifdef MAC
270130398Srwatson	SOCK_LOCK(so);
271104571Srwatson	error = mac_check_socket_receive(td->td_ucred, so);
272130398Srwatson	SOCK_UNLOCK(so);
273104571Srwatson	if (error)
274104571Srwatson		goto done1;
275104571Srwatson#endif
276104571Srwatson
27743412Snewton	auio.uio_iov = mp->msg_iov;
27843412Snewton	auio.uio_iovcnt = mp->msg_iovlen;
27943412Snewton	auio.uio_segflg = UIO_USERSPACE;
28043412Snewton	auio.uio_rw = UIO_READ;
28183366Sjulian	auio.uio_td = td;
28243412Snewton	auio.uio_offset = 0;			/* XXX */
28343412Snewton	auio.uio_resid = 0;
28443412Snewton	iov = mp->msg_iov;
28543412Snewton	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
28669084Sdillon		if ((auio.uio_resid += iov->iov_len) < 0) {
28786487Sdillon			error = EINVAL;
28886487Sdillon			goto done1;
28969084Sdillon		}
29043412Snewton	}
29143412Snewton#ifdef KTRACE
292131897Sphk	if (KTRPOINT(td, KTR_GENIO))
293131897Sphk		ktruio = cloneuio(&auio);
29443412Snewton#endif
29543412Snewton	len = auio.uio_resid;
29643412Snewton	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
29743412Snewton	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
29843412Snewton	    &mp->msg_flags);
29943412Snewton	if (error) {
30043412Snewton		if (auio.uio_resid != len && (error == ERESTART ||
30143412Snewton		    error == EINTR || error == EWOULDBLOCK))
30243412Snewton			error = 0;
30343412Snewton	}
30443412Snewton#ifdef KTRACE
305131897Sphk	if (ktruio != NULL) {
306131897Sphk		ktruio->uio_resid = len - auio.uio_resid;
307131897Sphk		ktrgenio(s, UIO_READ, ktruio, error);
30843412Snewton	}
30943412Snewton#endif
31043412Snewton	if (error)
31143412Snewton		goto out;
31283366Sjulian	td->td_retval[0] = len - auio.uio_resid;
31343412Snewton	if (mp->msg_name) {
31443412Snewton		len = mp->msg_namelen;
31543412Snewton		if (len <= 0 || fromsa == 0)
31643412Snewton			len = 0;
31743412Snewton		else {
31843412Snewton			/* save sa_len before it is destroyed by MSG_COMPAT */
31943412Snewton			len = MIN(len, fromsa->sa_len);
32043412Snewton			error = copyout(fromsa,
32143412Snewton			    (caddr_t)mp->msg_name, (unsigned)len);
32243412Snewton			if (error)
32343412Snewton				goto out;
32443412Snewton		}
32543412Snewton		mp->msg_namelen = len;
32643412Snewton		if (namelenp &&
32743412Snewton		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
32843412Snewton			goto out;
32943412Snewton		}
33043412Snewton	}
33143412Snewton	if (mp->msg_control) {
33243412Snewton		len = mp->msg_controllen;
33343412Snewton		m = control;
33443412Snewton		mp->msg_controllen = 0;
33543412Snewton		ctlbuf = (caddr_t) mp->msg_control;
33643412Snewton
33743412Snewton		while (m && len > 0) {
33843412Snewton			unsigned int tocopy;
33943412Snewton
34043412Snewton			if (len >= m->m_len)
34143412Snewton				tocopy = m->m_len;
34243412Snewton			else {
34343412Snewton				mp->msg_flags |= MSG_CTRUNC;
34443412Snewton				tocopy = len;
34543412Snewton			}
34643412Snewton
34749267Snewton			if ((error = copyout((caddr_t)mtod(m, caddr_t),
34849267Snewton					ctlbuf, tocopy)) != 0)
34943412Snewton				goto out;
35043412Snewton
35143412Snewton			ctlbuf += tocopy;
35243412Snewton			len -= tocopy;
35343412Snewton			m = m->m_next;
35443412Snewton		}
35553678Sphk		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
35643412Snewton	}
35743412Snewtonout:
35843412Snewton	if (fromsa)
35943412Snewton		FREE(fromsa, M_SONAME);
36043412Snewton	if (control)
36143412Snewton		m_freem(control);
36286487Sdillondone1:
36386487Sdillon	fputsock(so);
36443412Snewton	return (error);
36543412Snewton}
36643412Snewton
36743412Snewton#ifdef DEBUG_SVR4
36892761Salfredstatic void bufprint(u_char *, size_t);
36992761Salfredstatic int show_ioc(const char *, struct svr4_strioctl *);
37092761Salfredstatic int show_strbuf(struct svr4_strbuf *);
37192761Salfredstatic void show_msg(const char *, int, struct svr4_strbuf *,
37292761Salfred			  struct svr4_strbuf *, int);
37343412Snewton
37443412Snewtonstatic void
37543412Snewtonbufprint(buf, len)
37643412Snewton	u_char *buf;
37743412Snewton	size_t len;
37843412Snewton{
37943412Snewton	size_t i;
38043412Snewton
38143412Snewton	uprintf("\n\t");
38243412Snewton	for (i = 0; i < len; i++) {
38343412Snewton		uprintf("%x ", buf[i]);
38443412Snewton		if (i && (i % 16) == 0)
38543412Snewton			uprintf("\n\t");
38643412Snewton	}
38743412Snewton}
38843412Snewton
38943412Snewtonstatic int
39043412Snewtonshow_ioc(str, ioc)
39143412Snewton	const char		*str;
39243412Snewton	struct svr4_strioctl	*ioc;
39343412Snewton{
394121275Stjr	u_char *ptr = NULL;
395121275Stjr	int len;
39643412Snewton	int error;
39743412Snewton
398121275Stjr	len = ioc->len;
399121275Stjr	if (len > 1024)
400121275Stjr		len = 1024;
401121275Stjr
402121275Stjr	if (len > 0) {
403121275Stjr		ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
404121275Stjr		if ((error = copyin(ioc->buf, ptr, len)) != 0) {
405121275Stjr			free((char *) ptr, M_TEMP);
406121275Stjr			return error;
407121275Stjr		}
408121275Stjr	}
409121275Stjr
41043412Snewton	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
41143412Snewton	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
41243412Snewton
413121275Stjr	if (ptr != NULL)
414121275Stjr		bufprint(ptr, len);
41543412Snewton
41643412Snewton	uprintf("}\n");
41743412Snewton
418121275Stjr	if (ptr != NULL)
419121275Stjr		free((char *) ptr, M_TEMP);
42043412Snewton	return 0;
42143412Snewton}
42243412Snewton
42343412Snewton
42443412Snewtonstatic int
42543412Snewtonshow_strbuf(str)
42643412Snewton	struct svr4_strbuf *str;
42743412Snewton{
42843412Snewton	int error;
42943412Snewton	u_char *ptr = NULL;
43043412Snewton	int maxlen = str->maxlen;
43143412Snewton	int len = str->len;
43243412Snewton
433121275Stjr	if (maxlen > 8192)
434121275Stjr		maxlen = 8192;
435121275Stjr
43643412Snewton	if (maxlen < 0)
43743412Snewton		maxlen = 0;
43843412Snewton
43943412Snewton	if (len >= maxlen)
44043412Snewton		len = maxlen;
44143412Snewton
44243412Snewton	if (len > 0) {
443111119Simp	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
44443412Snewton
44543412Snewton	    if ((error = copyin(str->buf, ptr, len)) != 0) {
44643412Snewton		    free((char *) ptr, M_TEMP);
44743412Snewton		    return error;
44843412Snewton	    }
44943412Snewton	}
45043412Snewton
45143412Snewton	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
45243412Snewton
45343412Snewton	if (ptr)
45443412Snewton		bufprint(ptr, len);
45543412Snewton
45643412Snewton	uprintf("]}");
45743412Snewton
45843412Snewton	if (ptr)
45943412Snewton		free((char *) ptr, M_TEMP);
46043412Snewton
46143412Snewton	return 0;
46243412Snewton}
46343412Snewton
46443412Snewton
46543412Snewtonstatic void
46643412Snewtonshow_msg(str, fd, ctl, dat, flags)
46743412Snewton	const char		*str;
46843412Snewton	int			 fd;
46943412Snewton	struct svr4_strbuf	*ctl;
47043412Snewton	struct svr4_strbuf	*dat;
47143412Snewton	int			 flags;
47243412Snewton{
47343412Snewton	struct svr4_strbuf	buf;
47443412Snewton	int error;
47543412Snewton
47643412Snewton	uprintf("%s(%d", str, fd);
47743412Snewton	if (ctl != NULL) {
47843412Snewton		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
47943412Snewton			return;
48043412Snewton		show_strbuf(&buf);
48143412Snewton	}
48243412Snewton	else
48343412Snewton		uprintf(", NULL");
48443412Snewton
48543412Snewton	if (dat != NULL) {
48643412Snewton		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
48743412Snewton			return;
48843412Snewton		show_strbuf(&buf);
48943412Snewton	}
49043412Snewton	else
49143412Snewton		uprintf(", NULL");
49243412Snewton
49343412Snewton	uprintf(", %x);\n", flags);
49443412Snewton}
49543412Snewton
49643412Snewton#endif /* DEBUG_SVR4 */
49743412Snewton
49843412Snewton/*
49943412Snewton * We are faced with an interesting situation. On svr4 unix sockets
50043412Snewton * are really pipes. But we really have sockets, and we might as
50143412Snewton * well use them. At the point where svr4 calls TI_BIND, it has
50243412Snewton * already created a named pipe for the socket using mknod(2).
50343412Snewton * We need to create a socket with the same name when we bind,
50443412Snewton * so we need to remove the pipe before, otherwise we'll get address
50543412Snewton * already in use. So we *carefully* remove the pipe, to avoid
50643412Snewton * using this as a random file removal tool. We use system calls
50743412Snewton * to avoid code duplication.
50843412Snewton */
50943412Snewtonstatic int
51083366Sjulianclean_pipe(td, path)
51183366Sjulian	struct thread *td;
51243412Snewton	const char *path;
51343412Snewton{
51443412Snewton	struct lstat_args la;
51543412Snewton	struct unlink_args ua;
51643412Snewton	struct stat st;
51743412Snewton	int error;
51843412Snewton	caddr_t sg = stackgap_init();
51943412Snewton	size_t l = strlen(path) + 1;
52043412Snewton	void *tpath;
52143412Snewton
522121275Stjr	if ((tpath = stackgap_alloc(&sg, l)) == NULL)
523121275Stjr		return ENAMETOOLONG;
524107849Salfred	la.ub = stackgap_alloc(&sg, sizeof(struct stat));
52543412Snewton
52643412Snewton	if ((error = copyout(path, tpath, l)) != 0)
52743412Snewton		return error;
52843412Snewton
529107849Salfred	la.path = tpath;
53043412Snewton
53183366Sjulian	if ((error = lstat(td, &la)) != 0)
53243412Snewton		return 0;
53343412Snewton
534107849Salfred	if ((error = copyin(la.ub, &st, sizeof(st))) != 0)
53543412Snewton		return 0;
53643412Snewton
53743412Snewton	/*
53843412Snewton	 * Make sure we are dealing with a mode 0 named pipe.
53943412Snewton	 */
54043412Snewton	if ((st.st_mode & S_IFMT) != S_IFIFO)
54143412Snewton		return 0;
54243412Snewton
54343412Snewton	if ((st.st_mode & ALLPERMS) != 0)
54443412Snewton		return 0;
54543412Snewton
546107849Salfred	ua.path = la.path;
54743412Snewton
54883366Sjulian	if ((error = unlink(td, &ua)) != 0) {
54943412Snewton		DPRINTF(("clean_pipe: unlink failed %d\n", error));
55043412Snewton		return error;
55143412Snewton	}
55243412Snewton
55343412Snewton	return 0;
55443412Snewton}
55543412Snewton
55643412Snewton
55743412Snewtonstatic void
55843412Snewtonsockaddr_to_netaddr_in(sc, sain)
55943412Snewton	struct svr4_strmcmd *sc;
56043412Snewton	const struct sockaddr_in *sain;
56143412Snewton{
56243412Snewton	struct svr4_netaddr_in *na;
56343412Snewton	na = SVR4_ADDROF(sc);
56443412Snewton
56543412Snewton	na->family = sain->sin_family;
56643412Snewton	na->port = sain->sin_port;
56743412Snewton	na->addr = sain->sin_addr.s_addr;
56843412Snewton	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
56943412Snewton		 na->addr));
57043412Snewton}
57143412Snewton
57243412Snewton
57343412Snewtonstatic void
57443412Snewtonsockaddr_to_netaddr_un(sc, saun)
57543412Snewton	struct svr4_strmcmd *sc;
57643412Snewton	const struct sockaddr_un *saun;
57743412Snewton{
57843412Snewton	struct svr4_netaddr_un *na;
57943412Snewton	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
58043412Snewton	    sizeof(*sc);
58143412Snewton	const char *src;
58243412Snewton
58343412Snewton	na = SVR4_ADDROF(sc);
58443412Snewton	na->family = saun->sun_family;
58543412Snewton	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
58643412Snewton		if (dst == edst)
58743412Snewton			break;
58843412Snewton	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
58943412Snewton}
59043412Snewton
59143412Snewton
59243412Snewtonstatic void
59343412Snewtonnetaddr_to_sockaddr_in(sain, sc)
59443412Snewton	struct sockaddr_in *sain;
59543412Snewton	const struct svr4_strmcmd *sc;
59643412Snewton{
59743412Snewton	const struct svr4_netaddr_in *na;
59843412Snewton
59943412Snewton
60043412Snewton	na = SVR4_C_ADDROF(sc);
60143412Snewton	memset(sain, 0, sizeof(*sain));
60243412Snewton	sain->sin_len = sizeof(*sain);
60343412Snewton	sain->sin_family = na->family;
60443412Snewton	sain->sin_port = na->port;
60543412Snewton	sain->sin_addr.s_addr = na->addr;
60643412Snewton	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
60743412Snewton		 sain->sin_port, sain->sin_addr.s_addr));
60843412Snewton}
60943412Snewton
61043412Snewton
61143412Snewtonstatic void
61243412Snewtonnetaddr_to_sockaddr_un(saun, sc)
61343412Snewton	struct sockaddr_un *saun;
61443412Snewton	const struct svr4_strmcmd *sc;
61543412Snewton{
61643412Snewton	const struct svr4_netaddr_un *na;
61743412Snewton	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
61843412Snewton	const char *src;
61943412Snewton
62043412Snewton	na = SVR4_C_ADDROF(sc);
62143412Snewton	memset(saun, 0, sizeof(*saun));
62243412Snewton	saun->sun_family = na->family;
62343412Snewton	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
62443412Snewton		if (dst == edst)
62543412Snewton			break;
62643412Snewton	saun->sun_len = dst - saun->sun_path;
62743412Snewton	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
62843412Snewton		 saun->sun_path));
62943412Snewton}
63043412Snewton
63143412Snewton
63243412Snewtonstatic void
63343412Snewtongetparm(fp, pa)
63443412Snewton	struct file *fp;
63543412Snewton	struct svr4_si_sockparms *pa;
63643412Snewton{
63789306Salfred	struct svr4_strm *st;
63889306Salfred	struct socket *so;
63943412Snewton
64089306Salfred	st = svr4_stream_get(fp);
64143412Snewton	if (st == NULL)
64243412Snewton		return;
64343412Snewton
644109153Sdillon	so = fp->f_data;
64589306Salfred
64643412Snewton	pa->family = st->s_family;
64743412Snewton
64843412Snewton	switch (so->so_type) {
64943412Snewton	case SOCK_DGRAM:
65043412Snewton		pa->type = SVR4_T_CLTS;
65143412Snewton		pa->protocol = IPPROTO_UDP;
65243412Snewton		DPRINTF(("getparm(dgram)\n"));
65343412Snewton		return;
65443412Snewton
65543412Snewton	case SOCK_STREAM:
65643412Snewton	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
65743412Snewton		pa->protocol = IPPROTO_IP;
65843412Snewton		DPRINTF(("getparm(stream)\n"));
65943412Snewton		return;
66043412Snewton
66143412Snewton	case SOCK_RAW:
66243412Snewton		pa->type = SVR4_T_CLTS;
66343412Snewton		pa->protocol = IPPROTO_RAW;
66443412Snewton		DPRINTF(("getparm(raw)\n"));
66543412Snewton		return;
66643412Snewton
66743412Snewton	default:
66843412Snewton		pa->type = 0;
66943412Snewton		pa->protocol = 0;
67043412Snewton		DPRINTF(("getparm(type %d?)\n", so->so_type));
67143412Snewton		return;
67243412Snewton	}
67343412Snewton}
67443412Snewton
67543412Snewton
67643412Snewtonstatic int
67783366Sjuliansi_ogetudata(fp, fd, ioc, td)
67843412Snewton	struct file		*fp;
67943412Snewton	int 			 fd;
68043412Snewton	struct svr4_strioctl	*ioc;
68183366Sjulian	struct thread		*td;
68243412Snewton{
68343412Snewton	int error;
68443412Snewton	struct svr4_si_oudata ud;
68543412Snewton	struct svr4_si_sockparms pa;
68643412Snewton
68743412Snewton	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
68843412Snewton		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
68943412Snewton			 sizeof(ud), ioc->len));
69043412Snewton		return EINVAL;
69143412Snewton	}
69243412Snewton
69343412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
69443412Snewton		return error;
69543412Snewton
69643412Snewton	getparm(fp, &pa);
69743412Snewton
69843412Snewton	switch (pa.family) {
69943412Snewton	case AF_INET:
70043412Snewton	    ud.tidusize = 16384;
70143412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
70243412Snewton	    if (pa.type == SVR4_SOCK_STREAM)
70343412Snewton		    ud.etsdusize = 1;
70443412Snewton	    else
70543412Snewton		    ud.etsdusize = 0;
70643412Snewton	    break;
70743412Snewton
70843412Snewton	case AF_LOCAL:
70943412Snewton	    ud.tidusize = 65536;
71043412Snewton	    ud.addrsize = 128;
71143412Snewton	    ud.etsdusize = 128;
71243412Snewton	    break;
71343412Snewton
71443412Snewton	default:
71543412Snewton	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
71643412Snewton		     pa.family));
71743412Snewton	    return ENOSYS;
71843412Snewton	}
71943412Snewton
72043412Snewton	/* I have no idea what these should be! */
72143412Snewton	ud.optsize = 128;
72243412Snewton	ud.tsdusize = 128;
72343412Snewton
72443412Snewton	ud.servtype = pa.type;
72543412Snewton
72643412Snewton	/* XXX: Fixme */
72743412Snewton	ud.so_state = 0;
72843412Snewton	ud.so_options = 0;
72943412Snewton	return copyout(&ud, ioc->buf, ioc->len);
73043412Snewton}
73143412Snewton
73243412Snewton
73343412Snewtonstatic int
73483366Sjuliansi_sockparams(fp, fd, ioc, td)
73543412Snewton	struct file		*fp;
73643412Snewton	int 			 fd;
73743412Snewton	struct svr4_strioctl	*ioc;
73883366Sjulian	struct thread		*td;
73943412Snewton{
74043412Snewton	struct svr4_si_sockparms pa;
74143412Snewton
74243412Snewton	getparm(fp, &pa);
74343412Snewton	return copyout(&pa, ioc->buf, sizeof(pa));
74443412Snewton}
74543412Snewton
74643412Snewton
74743412Snewtonstatic int
74883366Sjuliansi_listen(fp, fd, ioc, td)
74943412Snewton	struct file		*fp;
75043412Snewton	int 			 fd;
75143412Snewton	struct svr4_strioctl	*ioc;
75283366Sjulian	struct thread		*td;
75343412Snewton{
75443412Snewton	int error;
75543412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
75643412Snewton	struct svr4_strmcmd lst;
75743412Snewton	struct listen_args la;
75843412Snewton
75943412Snewton	if (st == NULL)
76043412Snewton		return EINVAL;
76143412Snewton
762121275Stjr	if (ioc->len < 0 || ioc->len > sizeof(lst))
763121275Stjr		return EINVAL;
764121275Stjr
76543412Snewton	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
76643412Snewton		return error;
76743412Snewton
76843412Snewton	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
76943412Snewton		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
77043412Snewton		return EINVAL;
77143412Snewton	}
77243412Snewton
77343412Snewton	/*
77443412Snewton	 * We are making assumptions again...
77543412Snewton	 */
776107849Salfred	la.s = fd;
77743412Snewton	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
778107849Salfred	la.backlog = 5;
77943412Snewton
78083366Sjulian	if ((error = listen(td, &la)) != 0) {
78143412Snewton		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
78243412Snewton		return error;
78343412Snewton	}
78443412Snewton
78543412Snewton	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
78643412Snewton	lst.cmd = SVR4_TI_BIND_REPLY;
78743412Snewton
78843412Snewton	switch (st->s_family) {
78943412Snewton	case AF_INET:
79043412Snewton		/* XXX: Fill the length here */
79143412Snewton		break;
79243412Snewton
79343412Snewton	case AF_LOCAL:
79443412Snewton		lst.len = 140;
79543412Snewton		lst.pad[28] = 0x00000000;	/* magic again */
79643412Snewton		lst.pad[29] = 0x00000800;	/* magic again */
79743412Snewton		lst.pad[30] = 0x80001400;	/* magic again */
79843412Snewton		break;
79943412Snewton
80043412Snewton	default:
80143412Snewton		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
80243412Snewton		    st->s_family));
80343412Snewton		return ENOSYS;
80443412Snewton	}
80543412Snewton
80643412Snewton
80743412Snewton	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
80843412Snewton		return error;
80943412Snewton
81043412Snewton	return 0;
81143412Snewton}
81243412Snewton
81343412Snewton
81443412Snewtonstatic int
81583366Sjuliansi_getudata(fp, fd, ioc, td)
81643412Snewton	struct file		*fp;
81743412Snewton	int 			 fd;
81843412Snewton	struct svr4_strioctl	*ioc;
81983366Sjulian	struct thread		*td;
82043412Snewton{
82143412Snewton	int error;
82243412Snewton	struct svr4_si_udata ud;
82343412Snewton
82443412Snewton	if (sizeof(ud) != ioc->len) {
82543412Snewton		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
82643412Snewton			 sizeof(ud), ioc->len));
82743412Snewton		return EINVAL;
82843412Snewton	}
82943412Snewton
83043412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
83143412Snewton		return error;
83243412Snewton
83343412Snewton	getparm(fp, &ud.sockparms);
83443412Snewton
83543412Snewton	switch (ud.sockparms.family) {
83643412Snewton	case AF_INET:
83743412Snewton	    DPRINTF(("getudata_inet\n"));
83843412Snewton	    ud.tidusize = 16384;
83943412Snewton	    ud.tsdusize = 16384;
84043412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
84143412Snewton	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
84243412Snewton		    ud.etsdusize = 1;
84343412Snewton	    else
84443412Snewton		    ud.etsdusize = 0;
84543412Snewton	    ud.optsize = 0;
84643412Snewton	    break;
84743412Snewton
84843412Snewton	case AF_LOCAL:
84943412Snewton	    DPRINTF(("getudata_local\n"));
85043412Snewton	    ud.tidusize = 65536;
85143412Snewton	    ud.tsdusize = 128;
85243412Snewton	    ud.addrsize = 128;
85343412Snewton	    ud.etsdusize = 128;
85443412Snewton	    ud.optsize = 128;
85543412Snewton	    break;
85643412Snewton
85743412Snewton	default:
85843412Snewton	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
85943412Snewton		     ud.sockparms.family));
86043412Snewton	    return ENOSYS;
86143412Snewton	}
86243412Snewton
86343412Snewton
86443412Snewton	ud.servtype = ud.sockparms.type;
86543412Snewton	DPRINTF(("ud.servtype = %d\n", ud.servtype));
86643412Snewton	/* XXX: Fixme */
86743412Snewton	ud.so_state = 0;
86843412Snewton	ud.so_options = 0;
86943412Snewton	return copyout(&ud, ioc->buf, sizeof(ud));
87043412Snewton}
87143412Snewton
87243412Snewton
87343412Snewtonstatic int
87483366Sjuliansi_shutdown(fp, fd, ioc, td)
87543412Snewton	struct file		*fp;
87643412Snewton	int 			 fd;
87743412Snewton	struct svr4_strioctl	*ioc;
87883366Sjulian	struct thread		*td;
87943412Snewton{
88043412Snewton	int error;
88143412Snewton	struct shutdown_args ap;
88243412Snewton
883107849Salfred	if (ioc->len != sizeof(ap.how)) {
88443412Snewton		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
885107849Salfred			 sizeof(ap.how), ioc->len));
88643412Snewton		return EINVAL;
88743412Snewton	}
88843412Snewton
889107849Salfred	if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0)
89043412Snewton		return error;
89143412Snewton
892107849Salfred	ap.s = fd;
89343412Snewton
89483366Sjulian	return shutdown(td, &ap);
89543412Snewton}
89643412Snewton
89743412Snewton
89843412Snewtonstatic int
89983366Sjuliansockmod(fp, fd, ioc, td)
90043412Snewton	struct file		*fp;
90143412Snewton	int			 fd;
90243412Snewton	struct svr4_strioctl	*ioc;
90383366Sjulian	struct thread		*td;
90443412Snewton{
90543412Snewton	switch (ioc->cmd) {
90643412Snewton	case SVR4_SI_OGETUDATA:
90743412Snewton		DPRINTF(("SI_OGETUDATA\n"));
90883366Sjulian		return si_ogetudata(fp, fd, ioc, td);
90943412Snewton
91043412Snewton	case SVR4_SI_SHUTDOWN:
91143412Snewton		DPRINTF(("SI_SHUTDOWN\n"));
91283366Sjulian		return si_shutdown(fp, fd, ioc, td);
91343412Snewton
91443412Snewton	case SVR4_SI_LISTEN:
91543412Snewton		DPRINTF(("SI_LISTEN\n"));
91683366Sjulian		return si_listen(fp, fd, ioc, td);
91743412Snewton
91843412Snewton	case SVR4_SI_SETMYNAME:
91943412Snewton		DPRINTF(("SI_SETMYNAME\n"));
92043412Snewton		return 0;
92143412Snewton
92243412Snewton	case SVR4_SI_SETPEERNAME:
92343412Snewton		DPRINTF(("SI_SETPEERNAME\n"));
92443412Snewton		return 0;
92543412Snewton
92643412Snewton	case SVR4_SI_GETINTRANSIT:
92743412Snewton		DPRINTF(("SI_GETINTRANSIT\n"));
92843412Snewton		return 0;
92943412Snewton
93043412Snewton	case SVR4_SI_TCL_LINK:
93143412Snewton		DPRINTF(("SI_TCL_LINK\n"));
93243412Snewton		return 0;
93343412Snewton
93443412Snewton	case SVR4_SI_TCL_UNLINK:
93543412Snewton		DPRINTF(("SI_TCL_UNLINK\n"));
93643412Snewton		return 0;
93743412Snewton
93843412Snewton	case SVR4_SI_SOCKPARAMS:
93943412Snewton		DPRINTF(("SI_SOCKPARAMS\n"));
94083366Sjulian		return si_sockparams(fp, fd, ioc, td);
94143412Snewton
94243412Snewton	case SVR4_SI_GETUDATA:
94343412Snewton		DPRINTF(("SI_GETUDATA\n"));
94483366Sjulian		return si_getudata(fp, fd, ioc, td);
94543412Snewton
94643412Snewton	default:
94743412Snewton		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
94843412Snewton		return 0;
94943412Snewton
95043412Snewton	}
95143412Snewton}
95243412Snewton
95343412Snewton
95443412Snewtonstatic int
95583366Sjulianti_getinfo(fp, fd, ioc, td)
95643412Snewton	struct file		*fp;
95743412Snewton	int 			 fd;
95843412Snewton	struct svr4_strioctl	*ioc;
95983366Sjulian	struct thread		*td;
96043412Snewton{
96143412Snewton	int error;
96243412Snewton	struct svr4_infocmd info;
96343412Snewton
96443412Snewton	memset(&info, 0, sizeof(info));
96543412Snewton
966121275Stjr	if (ioc->len < 0 || ioc->len > sizeof(info))
967121275Stjr		return EINVAL;
968121275Stjr
96943412Snewton	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
97043412Snewton		return error;
97143412Snewton
97243412Snewton	if (info.cmd != SVR4_TI_INFO_REQUEST)
97343412Snewton		return EINVAL;
97443412Snewton
97543412Snewton	info.cmd = SVR4_TI_INFO_REPLY;
97643412Snewton	info.tsdu = 0;
97743412Snewton	info.etsdu = 1;
97843412Snewton	info.cdata = -2;
97943412Snewton	info.ddata = -2;
98043412Snewton	info.addr = 16;
98143412Snewton	info.opt = -1;
98243412Snewton	info.tidu = 16384;
98343412Snewton	info.serv = 2;
98443412Snewton	info.current = 0;
98543412Snewton	info.provider = 2;
98643412Snewton
98743412Snewton	ioc->len = sizeof(info);
98843412Snewton	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
98943412Snewton		return error;
99043412Snewton
99143412Snewton	return 0;
99243412Snewton}
99343412Snewton
99443412Snewton
99543412Snewtonstatic int
99683366Sjulianti_bind(fp, fd, ioc, td)
99743412Snewton	struct file		*fp;
99843412Snewton	int 			 fd;
99943412Snewton	struct svr4_strioctl	*ioc;
100083366Sjulian	struct thread		*td;
100143412Snewton{
100243412Snewton	int error;
100343412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
100443412Snewton	struct sockaddr_in sain;
100543412Snewton	struct sockaddr_un saun;
100643412Snewton	caddr_t sg;
100743412Snewton	void *skp, *sup = NULL;
100843412Snewton	int sasize;
100943412Snewton	struct svr4_strmcmd bnd;
101043412Snewton	struct bind_args ba;
101143412Snewton
101243412Snewton	if (st == NULL) {
101343412Snewton		DPRINTF(("ti_bind: bad file descriptor\n"));
101443412Snewton		return EINVAL;
101543412Snewton	}
101643412Snewton
1017121275Stjr	if (ioc->len < 0 || ioc->len > sizeof(bnd))
1018121275Stjr		return EINVAL;
1019121275Stjr
102043412Snewton	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
102143412Snewton		return error;
102243412Snewton
102343412Snewton	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
102443412Snewton		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
102543412Snewton		return EINVAL;
102643412Snewton	}
102743412Snewton
102843412Snewton	switch (st->s_family) {
102943412Snewton	case AF_INET:
103043412Snewton		skp = &sain;
103143412Snewton		sasize = sizeof(sain);
103243412Snewton
103343412Snewton		if (bnd.offs == 0)
103443412Snewton			goto reply;
103543412Snewton
103643412Snewton		netaddr_to_sockaddr_in(&sain, &bnd);
103743412Snewton
103843412Snewton		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
103943412Snewton			 sain.sin_family, sain.sin_port,
104043412Snewton			 sain.sin_addr.s_addr));
104143412Snewton		break;
104243412Snewton
104343412Snewton	case AF_LOCAL:
104443412Snewton		skp = &saun;
104543412Snewton		sasize = sizeof(saun);
104643412Snewton		if (bnd.offs == 0)
104743412Snewton			goto reply;
104843412Snewton
104943412Snewton		netaddr_to_sockaddr_un(&saun, &bnd);
105043412Snewton
105143412Snewton		if (saun.sun_path[0] == '\0')
105243412Snewton			goto reply;
105343412Snewton
105443412Snewton		DPRINTF(("TI_BIND: fam %d, path %s\n",
105543412Snewton			 saun.sun_family, saun.sun_path));
105643412Snewton
105783366Sjulian		if ((error = clean_pipe(td, saun.sun_path)) != 0)
105843412Snewton			return error;
105943412Snewton
106043412Snewton		bnd.pad[28] = 0x00001000;	/* magic again */
106143412Snewton		break;
106243412Snewton
106343412Snewton	default:
106443412Snewton		DPRINTF(("TI_BIND: Unsupported address family %d\n",
106543412Snewton			 st->s_family));
106643412Snewton		return ENOSYS;
106743412Snewton	}
106843412Snewton
106943412Snewton	sg = stackgap_init();
107043412Snewton	sup = stackgap_alloc(&sg, sasize);
107143412Snewton
107243412Snewton	if ((error = copyout(skp, sup, sasize)) != 0)
107343412Snewton		return error;
107443412Snewton
1075107849Salfred	ba.s = fd;
107643412Snewton	DPRINTF(("TI_BIND: fileno %d\n", fd));
1077107849Salfred	ba.name = (void *) sup;
1078107849Salfred	ba.namelen = sasize;
107943412Snewton
108083366Sjulian	if ((error = bind(td, &ba)) != 0) {
108143412Snewton		DPRINTF(("TI_BIND: bind failed %d\n", error));
108243412Snewton		return error;
108343412Snewton	}
108443412Snewton
108543412Snewtonreply:
108643412Snewton	if (sup == NULL) {
108743412Snewton		memset(&bnd, 0, sizeof(bnd));
108843412Snewton		bnd.len = sasize + 4;
108943412Snewton		bnd.offs = 0x10;	/* XXX */
109043412Snewton	}
109143412Snewton
109243412Snewton	bnd.cmd = SVR4_TI_BIND_REPLY;
109343412Snewton
109443412Snewton	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
109543412Snewton		return error;
109643412Snewton
109743412Snewton	return 0;
109843412Snewton}
109943412Snewton
110043412Snewton
110143412Snewtonstatic int
110283366Sjuliantimod(fp, fd, ioc, td)
110343412Snewton	struct file		*fp;
110443412Snewton	int			 fd;
110543412Snewton	struct svr4_strioctl	*ioc;
110683366Sjulian	struct thread		*td;
110743412Snewton{
110843412Snewton	switch (ioc->cmd) {
110943412Snewton	case SVR4_TI_GETINFO:
111043412Snewton		DPRINTF(("TI_GETINFO\n"));
111183366Sjulian		return ti_getinfo(fp, fd, ioc, td);
111243412Snewton
111343412Snewton	case SVR4_TI_OPTMGMT:
111443412Snewton		DPRINTF(("TI_OPTMGMT\n"));
111543412Snewton		return 0;
111643412Snewton
111743412Snewton	case SVR4_TI_BIND:
111843412Snewton		DPRINTF(("TI_BIND\n"));
111983366Sjulian		return ti_bind(fp, fd, ioc, td);
112043412Snewton
112143412Snewton	case SVR4_TI_UNBIND:
112243412Snewton		DPRINTF(("TI_UNBIND\n"));
112343412Snewton		return 0;
112443412Snewton
112543412Snewton	default:
112643412Snewton		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
112743412Snewton		return 0;
112843412Snewton	}
112943412Snewton}
113043412Snewton
113143412Snewton
113243412Snewtonint
113383366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
113443412Snewton	struct file *fp;
113583366Sjulian	struct thread *td;
113643412Snewton	register_t *retval;
113743412Snewton	int fd;
113843412Snewton	u_long cmd;
113943412Snewton	caddr_t dat;
114043412Snewton{
114143412Snewton	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
114243412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
114343412Snewton	int error;
114443412Snewton	void *skp, *sup;
114543412Snewton	struct sockaddr_in sain;
114643412Snewton	struct sockaddr_un saun;
114743412Snewton	struct svr4_strmcmd sc;
1148121275Stjr	int sasize, oldsasize;
114943412Snewton	caddr_t sg;
115043412Snewton	int *lenp;
115143412Snewton
115243412Snewton	DPRINTF(("svr4_stream_ti_ioctl\n"));
115343412Snewton
115443412Snewton	if (st == NULL)
115543412Snewton		return EINVAL;
115643412Snewton
115743412Snewton	sc.offs = 0x10;
115843412Snewton
115943412Snewton	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
116043412Snewton		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
116143412Snewton		return error;
116243412Snewton	}
116343412Snewton
116443412Snewton	switch (st->s_family) {
116543412Snewton	case AF_INET:
116643412Snewton		skp = &sain;
116743412Snewton		sasize = sizeof(sain);
116843412Snewton		break;
116943412Snewton
117043412Snewton	case AF_LOCAL:
117143412Snewton		skp = &saun;
117243412Snewton		sasize = sizeof(saun);
117343412Snewton		break;
117443412Snewton
117543412Snewton	default:
117643412Snewton		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
117743412Snewton			 st->s_family));
117843412Snewton		return ENOSYS;
117943412Snewton	}
118043412Snewton
118143412Snewton	sg = stackgap_init();
118243412Snewton	sup = stackgap_alloc(&sg, sasize);
118343412Snewton	lenp = stackgap_alloc(&sg, sizeof(*lenp));
118443412Snewton
118543412Snewton	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
118643412Snewton		DPRINTF(("ti_ioctl: error copying out lenp\n"));
118743412Snewton		return error;
118843412Snewton	}
118943412Snewton
119043412Snewton	switch (cmd) {
119143412Snewton	case SVR4_TI_GETMYNAME:
119243412Snewton		DPRINTF(("TI_GETMYNAME\n"));
119343412Snewton		{
119443412Snewton			struct getsockname_args ap;
1195107849Salfred			ap.fdes = fd;
1196107849Salfred			ap.asa = sup;
1197107849Salfred			ap.alen = lenp;
119883366Sjulian			if ((error = getsockname(td, &ap)) != 0) {
119943412Snewton				DPRINTF(("ti_ioctl: getsockname error\n"));
120043412Snewton				return error;
120143412Snewton			}
120243412Snewton		}
120343412Snewton		break;
120443412Snewton
120543412Snewton	case SVR4_TI_GETPEERNAME:
120643412Snewton		DPRINTF(("TI_GETPEERNAME\n"));
120743412Snewton		{
120843412Snewton			struct getpeername_args ap;
1209107849Salfred			ap.fdes = fd;
1210107849Salfred			ap.asa = sup;
1211107849Salfred			ap.alen = lenp;
121283366Sjulian			if ((error = getpeername(td, &ap)) != 0) {
121343412Snewton				DPRINTF(("ti_ioctl: getpeername error\n"));
121443412Snewton				return error;
121543412Snewton			}
121643412Snewton		}
121743412Snewton		break;
121843412Snewton
121943412Snewton	case SVR4_TI_SETMYNAME:
122043412Snewton		DPRINTF(("TI_SETMYNAME\n"));
122143412Snewton		return 0;
122243412Snewton
122343412Snewton	case SVR4_TI_SETPEERNAME:
122443412Snewton		DPRINTF(("TI_SETPEERNAME\n"));
122543412Snewton		return 0;
122643412Snewton	default:
122743412Snewton		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
122843412Snewton		return ENOSYS;
122943412Snewton	}
123043412Snewton
123143412Snewton	if ((error = copyin(sup, skp, sasize)) != 0) {
123243412Snewton		DPRINTF(("ti_ioctl: error copying in socket data\n"));
123343412Snewton		return error;
123443412Snewton	}
123543412Snewton
1236121275Stjr	oldsasize = sasize;
1237121275Stjr
123843412Snewton	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
123943412Snewton		DPRINTF(("ti_ioctl: error copying in socket size\n"));
124043412Snewton		return error;
124143412Snewton	}
124243412Snewton
1243121275Stjr	if (sasize < 0 || sasize > oldsasize)
1244121275Stjr		return EINVAL;
1245121275Stjr
124643412Snewton	switch (st->s_family) {
124743412Snewton	case AF_INET:
124843412Snewton		sockaddr_to_netaddr_in(&sc, &sain);
124943412Snewton		skb.len = sasize;
125043412Snewton		break;
125143412Snewton
125243412Snewton	case AF_LOCAL:
125343412Snewton		sockaddr_to_netaddr_un(&sc, &saun);
125443412Snewton		skb.len = sasize + 4;
125543412Snewton		break;
125643412Snewton
125743412Snewton	default:
125843412Snewton		return ENOSYS;
125943412Snewton	}
126043412Snewton
126143412Snewton
126243412Snewton	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
126343412Snewton		DPRINTF(("ti_ioctl: error copying out socket data\n"));
126443412Snewton		return error;
126543412Snewton	}
126643412Snewton
126743412Snewton
126843412Snewton	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
126943412Snewton		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
127043412Snewton		return error;
127143412Snewton	}
127243412Snewton
127343412Snewton	return error;
127443412Snewton}
127543412Snewton
127643412Snewton
127743412Snewton
127843412Snewton
127943412Snewtonstatic int
128083366Sjuliani_nread(fp, td, retval, fd, cmd, dat)
128143412Snewton	struct file *fp;
128283366Sjulian	struct thread *td;
128343412Snewton	register_t *retval;
128443412Snewton	int fd;
128543412Snewton	u_long cmd;
128643412Snewton	caddr_t dat;
128743412Snewton{
128843412Snewton	int error;
128943412Snewton	int nread = 0;
129043412Snewton
129143412Snewton	/*
129243412Snewton	 * We are supposed to return the message length in nread, and the
129343412Snewton	 * number of messages in retval. We don't have the notion of number
129443412Snewton	 * of stream messages, so we just find out if we have any bytes waiting
129543412Snewton	 * for us, and if we do, then we assume that we have at least one
129643412Snewton	 * message waiting for us.
129743412Snewton	 */
1298102003Srwatson	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred,
1299102003Srwatson	    td)) != 0)
130043412Snewton		return error;
130143412Snewton
130243412Snewton	if (nread != 0)
130343412Snewton		*retval = 1;
130443412Snewton	else
130543412Snewton		*retval = 0;
130643412Snewton
130743412Snewton	return copyout(&nread, dat, sizeof(nread));
130843412Snewton}
130943412Snewton
131043412Snewtonstatic int
131183366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat)
131243412Snewton	struct file *fp;
131383366Sjulian	struct thread *td;
131443412Snewton	register_t *retval;
131543412Snewton	int fd;
131643412Snewton	u_long cmd;
131743412Snewton	caddr_t dat;
131843412Snewton{
131943412Snewton	/*
132043412Snewton	 * Major hack again here. We assume that we are using this to
132143412Snewton	 * implement accept(2). If that is the case, we have already
132243412Snewton	 * called accept, and we have stored the file descriptor in
132343412Snewton	 * afd. We find the file descriptor that the code wants to use
132443412Snewton	 * in fd insert, and then we dup2() our accepted file descriptor
132543412Snewton	 * to it.
132643412Snewton	 */
132743412Snewton	int error;
132843412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
132943412Snewton	struct svr4_strfdinsert fdi;
133043412Snewton	struct dup2_args d2p;
133143412Snewton	struct close_args clp;
133243412Snewton
133343412Snewton	if (st == NULL) {
133443412Snewton		DPRINTF(("fdinsert: bad file type\n"));
133543412Snewton		return EINVAL;
133643412Snewton	}
133743412Snewton
133843412Snewton	if (st->s_afd == -1) {
133943412Snewton		DPRINTF(("fdinsert: accept fd not found\n"));
134043412Snewton		return ENOENT;
134143412Snewton	}
134243412Snewton
134343412Snewton	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
134443412Snewton		DPRINTF(("fdinsert: copyin failed %d\n", error));
134543412Snewton		return error;
134643412Snewton	}
134743412Snewton
1348107849Salfred	d2p.from = st->s_afd;
1349107849Salfred	d2p.to = fdi.fd;
135043412Snewton
135183366Sjulian	if ((error = dup2(td, &d2p)) != 0) {
135243412Snewton		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
135343412Snewton		    st->s_afd, fdi.fd, error));
135443412Snewton		return error;
135543412Snewton	}
135643412Snewton
1357107849Salfred	clp.fd = st->s_afd;
135843412Snewton
135983366Sjulian	if ((error = close(td, &clp)) != 0) {
136043412Snewton		DPRINTF(("fdinsert: close(%d) failed %d\n",
136143412Snewton		    st->s_afd, error));
136243412Snewton		return error;
136343412Snewton	}
136443412Snewton
136543412Snewton	st->s_afd = -1;
136643412Snewton
136743412Snewton	*retval = 0;
136843412Snewton	return 0;
136943412Snewton}
137043412Snewton
137143412Snewton
137243412Snewtonstatic int
137383366Sjulian_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
137443412Snewton	struct file *fp;
137583366Sjulian	struct thread *td;
137643412Snewton	register_t *retval;
137743412Snewton	int fd;
137843412Snewton	u_long cmd;
137943412Snewton	caddr_t dat;
138043412Snewton{
138143412Snewton	struct mkfifo_args ap;
138243412Snewton
138343412Snewton	/*
138443412Snewton	 * This is a supposed to be a kernel and library only ioctl.
138543412Snewton	 * It gets called before ti_bind, when we have a unix
138643412Snewton	 * socket, to physically create the socket transport and
138743412Snewton	 * ``reserve'' it. I don't know how this get reserved inside
138843412Snewton	 * the kernel, but we are going to create it nevertheless.
138943412Snewton	 */
1390107849Salfred	ap.path = dat;
1391107849Salfred	ap.mode = S_IFIFO;
139243412Snewton
139383366Sjulian	return mkfifo(td, &ap);
139443412Snewton}
139543412Snewton
139643412Snewtonstatic int
139783366Sjulian_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
139843412Snewton	struct file *fp;
139983366Sjulian	struct thread *td;
140043412Snewton	register_t *retval;
140143412Snewton	int fd;
140243412Snewton	u_long cmd;
140343412Snewton	caddr_t dat;
140443412Snewton{
140543412Snewton	struct unlink_args ap;
140643412Snewton
140743412Snewton	/*
140843412Snewton	 * This is a supposed to be a kernel and library only ioctl.
140943412Snewton	 * I guess it is supposed to release the socket.
141043412Snewton	 */
1411107849Salfred	ap.path = dat;
141243412Snewton
141383366Sjulian	return unlink(td, &ap);
141443412Snewton}
141543412Snewton
141643412Snewtonstatic int
141783366Sjuliani_str(fp, td, retval, fd, cmd, dat)
141843412Snewton	struct file *fp;
141983366Sjulian	struct thread *td;
142043412Snewton	register_t *retval;
142143412Snewton	int fd;
142243412Snewton	u_long cmd;
142343412Snewton	caddr_t dat;
142443412Snewton{
142543412Snewton	int			 error;
142643412Snewton	struct svr4_strioctl	 ioc;
142743412Snewton
142843412Snewton	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
142943412Snewton		return error;
143043412Snewton
143143412Snewton#ifdef DEBUG_SVR4
143243412Snewton	if ((error = show_ioc(">", &ioc)) != 0)
143343412Snewton		return error;
143443412Snewton#endif /* DEBUG_SVR4 */
143543412Snewton
143643412Snewton	switch (ioc.cmd & 0xff00) {
143743412Snewton	case SVR4_SIMOD:
143883366Sjulian		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
143943412Snewton			return error;
144043412Snewton		break;
144143412Snewton
144243412Snewton	case SVR4_TIMOD:
144383366Sjulian		if ((error = timod(fp, fd, &ioc, td)) != 0)
144443412Snewton			return error;
144543412Snewton		break;
144643412Snewton
144743412Snewton	default:
144843412Snewton		DPRINTF(("Unimplemented module %c %ld\n",
144943412Snewton			 (char) (cmd >> 8), cmd & 0xff));
145043412Snewton		return 0;
145143412Snewton	}
145243412Snewton
145343412Snewton#ifdef DEBUG_SVR4
145443412Snewton	if ((error = show_ioc("<", &ioc)) != 0)
145543412Snewton		return error;
145643412Snewton#endif /* DEBUG_SVR4 */
145743412Snewton	return copyout(&ioc, dat, sizeof(ioc));
145843412Snewton}
145943412Snewton
146043412Snewtonstatic int
146183366Sjuliani_setsig(fp, td, retval, fd, cmd, dat)
146243412Snewton	struct file *fp;
146383366Sjulian	struct thread *td;
146443412Snewton	register_t *retval;
146543412Snewton	int fd;
146643412Snewton	u_long cmd;
146743412Snewton	caddr_t dat;
146843412Snewton{
146943412Snewton	/*
147043412Snewton	 * This is the best we can do for now; we cannot generate
147143412Snewton	 * signals only for specific events so the signal mask gets
147243412Snewton	 * ignored; we save it just to pass it to a possible I_GETSIG...
147343412Snewton	 *
147443412Snewton	 * We alse have to fix the O_ASYNC fcntl bit, so the
147543412Snewton	 * process will get SIGPOLLs.
147643412Snewton	 */
147743412Snewton	int error;
147843412Snewton	register_t oflags, flags;
147943412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
148043412Snewton
148143412Snewton	if (st == NULL) {
148243412Snewton		DPRINTF(("i_setsig: bad file descriptor\n"));
148343412Snewton		return EINVAL;
148443412Snewton	}
148543412Snewton	/* get old status flags */
1486134266Sjhb	error = kern_fcntl(td, fd, F_GETFL, 0);
1487134266Sjhb	if (error)
1488134266Sjhb		return (error);
148943412Snewton
149083366Sjulian	oflags = td->td_retval[0];
149143412Snewton
149243412Snewton	/* update the flags */
149343412Snewton	if (dat != NULL) {
149443412Snewton		int mask;
149543412Snewton
149643412Snewton		flags = oflags | O_ASYNC;
149743412Snewton		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
149843412Snewton			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
149943412Snewton			  return error;
150043412Snewton		}
150143412Snewton		if (mask & SVR4_S_ALLMASK) {
150243412Snewton			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
150343412Snewton			  return EINVAL;
150443412Snewton		}
150543412Snewton		st->s_eventmask = mask;
150643412Snewton	}
150743412Snewton	else {
150843412Snewton		flags = oflags & ~O_ASYNC;
150943412Snewton		st->s_eventmask = 0;
151043412Snewton	}
151143412Snewton
151243412Snewton	/* set the new flags, if changed */
151343412Snewton	if (flags != oflags) {
1514134266Sjhb		error = kern_fcntl(td, fd, F_SETFL, flags);
1515134266Sjhb		if (error)
1516134266Sjhb			return (error);
151783366Sjulian		flags = td->td_retval[0];
151843412Snewton	}
151943412Snewton
152043412Snewton	/* set up SIGIO receiver if needed */
1521134266Sjhb	if (dat != NULL)
1522134266Sjhb		return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid));
152343412Snewton	return 0;
152443412Snewton}
152543412Snewton
152643412Snewtonstatic int
152783366Sjuliani_getsig(fp, td, retval, fd, cmd, dat)
152843412Snewton	struct file *fp;
152983366Sjulian	struct thread *td;
153043412Snewton	register_t *retval;
153143412Snewton	int fd;
153243412Snewton	u_long cmd;
153343412Snewton	caddr_t dat;
153443412Snewton{
153543412Snewton	int error;
153643412Snewton
153743412Snewton	if (dat != NULL) {
153843412Snewton		struct svr4_strm *st = svr4_stream_get(fp);
153943412Snewton
154043412Snewton		if (st == NULL) {
154143412Snewton			DPRINTF(("i_getsig: bad file descriptor\n"));
154243412Snewton			return EINVAL;
154343412Snewton		}
154443412Snewton		if ((error = copyout(&st->s_eventmask, dat,
154543412Snewton				     sizeof(st->s_eventmask))) != 0) {
154643412Snewton			DPRINTF(("i_getsig: bad eventmask pointer\n"));
154743412Snewton			return error;
154843412Snewton		}
154943412Snewton	}
155043412Snewton	return 0;
155143412Snewton}
155243412Snewton
155343412Snewtonint
155483366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
155543412Snewton	struct file *fp;
155683366Sjulian	struct thread *td;
155743412Snewton	register_t *retval;
155843412Snewton	int fd;
155943412Snewton	u_long cmd;
156043412Snewton	caddr_t dat;
156143412Snewton{
156243412Snewton	*retval = 0;
156343412Snewton
156443412Snewton	/*
156543412Snewton	 * All the following stuff assumes "sockmod" is pushed...
156643412Snewton	 */
156743412Snewton	switch (cmd) {
156843412Snewton	case SVR4_I_NREAD:
156943412Snewton		DPRINTF(("I_NREAD\n"));
157083366Sjulian		return i_nread(fp, td, retval, fd, cmd, dat);
157143412Snewton
157243412Snewton	case SVR4_I_PUSH:
157380114Sassar		DPRINTF(("I_PUSH %p\n", dat));
157443412Snewton#if defined(DEBUG_SVR4)
157580114Sassar		show_strbuf((struct svr4_strbuf *)dat);
157643412Snewton#endif
157743412Snewton		return 0;
157843412Snewton
157943412Snewton	case SVR4_I_POP:
158043412Snewton		DPRINTF(("I_POP\n"));
158143412Snewton		return 0;
158243412Snewton
158343412Snewton	case SVR4_I_LOOK:
158443412Snewton		DPRINTF(("I_LOOK\n"));
158543412Snewton		return 0;
158643412Snewton
158743412Snewton	case SVR4_I_FLUSH:
158843412Snewton		DPRINTF(("I_FLUSH\n"));
158943412Snewton		return 0;
159043412Snewton
159143412Snewton	case SVR4_I_SRDOPT:
159243412Snewton		DPRINTF(("I_SRDOPT\n"));
159343412Snewton		return 0;
159443412Snewton
159543412Snewton	case SVR4_I_GRDOPT:
159643412Snewton		DPRINTF(("I_GRDOPT\n"));
159743412Snewton		return 0;
159843412Snewton
159943412Snewton	case SVR4_I_STR:
160043412Snewton		DPRINTF(("I_STR\n"));
160183366Sjulian		return i_str(fp, td, retval, fd, cmd, dat);
160243412Snewton
160343412Snewton	case SVR4_I_SETSIG:
160443412Snewton		DPRINTF(("I_SETSIG\n"));
160583366Sjulian		return i_setsig(fp, td, retval, fd, cmd, dat);
160643412Snewton
160743412Snewton	case SVR4_I_GETSIG:
160843412Snewton	        DPRINTF(("I_GETSIG\n"));
160983366Sjulian		return i_getsig(fp, td, retval, fd, cmd, dat);
161043412Snewton
161143412Snewton	case SVR4_I_FIND:
161243412Snewton		DPRINTF(("I_FIND\n"));
161343412Snewton		/*
161443412Snewton		 * Here we are not pushing modules really, we just
161543412Snewton		 * pretend all are present
161643412Snewton		 */
161743412Snewton		*retval = 0;
161843412Snewton		return 0;
161943412Snewton
162043412Snewton	case SVR4_I_LINK:
162143412Snewton		DPRINTF(("I_LINK\n"));
162243412Snewton		return 0;
162343412Snewton
162443412Snewton	case SVR4_I_UNLINK:
162543412Snewton		DPRINTF(("I_UNLINK\n"));
162643412Snewton		return 0;
162743412Snewton
162843412Snewton	case SVR4_I_ERECVFD:
162943412Snewton		DPRINTF(("I_ERECVFD\n"));
163043412Snewton		return 0;
163143412Snewton
163243412Snewton	case SVR4_I_PEEK:
163343412Snewton		DPRINTF(("I_PEEK\n"));
163443412Snewton		return 0;
163543412Snewton
163643412Snewton	case SVR4_I_FDINSERT:
163743412Snewton		DPRINTF(("I_FDINSERT\n"));
163883366Sjulian		return i_fdinsert(fp, td, retval, fd, cmd, dat);
163943412Snewton
164043412Snewton	case SVR4_I_SENDFD:
164143412Snewton		DPRINTF(("I_SENDFD\n"));
164243412Snewton		return 0;
164343412Snewton
164443412Snewton	case SVR4_I_RECVFD:
164543412Snewton		DPRINTF(("I_RECVFD\n"));
164643412Snewton		return 0;
164743412Snewton
164843412Snewton	case SVR4_I_SWROPT:
164943412Snewton		DPRINTF(("I_SWROPT\n"));
165043412Snewton		return 0;
165143412Snewton
165243412Snewton	case SVR4_I_GWROPT:
165343412Snewton		DPRINTF(("I_GWROPT\n"));
165443412Snewton		return 0;
165543412Snewton
165643412Snewton	case SVR4_I_LIST:
165743412Snewton		DPRINTF(("I_LIST\n"));
165843412Snewton		return 0;
165943412Snewton
166043412Snewton	case SVR4_I_PLINK:
166143412Snewton		DPRINTF(("I_PLINK\n"));
166243412Snewton		return 0;
166343412Snewton
166443412Snewton	case SVR4_I_PUNLINK:
166543412Snewton		DPRINTF(("I_PUNLINK\n"));
166643412Snewton		return 0;
166743412Snewton
166843412Snewton	case SVR4_I_SETEV:
166943412Snewton		DPRINTF(("I_SETEV\n"));
167043412Snewton		return 0;
167143412Snewton
167243412Snewton	case SVR4_I_GETEV:
167343412Snewton		DPRINTF(("I_GETEV\n"));
167443412Snewton		return 0;
167543412Snewton
167643412Snewton	case SVR4_I_STREV:
167743412Snewton		DPRINTF(("I_STREV\n"));
167843412Snewton		return 0;
167943412Snewton
168043412Snewton	case SVR4_I_UNSTREV:
168143412Snewton		DPRINTF(("I_UNSTREV\n"));
168243412Snewton		return 0;
168343412Snewton
168443412Snewton	case SVR4_I_FLUSHBAND:
168543412Snewton		DPRINTF(("I_FLUSHBAND\n"));
168643412Snewton		return 0;
168743412Snewton
168843412Snewton	case SVR4_I_CKBAND:
168943412Snewton		DPRINTF(("I_CKBAND\n"));
169043412Snewton		return 0;
169143412Snewton
169243412Snewton	case SVR4_I_GETBAND:
169343412Snewton		DPRINTF(("I_GETBANK\n"));
169443412Snewton		return 0;
169543412Snewton
169643412Snewton	case SVR4_I_ATMARK:
169743412Snewton		DPRINTF(("I_ATMARK\n"));
169843412Snewton		return 0;
169943412Snewton
170043412Snewton	case SVR4_I_SETCLTIME:
170143412Snewton		DPRINTF(("I_SETCLTIME\n"));
170243412Snewton		return 0;
170343412Snewton
170443412Snewton	case SVR4_I_GETCLTIME:
170543412Snewton		DPRINTF(("I_GETCLTIME\n"));
170643412Snewton		return 0;
170743412Snewton
170843412Snewton	case SVR4_I_CANPUT:
170943412Snewton		DPRINTF(("I_CANPUT\n"));
171043412Snewton		return 0;
171143412Snewton
171243412Snewton	case SVR4__I_BIND_RSVD:
171343412Snewton		DPRINTF(("_I_BIND_RSVD\n"));
171483366Sjulian		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
171543412Snewton
171643412Snewton	case SVR4__I_RELE_RSVD:
171743412Snewton		DPRINTF(("_I_RELE_RSVD\n"));
171883366Sjulian		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
171943412Snewton
172043412Snewton	default:
172143412Snewton		DPRINTF(("unimpl cmd = %lx\n", cmd));
172243412Snewton		break;
172343412Snewton	}
172443412Snewton
172543412Snewton	return 0;
172643412Snewton}
172743412Snewton
172843412Snewton
172943412Snewton
173043412Snewtonint
173183366Sjuliansvr4_sys_putmsg(td, uap)
173283366Sjulian	register struct thread *td;
173343412Snewton	struct svr4_sys_putmsg_args *uap;
173443412Snewton{
173589306Salfred	struct file     *fp;
173689306Salfred	int error;
173789306Salfred
173889319Salfred	if ((error = fget(td, uap->fd, &fp)) != 0) {
173989306Salfred#ifdef DEBUG_SVR4
174089306Salfred	        uprintf("putmsg: bad fp\n");
174189306Salfred#endif
174289306Salfred		return EBADF;
174389306Salfred	}
174489306Salfred	error = svr4_do_putmsg(td, uap, fp);
174589306Salfred	fdrop(fp, td);
174689306Salfred	return (error);
174789306Salfred}
174889306Salfred
174989306Salfredstatic int
175089306Salfredsvr4_do_putmsg(td, uap, fp)
175189306Salfred	struct thread *td;
175289306Salfred	struct svr4_sys_putmsg_args *uap;
175343412Snewton	struct file	*fp;
175489306Salfred{
175543412Snewton	struct svr4_strbuf dat, ctl;
175643412Snewton	struct svr4_strmcmd sc;
175743412Snewton	struct sockaddr_in sain;
175843412Snewton	struct sockaddr_un saun;
175943412Snewton	void *skp, *sup;
176043412Snewton	int sasize, *retval;
176143412Snewton	struct svr4_strm *st;
176243412Snewton	int error;
176343412Snewton	caddr_t sg;
176443412Snewton
176583366Sjulian	retval = td->td_retval;
176654493Snewton
176743412Snewton#ifdef DEBUG_SVR4
1768107849Salfred	show_msg(">putmsg", uap->fd, uap->ctl,
1769107849Salfred		 uap->dat, uap->flags);
177043412Snewton#endif /* DEBUG_SVR4 */
177143412Snewton
177289306Salfred	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
177343412Snewton
1774107849Salfred	if (uap->ctl != NULL) {
1775107849Salfred	  if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) {
177643412Snewton#ifdef DEBUG_SVR4
177743412Snewton	    uprintf("putmsg: copyin(): %d\n", error);
177843412Snewton#endif
177943412Snewton	    return error;
178043412Snewton	  }
178143412Snewton	}
178243412Snewton	else
178343412Snewton		ctl.len = -1;
178443412Snewton
1785107849Salfred	if (uap->dat != NULL) {
1786107849Salfred	  if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) {
178743412Snewton#ifdef DEBUG_SVR4
178843412Snewton	    uprintf("putmsg: copyin(): %d (2)\n", error);
178943412Snewton#endif
179043412Snewton	    return error;
179143412Snewton	  }
179243412Snewton	}
179343412Snewton	else
179443412Snewton		dat.len = -1;
179543412Snewton
179643412Snewton	/*
179743412Snewton	 * Only for sockets for now.
179843412Snewton	 */
179943412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
180043412Snewton		DPRINTF(("putmsg: bad file type\n"));
180143412Snewton		return EINVAL;
180243412Snewton	}
180343412Snewton
1804121275Stjr	if (ctl.len < 0 || ctl.len > sizeof(sc)) {
180543412Snewton		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
180643412Snewton			 sizeof(struct svr4_strmcmd)));
180743412Snewton		return EINVAL;
180843412Snewton	}
180943412Snewton
181043412Snewton	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
181143412Snewton		return error;
181243412Snewton
181343412Snewton	switch (st->s_family) {
181443412Snewton	case AF_INET:
181543412Snewton	        if (sc.len != sizeof(sain)) {
181643412Snewton		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
181743412Snewton			        struct write_args wa;
181843412Snewton
181943412Snewton				/* Solaris seems to use sc.cmd = 3 to
182043412Snewton				 * send "expedited" data.  telnet uses
182143412Snewton				 * this for options processing, sending EOF,
182243412Snewton				 * etc.  I'm sure other things use it too.
182343412Snewton				 * I don't have any documentation
182443412Snewton				 * on it, so I'm making a guess that this
182543412Snewton				 * is how it works. newton@atdot.dotat.org XXX
182643412Snewton				 */
182751844Speter				DPRINTF(("sending expedited data ??\n"));
1828107849Salfred				wa.fd = uap->fd;
1829107849Salfred				wa.buf = dat.buf;
1830107849Salfred				wa.nbyte = dat.len;
183183366Sjulian				return write(td, &wa);
183243412Snewton			}
183343412Snewton	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
183443412Snewton	                return EINVAL;
183543412Snewton	        }
183643412Snewton	        netaddr_to_sockaddr_in(&sain, &sc);
183743412Snewton	        skp = &sain;
183843412Snewton	        sasize = sizeof(sain);
183943412Snewton	        error = sain.sin_family != st->s_family;
184043412Snewton		break;
184143412Snewton
184243412Snewton	case AF_LOCAL:
184343412Snewton		if (ctl.len == 8) {
184443412Snewton			/* We are doing an accept; succeed */
184543412Snewton			DPRINTF(("putmsg: Do nothing\n"));
184643412Snewton			*retval = 0;
184743412Snewton			return 0;
184843412Snewton		}
184943412Snewton		else {
185043412Snewton			/* Maybe we've been given a device/inode pair */
1851130640Sphk			dev_t *dev = SVR4_ADDROF(&sc);
185243412Snewton			ino_t *ino = (ino_t *) &dev[1];
185383366Sjulian			skp = svr4_find_socket(td, fp, *dev, *ino);
185443412Snewton			if (skp == NULL) {
185543412Snewton				skp = &saun;
185643412Snewton				/* I guess we have it by name */
185743412Snewton				netaddr_to_sockaddr_un(skp, &sc);
185843412Snewton			}
185943412Snewton			sasize = sizeof(saun);
186043412Snewton		}
186143412Snewton		break;
186243412Snewton
186343412Snewton	default:
186443412Snewton		DPRINTF(("putmsg: Unsupported address family %d\n",
186543412Snewton			 st->s_family));
186643412Snewton		return ENOSYS;
186743412Snewton	}
186843412Snewton
186943412Snewton	sg = stackgap_init();
187043412Snewton	sup = stackgap_alloc(&sg, sasize);
187143412Snewton
187243412Snewton	if ((error = copyout(skp, sup, sasize)) != 0)
187343412Snewton		return error;
187443412Snewton
187543412Snewton	switch (st->s_cmd = sc.cmd) {
187643412Snewton	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
187743412Snewton		{
187843412Snewton			struct connect_args co;
187943412Snewton
1880107849Salfred			co.s = uap->fd;
1881107849Salfred			co.name = (void *) sup;
1882107849Salfred			co.namelen = (int) sasize;
188343412Snewton
188483366Sjulian			return connect(td, &co);
188543412Snewton		}
188643412Snewton
188743412Snewton	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
188843412Snewton		{
188943412Snewton			struct msghdr msg;
189043412Snewton			struct iovec aiov;
189143412Snewton
189243412Snewton			msg.msg_name = (caddr_t) sup;
189343412Snewton			msg.msg_namelen = sasize;
189443412Snewton			msg.msg_iov = &aiov;
189543412Snewton			msg.msg_iovlen = 1;
189643412Snewton			msg.msg_control = 0;
189743412Snewton			msg.msg_flags = 0;
189843412Snewton			aiov.iov_base = dat.buf;
189943412Snewton			aiov.iov_len = dat.len;
190043412Snewton#if 0
190143412Snewton			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
190283366Sjulian					      uio, 0, 0, 0, uio->uio_td);
190343412Snewton#endif
1904107849Salfred			error = svr4_sendit(td, uap->fd, &msg,
1905107849Salfred				       uap->flags);
190643412Snewton			DPRINTF(("sendto_request error: %d\n", error));
190743412Snewton			*retval = 0;
190843412Snewton			return error;
190943412Snewton		}
191043412Snewton
191143412Snewton	default:
191243412Snewton		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
191343412Snewton		return ENOSYS;
191443412Snewton	}
191543412Snewton}
191643412Snewton
191743412Snewtonint
191889308Salfredsvr4_sys_getmsg(td, uap)
191989308Salfred	struct thread *td;
192089306Salfred	struct svr4_sys_getmsg_args *uap;
192189306Salfred{
192289306Salfred	struct file     *fp;
192389306Salfred	int error;
192489306Salfred
192589319Salfred	if ((error = fget(td, uap->fd, &fp)) != 0) {
192689306Salfred#ifdef DEBUG_SVR4
192789306Salfred	        uprintf("getmsg: bad fp\n");
192889306Salfred#endif
192989306Salfred		return EBADF;
193089306Salfred	}
193189308Salfred	error = svr4_do_getmsg(td, uap, fp);
193289306Salfred	fdrop(fp, td);
193389306Salfred	return (error);
193489306Salfred}
193589306Salfred
193689306Salfredint
193789536Salfredsvr4_do_getmsg(td, uap, fp)
193883366Sjulian	register struct thread *td;
193943412Snewton	struct svr4_sys_getmsg_args *uap;
194089306Salfred	struct file *fp;
194143412Snewton{
194243412Snewton	struct getpeername_args ga;
194343412Snewton	struct accept_args aa;
194443412Snewton	struct svr4_strbuf dat, ctl;
194543412Snewton	struct svr4_strmcmd sc;
194643412Snewton	int error, *retval;
194743412Snewton	struct msghdr msg;
194843412Snewton	struct iovec aiov;
194943412Snewton	struct sockaddr_in sain;
195043412Snewton	struct sockaddr_un saun;
195143412Snewton	void *skp, *sup;
195243412Snewton	int sasize;
195343412Snewton	struct svr4_strm *st;
195443412Snewton	int *flen;
195543412Snewton	int fl;
195643412Snewton	caddr_t sg;
195743412Snewton
195883366Sjulian	retval = td->td_retval;
195954493Snewton
196089306Salfred	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
196143412Snewton
196243412Snewton	memset(&sc, 0, sizeof(sc));
196343412Snewton
196443412Snewton#ifdef DEBUG_SVR4
1965107849Salfred	show_msg(">getmsg", uap->fd, uap->ctl,
1966107849Salfred		 uap->dat, 0);
196743412Snewton#endif /* DEBUG_SVR4 */
196843412Snewton
1969107849Salfred	if (uap->ctl != NULL) {
1970107849Salfred		if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
197143412Snewton			return error;
1972121275Stjr		if (ctl.len < 0)
1973121275Stjr			return EINVAL;
197443412Snewton	}
197543412Snewton	else {
197643412Snewton		ctl.len = -1;
197743412Snewton		ctl.maxlen = 0;
197843412Snewton	}
197943412Snewton
1980107849Salfred	if (uap->dat != NULL) {
1981107849Salfred	    	if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0)
198243412Snewton			return error;
198343412Snewton	}
198443412Snewton	else {
198543412Snewton		dat.len = -1;
198643412Snewton		dat.maxlen = 0;
198743412Snewton	}
198843412Snewton
198943412Snewton	/*
199043412Snewton	 * Only for sockets for now.
199143412Snewton	 */
199243412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
199343412Snewton		DPRINTF(("getmsg: bad file type\n"));
199443412Snewton		return EINVAL;
199543412Snewton	}
199643412Snewton
199743412Snewton	if (ctl.maxlen == -1 || dat.maxlen == -1) {
199843412Snewton		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
199943412Snewton		return ENOSYS;
200043412Snewton	}
200143412Snewton
200243412Snewton	switch (st->s_family) {
200343412Snewton	case AF_INET:
200443412Snewton		skp = &sain;
200543412Snewton		sasize = sizeof(sain);
200643412Snewton		break;
200743412Snewton
200843412Snewton	case AF_LOCAL:
200943412Snewton		skp = &saun;
201043412Snewton		sasize = sizeof(saun);
201143412Snewton		break;
201243412Snewton
201343412Snewton	default:
201443412Snewton		DPRINTF(("getmsg: Unsupported address family %d\n",
201543412Snewton			 st->s_family));
201643412Snewton		return ENOSYS;
201743412Snewton	}
201843412Snewton
201943412Snewton	sg = stackgap_init();
202043412Snewton	sup = stackgap_alloc(&sg, sasize);
202143412Snewton	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
202243412Snewton
202343412Snewton	fl = sasize;
202443412Snewton	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
202543412Snewton		return error;
202643412Snewton
202743412Snewton	switch (st->s_cmd) {
202843412Snewton	case SVR4_TI_CONNECT_REQUEST:
202943412Snewton		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
203043412Snewton		/*
203143412Snewton		 * We do the connect in one step, so the putmsg should
203243412Snewton		 * have gotten the error.
203343412Snewton		 */
203443412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
203543412Snewton		sc.len = 0;
203643412Snewton
203743412Snewton		ctl.len = 8;
203843412Snewton		dat.len = -1;
203943412Snewton		fl = 1;
204043412Snewton		st->s_cmd = sc.cmd;
204143412Snewton		break;
204243412Snewton
204343412Snewton	case SVR4_TI_OK_REPLY:
204443412Snewton		DPRINTF(("getmsg: TI_OK_REPLY\n"));
204543412Snewton		/*
204643412Snewton		 * We are immediately after a connect reply, so we send
204743412Snewton		 * a connect verification.
204843412Snewton		 */
204943412Snewton
2050107849Salfred		ga.fdes = uap->fd;
2051107849Salfred		ga.asa = (void *) sup;
2052107849Salfred		ga.alen = flen;
205343412Snewton
205483366Sjulian		if ((error = getpeername(td, &ga)) != 0) {
205543412Snewton			DPRINTF(("getmsg: getpeername failed %d\n", error));
205643412Snewton			return error;
205743412Snewton		}
205843412Snewton
205943412Snewton		if ((error = copyin(sup, skp, sasize)) != 0)
206043412Snewton			return error;
206143412Snewton
206243412Snewton		sc.cmd = SVR4_TI_CONNECT_REPLY;
206343412Snewton		sc.pad[0] = 0x4;
206443412Snewton		sc.offs = 0x18;
206543412Snewton		sc.pad[1] = 0x14;
206643412Snewton		sc.pad[2] = 0x04000402;
206743412Snewton
206843412Snewton		switch (st->s_family) {
206943412Snewton		case AF_INET:
207043412Snewton			sc.len = sasize;
207143412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
207243412Snewton			break;
207343412Snewton
207443412Snewton		case AF_LOCAL:
207543412Snewton			sc.len = sasize + 4;
207643412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
207743412Snewton			break;
207843412Snewton
207943412Snewton		default:
208043412Snewton			return ENOSYS;
208143412Snewton		}
208243412Snewton
208343412Snewton		ctl.len = 40;
208443412Snewton		dat.len = -1;
208543412Snewton		fl = 0;
208643412Snewton		st->s_cmd = sc.cmd;
208743412Snewton		break;
208843412Snewton
208943412Snewton	case SVR4_TI__ACCEPT_OK:
209043412Snewton		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
209143412Snewton		/*
209243412Snewton		 * We do the connect in one step, so the putmsg should
209343412Snewton		 * have gotten the error.
209443412Snewton		 */
209543412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
209643412Snewton		sc.len = 1;
209743412Snewton
209843412Snewton		ctl.len = 8;
209943412Snewton		dat.len = -1;
210043412Snewton		fl = 1;
210143412Snewton		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
210243412Snewton		break;
210343412Snewton
210443412Snewton	case SVR4_TI__ACCEPT_WAIT:
210543412Snewton		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
210643412Snewton		/*
210743412Snewton		 * We are after a listen, so we try to accept...
210843412Snewton		 */
2109107849Salfred		aa.s = uap->fd;
2110107849Salfred		aa.name = (void *) sup;
2111107849Salfred		aa.anamelen = flen;
211243412Snewton
211383366Sjulian		if ((error = accept(td, &aa)) != 0) {
211443412Snewton			DPRINTF(("getmsg: accept failed %d\n", error));
211543412Snewton			return error;
211643412Snewton		}
211743412Snewton
211843412Snewton		st->s_afd = *retval;
211943412Snewton
212043412Snewton		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
212143412Snewton
212243412Snewton		if ((error = copyin(sup, skp, sasize)) != 0)
212343412Snewton			return error;
212443412Snewton
212543412Snewton		sc.cmd = SVR4_TI_ACCEPT_REPLY;
212643412Snewton		sc.offs = 0x18;
212743412Snewton		sc.pad[0] = 0x0;
212843412Snewton
212943412Snewton		switch (st->s_family) {
213043412Snewton		case AF_INET:
213143412Snewton			sc.pad[1] = 0x28;
213243412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
213343412Snewton			ctl.len = 40;
213443412Snewton			sc.len = sasize;
213543412Snewton			break;
213643412Snewton
213743412Snewton		case AF_LOCAL:
213843412Snewton			sc.pad[1] = 0x00010000;
213943412Snewton			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
214043412Snewton			sc.pad[3] = 0x00010000;
214143412Snewton			ctl.len = 134;
214243412Snewton			sc.len = sasize + 4;
214343412Snewton			break;
214443412Snewton
214543412Snewton		default:
214643412Snewton			return ENOSYS;
214743412Snewton		}
214843412Snewton
214943412Snewton		dat.len = -1;
215043412Snewton		fl = 0;
215143412Snewton		st->s_cmd = SVR4_TI__ACCEPT_OK;
215243412Snewton		break;
215343412Snewton
215443412Snewton	case SVR4_TI_SENDTO_REQUEST:
215543412Snewton		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
215643412Snewton		if (ctl.maxlen > 36 && ctl.len < 36)
215743412Snewton		    ctl.len = 36;
215843412Snewton
2159121275Stjr		if (ctl.len > sizeof(sc))
2160121275Stjr			ctl.len = sizeof(sc);
2161121275Stjr
216243412Snewton		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
216343412Snewton			return error;
216443412Snewton
216543412Snewton		switch (st->s_family) {
216643412Snewton		case AF_INET:
216743412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
216843412Snewton			break;
216943412Snewton
217043412Snewton		case AF_LOCAL:
217143412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
217243412Snewton			break;
217343412Snewton
217443412Snewton		default:
217543412Snewton			return ENOSYS;
217643412Snewton		}
217743412Snewton
217843412Snewton		msg.msg_name = (caddr_t) sup;
217943412Snewton		msg.msg_namelen = sasize;
218043412Snewton		msg.msg_iov = &aiov;
218143412Snewton		msg.msg_iovlen = 1;
218243412Snewton		msg.msg_control = 0;
218343412Snewton		aiov.iov_base = dat.buf;
218443412Snewton		aiov.iov_len = dat.maxlen;
218543412Snewton		msg.msg_flags = 0;
218643412Snewton
2187107849Salfred		error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen);
218843412Snewton
218943412Snewton		if (error) {
219043412Snewton			DPRINTF(("getmsg: recvit failed %d\n", error));
219143412Snewton			return error;
219243412Snewton		}
219343412Snewton
219443412Snewton		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
219543412Snewton			return error;
219643412Snewton
219743412Snewton		sc.cmd = SVR4_TI_RECVFROM_IND;
219843412Snewton
219943412Snewton		switch (st->s_family) {
220043412Snewton		case AF_INET:
220143412Snewton			sc.len = sasize;
220243412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
220343412Snewton			break;
220443412Snewton
220543412Snewton		case AF_LOCAL:
220643412Snewton			sc.len = sasize + 4;
220743412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
220843412Snewton			break;
220943412Snewton
221043412Snewton		default:
221143412Snewton			return ENOSYS;
221243412Snewton		}
221343412Snewton
221443412Snewton		dat.len = *retval;
221543412Snewton		fl = 0;
221643412Snewton		st->s_cmd = sc.cmd;
221743412Snewton		break;
221843412Snewton
221943412Snewton	default:
222043412Snewton		st->s_cmd = sc.cmd;
222143412Snewton		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
222243412Snewton		        struct read_args ra;
222343412Snewton
222472082Sasmodai			/* More weirdness:  Again, I can't find documentation
222543412Snewton			 * to back this up, but when a process does a generic
222643412Snewton			 * "getmsg()" call it seems that the command field is
222743412Snewton			 * zero and the length of the data area is zero.  I
222843412Snewton			 * think processes expect getmsg() to fill in dat.len
222943412Snewton			 * after reading at most dat.maxlen octets from the
223043412Snewton			 * stream.  Since we're using sockets I can let
223143412Snewton			 * read() look after it and frob return values
223243412Snewton			 * appropriately (or inappropriately :-)
223343412Snewton			 *   -- newton@atdot.dotat.org        XXX
223443412Snewton			 */
2235107849Salfred			ra.fd = uap->fd;
2236107849Salfred			ra.buf = dat.buf;
2237107849Salfred			ra.nbyte = dat.maxlen;
223883366Sjulian			if ((error = read(td, &ra)) != 0) {
223943412Snewton			        return error;
224043412Snewton			}
224143412Snewton			dat.len = *retval;
224243412Snewton			*retval = 0;
224343412Snewton			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
224443412Snewton			break;
224543412Snewton		}
224643412Snewton		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
224743412Snewton		return EINVAL;
224843412Snewton	}
224943412Snewton
2250107849Salfred	if (uap->ctl) {
225143412Snewton		if (ctl.len != -1)
225243412Snewton			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
225343412Snewton				return error;
225443412Snewton
2255107849Salfred		if ((error = copyout(&ctl, uap->ctl, sizeof(ctl))) != 0)
225643412Snewton			return error;
225743412Snewton	}
225843412Snewton
2259107849Salfred	if (uap->dat) {
2260107849Salfred		if ((error = copyout(&dat, uap->dat, sizeof(dat))) != 0)
226143412Snewton			return error;
226243412Snewton	}
226343412Snewton
2264107849Salfred	if (uap->flags) { /* XXX: Need translation */
2265107849Salfred		if ((error = copyout(&fl, uap->flags, sizeof(fl))) != 0)
226643412Snewton			return error;
226743412Snewton	}
226843412Snewton
226943412Snewton	*retval = 0;
227043412Snewton
227143412Snewton#ifdef DEBUG_SVR4
2272107849Salfred	show_msg("<getmsg", uap->fd, uap->ctl,
2273107849Salfred		 uap->dat, fl);
227443412Snewton#endif /* DEBUG_SVR4 */
227543412Snewton	return error;
227643412Snewton}
227743412Snewton
227883366Sjulianint svr4_sys_send(td, uap)
227983366Sjulian	struct thread *td;
228043412Snewton	struct svr4_sys_send_args *uap;
228143412Snewton{
2282103886Smini	struct osend_args osa;
2283107849Salfred	osa.s = uap->s;
2284107849Salfred	osa.buf = uap->buf;
2285107849Salfred	osa.len = uap->len;
2286107849Salfred	osa.flags = uap->flags;
2287103886Smini	return osend(td, &osa);
228843412Snewton}
228943412Snewton
229083366Sjulianint svr4_sys_recv(td, uap)
229183366Sjulian	struct thread *td;
229243412Snewton	struct svr4_sys_recv_args *uap;
229343412Snewton{
2294103886Smini	struct orecv_args ora;
2295107849Salfred	ora.s = uap->s;
2296107849Salfred	ora.buf = uap->buf;
2297107849Salfred	ora.len = uap->len;
2298107849Salfred	ora.flags = uap->flags;
2299103886Smini	return orecv(td, &ora);
230043412Snewton}
230143412Snewton
230243412Snewton/*
230343412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into
230443412Snewton * sendto().  Let's leave it here for now...
230543412Snewton */
230643412Snewtonint
230783366Sjuliansvr4_sys_sendto(td, uap)
230883366Sjulian        struct thread *td;
230943412Snewton        struct svr4_sys_sendto_args *uap;
231043412Snewton{
231143412Snewton        struct sendto_args sa;
231243412Snewton
2313107849Salfred	sa.s = uap->s;
2314107849Salfred	sa.buf = uap->buf;
2315107849Salfred	sa.len = uap->len;
2316107849Salfred	sa.flags = uap->flags;
2317107849Salfred	sa.to = (caddr_t)uap->to;
2318107849Salfred	sa.tolen = uap->tolen;
231943412Snewton
232043412Snewton	DPRINTF(("calling sendto()\n"));
232183366Sjulian	return sendto(td, &sa);
232243412Snewton}
232343412Snewton
2324