svr4_stream.c revision 89319
143412Snewton/*
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.
2949267Snewton *
3050477Speter * $FreeBSD: head/sys/compat/svr4/svr4_stream.c 89319 2002-01-14 00:13:45Z alfred $
3143412Snewton */
3243412Snewton
3343412Snewton/*
3443412Snewton * Pretend that we have streams...
3543412Snewton * Yes, this is gross.
3643412Snewton *
3743412Snewton * ToDo: The state machine for getmsg needs re-thinking
3843412Snewton */
3943412Snewton
4043412Snewton#define COMPAT_43 1
4143412Snewton
4243412Snewton#include <sys/param.h>
4343412Snewton#include <sys/systm.h>
4476166Smarkm#include <sys/fcntl.h>
4543412Snewton#include <sys/filedesc.h>
4643412Snewton#include <sys/filio.h>
4776166Smarkm#include <sys/lock.h>
4876166Smarkm#include <sys/malloc.h>
4976166Smarkm#include <sys/file.h> 		/* Must come after sys/malloc.h */
5043412Snewton#include <sys/mbuf.h>
5176166Smarkm#include <sys/mutex.h>
5276166Smarkm#include <sys/proc.h>
5343412Snewton#include <sys/protosw.h>
5443412Snewton#include <sys/signal.h>
5543412Snewton#include <sys/signalvar.h>
5676166Smarkm#include <sys/socket.h>
5776166Smarkm#include <sys/socketvar.h>
5843412Snewton#include <sys/stat.h>
5943412Snewton#include <sys/sysproto.h>
6076166Smarkm#include <sys/uio.h>
6176166Smarkm#include <sys/ktrace.h>		/* Must come after sys/uio.h */
6276166Smarkm#include <sys/un.h>
6343412Snewton
6476166Smarkm#include <netinet/in.h>
6576166Smarkm
6665302Sobrien#include <compat/svr4/svr4.h>
6765302Sobrien#include <compat/svr4/svr4_types.h>
6865302Sobrien#include <compat/svr4/svr4_util.h>
6965302Sobrien#include <compat/svr4/svr4_signal.h>
7065302Sobrien#include <compat/svr4/svr4_proto.h>
7165302Sobrien#include <compat/svr4/svr4_stropts.h>
7265302Sobrien#include <compat/svr4/svr4_timod.h>
7365302Sobrien#include <compat/svr4/svr4_sockmod.h>
7465302Sobrien#include <compat/svr4/svr4_ioctl.h>
7565302Sobrien#include <compat/svr4/svr4_socket.h>
7643412Snewton
7743412Snewton/* Utils */
7883366Sjulianstatic int clean_pipe __P((struct thread *, const char *));
7943412Snewtonstatic void getparm __P((struct file *, struct svr4_si_sockparms *));
8089308Salfredstatic int svr4_do_putmsg __P((struct thread *, struct svr4_sys_putmsg_args *,
8189306Salfred			       struct file *));
8289308Salfredstatic int svr4_do_getmsg __P((struct thread *, struct svr4_sys_getmsg_args *,
8389306Salfred			       struct file *));
8443412Snewton
8543412Snewton/* Address Conversions */
8643412Snewtonstatic void sockaddr_to_netaddr_in __P((struct svr4_strmcmd *,
8743412Snewton					const struct sockaddr_in *));
8843412Snewtonstatic void sockaddr_to_netaddr_un __P((struct svr4_strmcmd *,
8943412Snewton					const struct sockaddr_un *));
9043412Snewtonstatic void netaddr_to_sockaddr_in __P((struct sockaddr_in *,
9143412Snewton					const struct svr4_strmcmd *));
9243412Snewtonstatic void netaddr_to_sockaddr_un __P((struct sockaddr_un *,
9343412Snewton					const struct svr4_strmcmd *));
9443412Snewton
9543412Snewton/* stream ioctls */
9683366Sjulianstatic int i_nread __P((struct file *, struct thread *, register_t *, int,
9743412Snewton			u_long, caddr_t));
9883366Sjulianstatic int i_fdinsert __P((struct file *, struct thread *, register_t *, int,
9943412Snewton			   u_long, caddr_t));
10083366Sjulianstatic int i_str   __P((struct file *, struct thread *, register_t *, int,
10143412Snewton			u_long, caddr_t));
10283366Sjulianstatic int i_setsig   __P((struct file *, struct thread *, register_t *, int,
10343412Snewton			u_long, caddr_t));
10483366Sjulianstatic int i_getsig   __P((struct file *, struct thread *, register_t *, int,
10543412Snewton			u_long, caddr_t));
10683366Sjulianstatic int _i_bind_rsvd __P((struct file *, struct thread *, register_t *, int,
10743412Snewton			     u_long, caddr_t));
10883366Sjulianstatic int _i_rele_rsvd __P((struct file *, struct thread *, register_t *, int,
10943412Snewton			     u_long, caddr_t));
11043412Snewton
11143412Snewton/* i_str sockmod calls */
11243412Snewtonstatic int sockmod       __P((struct file *, int, struct svr4_strioctl *,
11383366Sjulian			      struct thread *));
11443412Snewtonstatic int si_listen     __P((struct file *, int, struct svr4_strioctl *,
11583366Sjulian			      struct thread *));
11643412Snewtonstatic int si_ogetudata  __P((struct file *, int, struct svr4_strioctl *,
11783366Sjulian			      struct thread *));
11843412Snewtonstatic int si_sockparams __P((struct file *, int, struct svr4_strioctl *,
11983366Sjulian			      struct thread *));
12043412Snewtonstatic int si_shutdown	 __P((struct file *, int, struct svr4_strioctl *,
12183366Sjulian			      struct thread *));
12243412Snewtonstatic int si_getudata   __P((struct file *, int, struct svr4_strioctl *,
12383366Sjulian			      struct thread *));
12443412Snewton
12543412Snewton/* i_str timod calls */
12643412Snewtonstatic int timod         __P((struct file *, int, struct svr4_strioctl *,
12783366Sjulian		              struct thread *));
12843412Snewtonstatic int ti_getinfo    __P((struct file *, int, struct svr4_strioctl *,
12983366Sjulian			      struct thread *));
13043412Snewtonstatic int ti_bind       __P((struct file *, int, struct svr4_strioctl *,
13183366Sjulian			      struct thread *));
13243412Snewton
13343412Snewton/* infrastructure */
13483366Sjulianstatic int svr4_sendit __P((struct thread *td, int s, struct msghdr *mp,
13543412Snewton			    int flags));
13643412Snewton
13783366Sjulianstatic int svr4_recvit __P((struct thread *td, int s, struct msghdr *mp,
13843412Snewton			    caddr_t namelenp));
13943412Snewton
14043412Snewton/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
14143412Snewton * it isn't part of a "public" interface;  We're supposed to use
14243412Snewton * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
14343412Snewton * that matter.  Solution:  Suck sendit()/recvit() into here where we
14443412Snewton * can do what we like.
14543412Snewton *
14643412Snewton * I hate code duplication.
14743412Snewton *
14843412Snewton * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
14943412Snewton */
15043412Snewtonstatic int
15183366Sjuliansvr4_sendit(td, s, mp, flags)
15283366Sjulian	register struct thread *td;
15343412Snewton	int s;
15443412Snewton	register struct msghdr *mp;
15543412Snewton	int flags;
15643412Snewton{
15743412Snewton	struct uio auio;
15843412Snewton	register struct iovec *iov;
15943412Snewton	register int i;
16043412Snewton	struct mbuf *control;
16143412Snewton	struct sockaddr *to;
16243412Snewton	int len, error;
16343412Snewton	struct socket *so;
16443412Snewton#ifdef KTRACE
16543412Snewton	struct iovec *ktriov = NULL;
16662378Sgreen	struct uio ktruio;
16743412Snewton#endif
16843412Snewton
16986487Sdillon	if ((error = fgetsock(td, s, &so, NULL)) != 0)
17043412Snewton		return (error);
17143412Snewton	auio.uio_iov = mp->msg_iov;
17243412Snewton	auio.uio_iovcnt = mp->msg_iovlen;
17343412Snewton	auio.uio_segflg = UIO_USERSPACE;
17443412Snewton	auio.uio_rw = UIO_WRITE;
17583366Sjulian	auio.uio_td = td;
17643412Snewton	auio.uio_offset = 0;			/* XXX */
17743412Snewton	auio.uio_resid = 0;
17843412Snewton	iov = mp->msg_iov;
17943412Snewton	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
18069084Sdillon		if ((auio.uio_resid += iov->iov_len) < 0) {
18186487Sdillon			error = EINVAL;
18286487Sdillon			goto done1;
18369084Sdillon		}
18443412Snewton	}
18543412Snewton	if (mp->msg_name) {
18643412Snewton		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
18786487Sdillon		if (error)
18886487Sdillon			goto done1;
18969084Sdillon	} else {
19043412Snewton		to = 0;
19169084Sdillon	}
19243412Snewton	if (mp->msg_control) {
19343412Snewton		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
19443412Snewton			error = EINVAL;
19543412Snewton			goto bad;
19643412Snewton		}
19743412Snewton		error = sockargs(&control, mp->msg_control,
19843412Snewton		    mp->msg_controllen, MT_CONTROL);
19943412Snewton		if (error)
20043412Snewton			goto bad;
20169084Sdillon	} else {
20243412Snewton		control = 0;
20369084Sdillon	}
20443412Snewton#ifdef KTRACE
20583366Sjulian	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
20643412Snewton		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
20743412Snewton
20843412Snewton		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
20943412Snewton		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
21062378Sgreen		ktruio = auio;
21143412Snewton	}
21243412Snewton#endif
21343412Snewton	len = auio.uio_resid;
21443412Snewton	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
21583366Sjulian						     flags, td);
21643412Snewton	if (error) {
21743412Snewton		if (auio.uio_resid != len && (error == ERESTART ||
21843412Snewton		    error == EINTR || error == EWOULDBLOCK))
21943412Snewton			error = 0;
22073929Sjhb		if (error == EPIPE) {
22183366Sjulian			PROC_LOCK(td->td_proc);
22283366Sjulian			psignal(td->td_proc, SIGPIPE);
22383366Sjulian			PROC_UNLOCK(td->td_proc);
22473929Sjhb		}
22543412Snewton	}
22643412Snewton	if (error == 0)
22783366Sjulian		td->td_retval[0] = len - auio.uio_resid;
22843412Snewton#ifdef KTRACE
22943412Snewton	if (ktriov != NULL) {
23062378Sgreen		if (error == 0) {
23162378Sgreen			ktruio.uio_iov = ktriov;
23283366Sjulian			ktruio.uio_resid = td->td_retval[0];
23383366Sjulian			ktrgenio(td->td_proc->p_tracep, s, UIO_WRITE, &ktruio, error);
23462378Sgreen		}
23543412Snewton		FREE(ktriov, M_TEMP);
23643412Snewton	}
23743412Snewton#endif
23843412Snewtonbad:
23943412Snewton	if (to)
24043412Snewton		FREE(to, M_SONAME);
24186487Sdillondone1:
24289306Salfred	fdrop(fp, td);
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
26343412Snewton	struct iovec *ktriov = NULL;
26462378Sgreen	struct uio ktruio;
26543412Snewton#endif
26643412Snewton
26786487Sdillon	if ((error = fgetsock(td, s, &so, NULL)) != 0)
26843412Snewton		return (error);
26943412Snewton	auio.uio_iov = mp->msg_iov;
27043412Snewton	auio.uio_iovcnt = mp->msg_iovlen;
27143412Snewton	auio.uio_segflg = UIO_USERSPACE;
27243412Snewton	auio.uio_rw = UIO_READ;
27383366Sjulian	auio.uio_td = td;
27443412Snewton	auio.uio_offset = 0;			/* XXX */
27543412Snewton	auio.uio_resid = 0;
27643412Snewton	iov = mp->msg_iov;
27743412Snewton	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
27869084Sdillon		if ((auio.uio_resid += iov->iov_len) < 0) {
27986487Sdillon			error = EINVAL;
28086487Sdillon			goto done1;
28169084Sdillon		}
28243412Snewton	}
28343412Snewton#ifdef KTRACE
28483366Sjulian	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
28543412Snewton		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
28643412Snewton
28743412Snewton		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
28843412Snewton		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
28962378Sgreen		ktruio = auio;
29043412Snewton	}
29143412Snewton#endif
29243412Snewton	len = auio.uio_resid;
29343412Snewton	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
29443412Snewton	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
29543412Snewton	    &mp->msg_flags);
29643412Snewton	if (error) {
29743412Snewton		if (auio.uio_resid != len && (error == ERESTART ||
29843412Snewton		    error == EINTR || error == EWOULDBLOCK))
29943412Snewton			error = 0;
30043412Snewton	}
30143412Snewton#ifdef KTRACE
30243412Snewton	if (ktriov != NULL) {
30362378Sgreen		if (error == 0) {
30462378Sgreen			ktruio.uio_iov = ktriov;
30562378Sgreen			ktruio.uio_resid = len - auio.uio_resid;
30683366Sjulian			ktrgenio(td->td_proc->p_tracep, s, UIO_READ, &ktruio, error);
30762378Sgreen		}
30843412Snewton		FREE(ktriov, M_TEMP);
30943412Snewton	}
31043412Snewton#endif
31143412Snewton	if (error)
31243412Snewton		goto out;
31383366Sjulian	td->td_retval[0] = len - auio.uio_resid;
31443412Snewton	if (mp->msg_name) {
31543412Snewton		len = mp->msg_namelen;
31643412Snewton		if (len <= 0 || fromsa == 0)
31743412Snewton			len = 0;
31843412Snewton		else {
31943412Snewton#ifndef MIN
32043412Snewton#define MIN(a,b) ((a)>(b)?(b):(a))
32143412Snewton#endif
32243412Snewton			/* save sa_len before it is destroyed by MSG_COMPAT */
32343412Snewton			len = MIN(len, fromsa->sa_len);
32443412Snewton			error = copyout(fromsa,
32543412Snewton			    (caddr_t)mp->msg_name, (unsigned)len);
32643412Snewton			if (error)
32743412Snewton				goto out;
32843412Snewton		}
32943412Snewton		mp->msg_namelen = len;
33043412Snewton		if (namelenp &&
33143412Snewton		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
33243412Snewton			goto out;
33343412Snewton		}
33443412Snewton	}
33543412Snewton	if (mp->msg_control) {
33643412Snewton		len = mp->msg_controllen;
33743412Snewton		m = control;
33843412Snewton		mp->msg_controllen = 0;
33943412Snewton		ctlbuf = (caddr_t) mp->msg_control;
34043412Snewton
34143412Snewton		while (m && len > 0) {
34243412Snewton			unsigned int tocopy;
34343412Snewton
34443412Snewton			if (len >= m->m_len)
34543412Snewton				tocopy = m->m_len;
34643412Snewton			else {
34743412Snewton				mp->msg_flags |= MSG_CTRUNC;
34843412Snewton				tocopy = len;
34943412Snewton			}
35043412Snewton
35149267Snewton			if ((error = copyout((caddr_t)mtod(m, caddr_t),
35249267Snewton					ctlbuf, tocopy)) != 0)
35343412Snewton				goto out;
35443412Snewton
35543412Snewton			ctlbuf += tocopy;
35643412Snewton			len -= tocopy;
35743412Snewton			m = m->m_next;
35843412Snewton		}
35953678Sphk		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
36043412Snewton	}
36143412Snewtonout:
36243412Snewton	if (fromsa)
36343412Snewton		FREE(fromsa, M_SONAME);
36443412Snewton	if (control)
36543412Snewton		m_freem(control);
36686487Sdillondone1:
36789306Salfred	fdrop(fp, td);
36886487Sdillon	fputsock(so);
36943412Snewton	return (error);
37043412Snewton}
37143412Snewton
37243412Snewton#ifdef DEBUG_SVR4
37343412Snewtonstatic void bufprint __P((u_char *, size_t));
37443412Snewtonstatic int show_ioc __P((const char *, struct svr4_strioctl *));
37543412Snewtonstatic int show_strbuf __P((struct svr4_strbuf *));
37643412Snewtonstatic void show_msg __P((const char *, int, struct svr4_strbuf *,
37743412Snewton			  struct svr4_strbuf *, int));
37843412Snewton
37943412Snewtonstatic void
38043412Snewtonbufprint(buf, len)
38143412Snewton	u_char *buf;
38243412Snewton	size_t len;
38343412Snewton{
38443412Snewton	size_t i;
38543412Snewton
38643412Snewton	uprintf("\n\t");
38743412Snewton	for (i = 0; i < len; i++) {
38843412Snewton		uprintf("%x ", buf[i]);
38943412Snewton		if (i && (i % 16) == 0)
39043412Snewton			uprintf("\n\t");
39143412Snewton	}
39243412Snewton}
39343412Snewton
39443412Snewtonstatic int
39543412Snewtonshow_ioc(str, ioc)
39643412Snewton	const char		*str;
39743412Snewton	struct svr4_strioctl	*ioc;
39843412Snewton{
39943412Snewton	u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK);
40043412Snewton	int error;
40143412Snewton
40243412Snewton	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
40343412Snewton	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
40443412Snewton
40543412Snewton	if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) {
40643412Snewton		free((char *) ptr, M_TEMP);
40743412Snewton		return error;
40843412Snewton	}
40943412Snewton
41043412Snewton	bufprint(ptr, ioc->len);
41143412Snewton
41243412Snewton	uprintf("}\n");
41343412Snewton
41443412Snewton	free((char *) ptr, M_TEMP);
41543412Snewton	return 0;
41643412Snewton}
41743412Snewton
41843412Snewton
41943412Snewtonstatic int
42043412Snewtonshow_strbuf(str)
42143412Snewton	struct svr4_strbuf *str;
42243412Snewton{
42343412Snewton	int error;
42443412Snewton	u_char *ptr = NULL;
42543412Snewton	int maxlen = str->maxlen;
42643412Snewton	int len = str->len;
42743412Snewton
42843412Snewton	if (maxlen < 0)
42943412Snewton		maxlen = 0;
43043412Snewton
43143412Snewton	if (len >= maxlen)
43243412Snewton		len = maxlen;
43343412Snewton
43443412Snewton	if (len > 0) {
43543412Snewton	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
43643412Snewton
43743412Snewton	    if ((error = copyin(str->buf, ptr, len)) != 0) {
43843412Snewton		    free((char *) ptr, M_TEMP);
43943412Snewton		    return error;
44043412Snewton	    }
44143412Snewton	}
44243412Snewton
44343412Snewton	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
44443412Snewton
44543412Snewton	if (ptr)
44643412Snewton		bufprint(ptr, len);
44743412Snewton
44843412Snewton	uprintf("]}");
44943412Snewton
45043412Snewton	if (ptr)
45143412Snewton		free((char *) ptr, M_TEMP);
45243412Snewton
45343412Snewton	return 0;
45443412Snewton}
45543412Snewton
45643412Snewton
45743412Snewtonstatic void
45843412Snewtonshow_msg(str, fd, ctl, dat, flags)
45943412Snewton	const char		*str;
46043412Snewton	int			 fd;
46143412Snewton	struct svr4_strbuf	*ctl;
46243412Snewton	struct svr4_strbuf	*dat;
46343412Snewton	int			 flags;
46443412Snewton{
46543412Snewton	struct svr4_strbuf	buf;
46643412Snewton	int error;
46743412Snewton
46843412Snewton	uprintf("%s(%d", str, fd);
46943412Snewton	if (ctl != NULL) {
47043412Snewton		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
47143412Snewton			return;
47243412Snewton		show_strbuf(&buf);
47343412Snewton	}
47443412Snewton	else
47543412Snewton		uprintf(", NULL");
47643412Snewton
47743412Snewton	if (dat != NULL) {
47843412Snewton		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
47943412Snewton			return;
48043412Snewton		show_strbuf(&buf);
48143412Snewton	}
48243412Snewton	else
48343412Snewton		uprintf(", NULL");
48443412Snewton
48543412Snewton	uprintf(", %x);\n", flags);
48643412Snewton}
48743412Snewton
48843412Snewton#endif /* DEBUG_SVR4 */
48943412Snewton
49043412Snewton/*
49143412Snewton * We are faced with an interesting situation. On svr4 unix sockets
49243412Snewton * are really pipes. But we really have sockets, and we might as
49343412Snewton * well use them. At the point where svr4 calls TI_BIND, it has
49443412Snewton * already created a named pipe for the socket using mknod(2).
49543412Snewton * We need to create a socket with the same name when we bind,
49643412Snewton * so we need to remove the pipe before, otherwise we'll get address
49743412Snewton * already in use. So we *carefully* remove the pipe, to avoid
49843412Snewton * using this as a random file removal tool. We use system calls
49943412Snewton * to avoid code duplication.
50043412Snewton */
50143412Snewtonstatic int
50283366Sjulianclean_pipe(td, path)
50383366Sjulian	struct thread *td;
50443412Snewton	const char *path;
50543412Snewton{
50643412Snewton	struct lstat_args la;
50743412Snewton	struct unlink_args ua;
50843412Snewton	struct stat st;
50943412Snewton	int error;
51043412Snewton	caddr_t sg = stackgap_init();
51143412Snewton	size_t l = strlen(path) + 1;
51243412Snewton	void *tpath;
51343412Snewton
51443412Snewton	tpath = stackgap_alloc(&sg, l);
51543412Snewton	SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
51643412Snewton
51743412Snewton	if ((error = copyout(path, tpath, l)) != 0)
51843412Snewton		return error;
51943412Snewton
52043412Snewton	SCARG(&la, path) = tpath;
52143412Snewton
52283366Sjulian	if ((error = lstat(td, &la)) != 0)
52343412Snewton		return 0;
52443412Snewton
52543412Snewton	if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
52643412Snewton		return 0;
52743412Snewton
52843412Snewton	/*
52943412Snewton	 * Make sure we are dealing with a mode 0 named pipe.
53043412Snewton	 */
53143412Snewton	if ((st.st_mode & S_IFMT) != S_IFIFO)
53243412Snewton		return 0;
53343412Snewton
53443412Snewton	if ((st.st_mode & ALLPERMS) != 0)
53543412Snewton		return 0;
53643412Snewton
53743412Snewton	SCARG(&ua, path) = SCARG(&la, path);
53843412Snewton
53983366Sjulian	if ((error = unlink(td, &ua)) != 0) {
54043412Snewton		DPRINTF(("clean_pipe: unlink failed %d\n", error));
54143412Snewton		return error;
54243412Snewton	}
54343412Snewton
54443412Snewton	return 0;
54543412Snewton}
54643412Snewton
54743412Snewton
54843412Snewtonstatic void
54943412Snewtonsockaddr_to_netaddr_in(sc, sain)
55043412Snewton	struct svr4_strmcmd *sc;
55143412Snewton	const struct sockaddr_in *sain;
55243412Snewton{
55343412Snewton	struct svr4_netaddr_in *na;
55443412Snewton	na = SVR4_ADDROF(sc);
55543412Snewton
55643412Snewton	na->family = sain->sin_family;
55743412Snewton	na->port = sain->sin_port;
55843412Snewton	na->addr = sain->sin_addr.s_addr;
55943412Snewton	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
56043412Snewton		 na->addr));
56143412Snewton}
56243412Snewton
56343412Snewton
56443412Snewtonstatic void
56543412Snewtonsockaddr_to_netaddr_un(sc, saun)
56643412Snewton	struct svr4_strmcmd *sc;
56743412Snewton	const struct sockaddr_un *saun;
56843412Snewton{
56943412Snewton	struct svr4_netaddr_un *na;
57043412Snewton	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
57143412Snewton	    sizeof(*sc);
57243412Snewton	const char *src;
57343412Snewton
57443412Snewton	na = SVR4_ADDROF(sc);
57543412Snewton	na->family = saun->sun_family;
57643412Snewton	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
57743412Snewton		if (dst == edst)
57843412Snewton			break;
57943412Snewton	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
58043412Snewton}
58143412Snewton
58243412Snewton
58343412Snewtonstatic void
58443412Snewtonnetaddr_to_sockaddr_in(sain, sc)
58543412Snewton	struct sockaddr_in *sain;
58643412Snewton	const struct svr4_strmcmd *sc;
58743412Snewton{
58843412Snewton	const struct svr4_netaddr_in *na;
58943412Snewton
59043412Snewton
59143412Snewton	na = SVR4_C_ADDROF(sc);
59243412Snewton	memset(sain, 0, sizeof(*sain));
59343412Snewton	sain->sin_len = sizeof(*sain);
59443412Snewton	sain->sin_family = na->family;
59543412Snewton	sain->sin_port = na->port;
59643412Snewton	sain->sin_addr.s_addr = na->addr;
59743412Snewton	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
59843412Snewton		 sain->sin_port, sain->sin_addr.s_addr));
59943412Snewton}
60043412Snewton
60143412Snewton
60243412Snewtonstatic void
60343412Snewtonnetaddr_to_sockaddr_un(saun, sc)
60443412Snewton	struct sockaddr_un *saun;
60543412Snewton	const struct svr4_strmcmd *sc;
60643412Snewton{
60743412Snewton	const struct svr4_netaddr_un *na;
60843412Snewton	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
60943412Snewton	const char *src;
61043412Snewton
61143412Snewton	na = SVR4_C_ADDROF(sc);
61243412Snewton	memset(saun, 0, sizeof(*saun));
61343412Snewton	saun->sun_family = na->family;
61443412Snewton	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
61543412Snewton		if (dst == edst)
61643412Snewton			break;
61743412Snewton	saun->sun_len = dst - saun->sun_path;
61843412Snewton	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
61943412Snewton		 saun->sun_path));
62043412Snewton}
62143412Snewton
62243412Snewton
62343412Snewtonstatic void
62443412Snewtongetparm(fp, pa)
62543412Snewton	struct file *fp;
62643412Snewton	struct svr4_si_sockparms *pa;
62743412Snewton{
62889306Salfred	struct svr4_strm *st;
62989306Salfred	struct socket *so;
63043412Snewton
63189306Salfred	st = svr4_stream_get(fp);
63243412Snewton	if (st == NULL)
63343412Snewton		return;
63443412Snewton
63589306Salfred	so = (struct socket *) fp->f_data;
63689306Salfred
63743412Snewton	pa->family = st->s_family;
63843412Snewton
63943412Snewton	switch (so->so_type) {
64043412Snewton	case SOCK_DGRAM:
64143412Snewton		pa->type = SVR4_T_CLTS;
64243412Snewton		pa->protocol = IPPROTO_UDP;
64343412Snewton		DPRINTF(("getparm(dgram)\n"));
64443412Snewton		return;
64543412Snewton
64643412Snewton	case SOCK_STREAM:
64743412Snewton	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
64843412Snewton		pa->protocol = IPPROTO_IP;
64943412Snewton		DPRINTF(("getparm(stream)\n"));
65043412Snewton		return;
65143412Snewton
65243412Snewton	case SOCK_RAW:
65343412Snewton		pa->type = SVR4_T_CLTS;
65443412Snewton		pa->protocol = IPPROTO_RAW;
65543412Snewton		DPRINTF(("getparm(raw)\n"));
65643412Snewton		return;
65743412Snewton
65843412Snewton	default:
65943412Snewton		pa->type = 0;
66043412Snewton		pa->protocol = 0;
66143412Snewton		DPRINTF(("getparm(type %d?)\n", so->so_type));
66243412Snewton		return;
66343412Snewton	}
66443412Snewton}
66543412Snewton
66643412Snewton
66743412Snewtonstatic int
66883366Sjuliansi_ogetudata(fp, fd, ioc, td)
66943412Snewton	struct file		*fp;
67043412Snewton	int 			 fd;
67143412Snewton	struct svr4_strioctl	*ioc;
67283366Sjulian	struct thread		*td;
67343412Snewton{
67443412Snewton	int error;
67543412Snewton	struct svr4_si_oudata ud;
67643412Snewton	struct svr4_si_sockparms pa;
67743412Snewton
67843412Snewton	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
67943412Snewton		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
68043412Snewton			 sizeof(ud), ioc->len));
68143412Snewton		return EINVAL;
68243412Snewton	}
68343412Snewton
68443412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
68543412Snewton		return error;
68643412Snewton
68743412Snewton	getparm(fp, &pa);
68843412Snewton
68943412Snewton	switch (pa.family) {
69043412Snewton	case AF_INET:
69143412Snewton	    ud.tidusize = 16384;
69243412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
69343412Snewton	    if (pa.type == SVR4_SOCK_STREAM)
69443412Snewton		    ud.etsdusize = 1;
69543412Snewton	    else
69643412Snewton		    ud.etsdusize = 0;
69743412Snewton	    break;
69843412Snewton
69943412Snewton	case AF_LOCAL:
70043412Snewton	    ud.tidusize = 65536;
70143412Snewton	    ud.addrsize = 128;
70243412Snewton	    ud.etsdusize = 128;
70343412Snewton	    break;
70443412Snewton
70543412Snewton	default:
70643412Snewton	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
70743412Snewton		     pa.family));
70843412Snewton	    return ENOSYS;
70943412Snewton	}
71043412Snewton
71143412Snewton	/* I have no idea what these should be! */
71243412Snewton	ud.optsize = 128;
71343412Snewton	ud.tsdusize = 128;
71443412Snewton
71543412Snewton	ud.servtype = pa.type;
71643412Snewton
71743412Snewton	/* XXX: Fixme */
71843412Snewton	ud.so_state = 0;
71943412Snewton	ud.so_options = 0;
72043412Snewton	return copyout(&ud, ioc->buf, ioc->len);
72143412Snewton}
72243412Snewton
72343412Snewton
72443412Snewtonstatic int
72583366Sjuliansi_sockparams(fp, fd, ioc, td)
72643412Snewton	struct file		*fp;
72743412Snewton	int 			 fd;
72843412Snewton	struct svr4_strioctl	*ioc;
72983366Sjulian	struct thread		*td;
73043412Snewton{
73143412Snewton	struct svr4_si_sockparms pa;
73243412Snewton
73343412Snewton	getparm(fp, &pa);
73443412Snewton	return copyout(&pa, ioc->buf, sizeof(pa));
73543412Snewton}
73643412Snewton
73743412Snewton
73843412Snewtonstatic int
73983366Sjuliansi_listen(fp, fd, ioc, td)
74043412Snewton	struct file		*fp;
74143412Snewton	int 			 fd;
74243412Snewton	struct svr4_strioctl	*ioc;
74383366Sjulian	struct thread		*td;
74443412Snewton{
74543412Snewton	int error;
74643412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
74743412Snewton	struct svr4_strmcmd lst;
74843412Snewton	struct listen_args la;
74943412Snewton
75043412Snewton	if (st == NULL)
75143412Snewton		return EINVAL;
75243412Snewton
75343412Snewton	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
75443412Snewton		return error;
75543412Snewton
75643412Snewton	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
75743412Snewton		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
75843412Snewton		return EINVAL;
75943412Snewton	}
76043412Snewton
76143412Snewton	/*
76243412Snewton	 * We are making assumptions again...
76343412Snewton	 */
76443412Snewton	SCARG(&la, s) = fd;
76543412Snewton	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
76643412Snewton	SCARG(&la, backlog) = 5;
76743412Snewton
76883366Sjulian	if ((error = listen(td, &la)) != 0) {
76943412Snewton		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
77043412Snewton		return error;
77143412Snewton	}
77243412Snewton
77343412Snewton	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
77443412Snewton	lst.cmd = SVR4_TI_BIND_REPLY;
77543412Snewton
77643412Snewton	switch (st->s_family) {
77743412Snewton	case AF_INET:
77843412Snewton		/* XXX: Fill the length here */
77943412Snewton		break;
78043412Snewton
78143412Snewton	case AF_LOCAL:
78243412Snewton		lst.len = 140;
78343412Snewton		lst.pad[28] = 0x00000000;	/* magic again */
78443412Snewton		lst.pad[29] = 0x00000800;	/* magic again */
78543412Snewton		lst.pad[30] = 0x80001400;	/* magic again */
78643412Snewton		break;
78743412Snewton
78843412Snewton	default:
78943412Snewton		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
79043412Snewton		    st->s_family));
79143412Snewton		return ENOSYS;
79243412Snewton	}
79343412Snewton
79443412Snewton
79543412Snewton	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
79643412Snewton		return error;
79743412Snewton
79843412Snewton	return 0;
79943412Snewton}
80043412Snewton
80143412Snewton
80243412Snewtonstatic int
80383366Sjuliansi_getudata(fp, fd, ioc, td)
80443412Snewton	struct file		*fp;
80543412Snewton	int 			 fd;
80643412Snewton	struct svr4_strioctl	*ioc;
80783366Sjulian	struct thread		*td;
80843412Snewton{
80943412Snewton	int error;
81043412Snewton	struct svr4_si_udata ud;
81143412Snewton
81243412Snewton	if (sizeof(ud) != ioc->len) {
81343412Snewton		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
81443412Snewton			 sizeof(ud), ioc->len));
81543412Snewton		return EINVAL;
81643412Snewton	}
81743412Snewton
81843412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
81943412Snewton		return error;
82043412Snewton
82143412Snewton	getparm(fp, &ud.sockparms);
82243412Snewton
82343412Snewton	switch (ud.sockparms.family) {
82443412Snewton	case AF_INET:
82543412Snewton	    DPRINTF(("getudata_inet\n"));
82643412Snewton	    ud.tidusize = 16384;
82743412Snewton	    ud.tsdusize = 16384;
82843412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
82943412Snewton	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
83043412Snewton		    ud.etsdusize = 1;
83143412Snewton	    else
83243412Snewton		    ud.etsdusize = 0;
83343412Snewton	    ud.optsize = 0;
83443412Snewton	    break;
83543412Snewton
83643412Snewton	case AF_LOCAL:
83743412Snewton	    DPRINTF(("getudata_local\n"));
83843412Snewton	    ud.tidusize = 65536;
83943412Snewton	    ud.tsdusize = 128;
84043412Snewton	    ud.addrsize = 128;
84143412Snewton	    ud.etsdusize = 128;
84243412Snewton	    ud.optsize = 128;
84343412Snewton	    break;
84443412Snewton
84543412Snewton	default:
84643412Snewton	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
84743412Snewton		     ud.sockparms.family));
84843412Snewton	    return ENOSYS;
84943412Snewton	}
85043412Snewton
85143412Snewton
85243412Snewton	ud.servtype = ud.sockparms.type;
85343412Snewton	DPRINTF(("ud.servtype = %d\n", ud.servtype));
85443412Snewton	/* XXX: Fixme */
85543412Snewton	ud.so_state = 0;
85643412Snewton	ud.so_options = 0;
85743412Snewton	return copyout(&ud, ioc->buf, sizeof(ud));
85843412Snewton}
85943412Snewton
86043412Snewton
86143412Snewtonstatic int
86283366Sjuliansi_shutdown(fp, fd, ioc, td)
86343412Snewton	struct file		*fp;
86443412Snewton	int 			 fd;
86543412Snewton	struct svr4_strioctl	*ioc;
86683366Sjulian	struct thread		*td;
86743412Snewton{
86843412Snewton	int error;
86943412Snewton	struct shutdown_args ap;
87043412Snewton
87143412Snewton	if (ioc->len != sizeof(SCARG(&ap, how))) {
87243412Snewton		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
87343412Snewton			 sizeof(SCARG(&ap, how)), ioc->len));
87443412Snewton		return EINVAL;
87543412Snewton	}
87643412Snewton
87743412Snewton	if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
87843412Snewton		return error;
87943412Snewton
88043412Snewton	SCARG(&ap, s) = fd;
88143412Snewton
88283366Sjulian	return shutdown(td, &ap);
88343412Snewton}
88443412Snewton
88543412Snewton
88643412Snewtonstatic int
88783366Sjuliansockmod(fp, fd, ioc, td)
88843412Snewton	struct file		*fp;
88943412Snewton	int			 fd;
89043412Snewton	struct svr4_strioctl	*ioc;
89183366Sjulian	struct thread		*td;
89243412Snewton{
89343412Snewton	switch (ioc->cmd) {
89443412Snewton	case SVR4_SI_OGETUDATA:
89543412Snewton		DPRINTF(("SI_OGETUDATA\n"));
89683366Sjulian		return si_ogetudata(fp, fd, ioc, td);
89743412Snewton
89843412Snewton	case SVR4_SI_SHUTDOWN:
89943412Snewton		DPRINTF(("SI_SHUTDOWN\n"));
90083366Sjulian		return si_shutdown(fp, fd, ioc, td);
90143412Snewton
90243412Snewton	case SVR4_SI_LISTEN:
90343412Snewton		DPRINTF(("SI_LISTEN\n"));
90483366Sjulian		return si_listen(fp, fd, ioc, td);
90543412Snewton
90643412Snewton	case SVR4_SI_SETMYNAME:
90743412Snewton		DPRINTF(("SI_SETMYNAME\n"));
90843412Snewton		return 0;
90943412Snewton
91043412Snewton	case SVR4_SI_SETPEERNAME:
91143412Snewton		DPRINTF(("SI_SETPEERNAME\n"));
91243412Snewton		return 0;
91343412Snewton
91443412Snewton	case SVR4_SI_GETINTRANSIT:
91543412Snewton		DPRINTF(("SI_GETINTRANSIT\n"));
91643412Snewton		return 0;
91743412Snewton
91843412Snewton	case SVR4_SI_TCL_LINK:
91943412Snewton		DPRINTF(("SI_TCL_LINK\n"));
92043412Snewton		return 0;
92143412Snewton
92243412Snewton	case SVR4_SI_TCL_UNLINK:
92343412Snewton		DPRINTF(("SI_TCL_UNLINK\n"));
92443412Snewton		return 0;
92543412Snewton
92643412Snewton	case SVR4_SI_SOCKPARAMS:
92743412Snewton		DPRINTF(("SI_SOCKPARAMS\n"));
92883366Sjulian		return si_sockparams(fp, fd, ioc, td);
92943412Snewton
93043412Snewton	case SVR4_SI_GETUDATA:
93143412Snewton		DPRINTF(("SI_GETUDATA\n"));
93283366Sjulian		return si_getudata(fp, fd, ioc, td);
93343412Snewton
93443412Snewton	default:
93543412Snewton		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
93643412Snewton		return 0;
93743412Snewton
93843412Snewton	}
93943412Snewton}
94043412Snewton
94143412Snewton
94243412Snewtonstatic int
94383366Sjulianti_getinfo(fp, fd, ioc, td)
94443412Snewton	struct file		*fp;
94543412Snewton	int 			 fd;
94643412Snewton	struct svr4_strioctl	*ioc;
94783366Sjulian	struct thread		*td;
94843412Snewton{
94943412Snewton	int error;
95043412Snewton	struct svr4_infocmd info;
95143412Snewton
95243412Snewton	memset(&info, 0, sizeof(info));
95343412Snewton
95443412Snewton	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
95543412Snewton		return error;
95643412Snewton
95743412Snewton	if (info.cmd != SVR4_TI_INFO_REQUEST)
95843412Snewton		return EINVAL;
95943412Snewton
96043412Snewton	info.cmd = SVR4_TI_INFO_REPLY;
96143412Snewton	info.tsdu = 0;
96243412Snewton	info.etsdu = 1;
96343412Snewton	info.cdata = -2;
96443412Snewton	info.ddata = -2;
96543412Snewton	info.addr = 16;
96643412Snewton	info.opt = -1;
96743412Snewton	info.tidu = 16384;
96843412Snewton	info.serv = 2;
96943412Snewton	info.current = 0;
97043412Snewton	info.provider = 2;
97143412Snewton
97243412Snewton	ioc->len = sizeof(info);
97343412Snewton	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
97443412Snewton		return error;
97543412Snewton
97643412Snewton	return 0;
97743412Snewton}
97843412Snewton
97943412Snewton
98043412Snewtonstatic int
98183366Sjulianti_bind(fp, fd, ioc, td)
98243412Snewton	struct file		*fp;
98343412Snewton	int 			 fd;
98443412Snewton	struct svr4_strioctl	*ioc;
98583366Sjulian	struct thread		*td;
98643412Snewton{
98743412Snewton	int error;
98843412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
98943412Snewton	struct sockaddr_in sain;
99043412Snewton	struct sockaddr_un saun;
99143412Snewton	caddr_t sg;
99243412Snewton	void *skp, *sup = NULL;
99343412Snewton	int sasize;
99443412Snewton	struct svr4_strmcmd bnd;
99543412Snewton	struct bind_args ba;
99643412Snewton
99743412Snewton	if (st == NULL) {
99843412Snewton		DPRINTF(("ti_bind: bad file descriptor\n"));
99943412Snewton		return EINVAL;
100043412Snewton	}
100143412Snewton
100243412Snewton	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
100343412Snewton		return error;
100443412Snewton
100543412Snewton	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
100643412Snewton		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
100743412Snewton		return EINVAL;
100843412Snewton	}
100943412Snewton
101043412Snewton	switch (st->s_family) {
101143412Snewton	case AF_INET:
101243412Snewton		skp = &sain;
101343412Snewton		sasize = sizeof(sain);
101443412Snewton
101543412Snewton		if (bnd.offs == 0)
101643412Snewton			goto reply;
101743412Snewton
101843412Snewton		netaddr_to_sockaddr_in(&sain, &bnd);
101943412Snewton
102043412Snewton		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
102143412Snewton			 sain.sin_family, sain.sin_port,
102243412Snewton			 sain.sin_addr.s_addr));
102343412Snewton		break;
102443412Snewton
102543412Snewton	case AF_LOCAL:
102643412Snewton		skp = &saun;
102743412Snewton		sasize = sizeof(saun);
102843412Snewton		if (bnd.offs == 0)
102943412Snewton			goto reply;
103043412Snewton
103143412Snewton		netaddr_to_sockaddr_un(&saun, &bnd);
103243412Snewton
103343412Snewton		if (saun.sun_path[0] == '\0')
103443412Snewton			goto reply;
103543412Snewton
103643412Snewton		DPRINTF(("TI_BIND: fam %d, path %s\n",
103743412Snewton			 saun.sun_family, saun.sun_path));
103843412Snewton
103983366Sjulian		if ((error = clean_pipe(td, saun.sun_path)) != 0)
104043412Snewton			return error;
104143412Snewton
104243412Snewton		bnd.pad[28] = 0x00001000;	/* magic again */
104343412Snewton		break;
104443412Snewton
104543412Snewton	default:
104643412Snewton		DPRINTF(("TI_BIND: Unsupported address family %d\n",
104743412Snewton			 st->s_family));
104843412Snewton		return ENOSYS;
104943412Snewton	}
105043412Snewton
105143412Snewton	sg = stackgap_init();
105243412Snewton	sup = stackgap_alloc(&sg, sasize);
105343412Snewton
105443412Snewton	if ((error = copyout(skp, sup, sasize)) != 0)
105543412Snewton		return error;
105643412Snewton
105743412Snewton	SCARG(&ba, s) = fd;
105843412Snewton	DPRINTF(("TI_BIND: fileno %d\n", fd));
105943412Snewton	SCARG(&ba, name) = (void *) sup;
106043412Snewton	SCARG(&ba, namelen) = sasize;
106143412Snewton
106283366Sjulian	if ((error = bind(td, &ba)) != 0) {
106343412Snewton		DPRINTF(("TI_BIND: bind failed %d\n", error));
106443412Snewton		return error;
106543412Snewton	}
106643412Snewton
106743412Snewtonreply:
106843412Snewton	if (sup == NULL) {
106943412Snewton		memset(&bnd, 0, sizeof(bnd));
107043412Snewton		bnd.len = sasize + 4;
107143412Snewton		bnd.offs = 0x10;	/* XXX */
107243412Snewton	}
107343412Snewton
107443412Snewton	bnd.cmd = SVR4_TI_BIND_REPLY;
107543412Snewton
107643412Snewton	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
107743412Snewton		return error;
107843412Snewton
107943412Snewton	return 0;
108043412Snewton}
108143412Snewton
108243412Snewton
108343412Snewtonstatic int
108483366Sjuliantimod(fp, fd, ioc, td)
108543412Snewton	struct file		*fp;
108643412Snewton	int			 fd;
108743412Snewton	struct svr4_strioctl	*ioc;
108883366Sjulian	struct thread		*td;
108943412Snewton{
109043412Snewton	switch (ioc->cmd) {
109143412Snewton	case SVR4_TI_GETINFO:
109243412Snewton		DPRINTF(("TI_GETINFO\n"));
109383366Sjulian		return ti_getinfo(fp, fd, ioc, td);
109443412Snewton
109543412Snewton	case SVR4_TI_OPTMGMT:
109643412Snewton		DPRINTF(("TI_OPTMGMT\n"));
109743412Snewton		return 0;
109843412Snewton
109943412Snewton	case SVR4_TI_BIND:
110043412Snewton		DPRINTF(("TI_BIND\n"));
110183366Sjulian		return ti_bind(fp, fd, ioc, td);
110243412Snewton
110343412Snewton	case SVR4_TI_UNBIND:
110443412Snewton		DPRINTF(("TI_UNBIND\n"));
110543412Snewton		return 0;
110643412Snewton
110743412Snewton	default:
110843412Snewton		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
110943412Snewton		return 0;
111043412Snewton	}
111143412Snewton}
111243412Snewton
111343412Snewton
111443412Snewtonint
111583366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
111643412Snewton	struct file *fp;
111783366Sjulian	struct thread *td;
111843412Snewton	register_t *retval;
111943412Snewton	int fd;
112043412Snewton	u_long cmd;
112143412Snewton	caddr_t dat;
112243412Snewton{
112343412Snewton	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
112443412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
112543412Snewton	int error;
112643412Snewton	void *skp, *sup;
112743412Snewton	struct sockaddr_in sain;
112843412Snewton	struct sockaddr_un saun;
112943412Snewton	struct svr4_strmcmd sc;
113043412Snewton	int sasize;
113143412Snewton	caddr_t sg;
113243412Snewton	int *lenp;
113343412Snewton
113443412Snewton	DPRINTF(("svr4_stream_ti_ioctl\n"));
113543412Snewton
113643412Snewton	if (st == NULL)
113743412Snewton		return EINVAL;
113843412Snewton
113943412Snewton	sc.offs = 0x10;
114043412Snewton
114143412Snewton	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
114243412Snewton		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
114343412Snewton		return error;
114443412Snewton	}
114543412Snewton
114643412Snewton	switch (st->s_family) {
114743412Snewton	case AF_INET:
114843412Snewton		skp = &sain;
114943412Snewton		sasize = sizeof(sain);
115043412Snewton		break;
115143412Snewton
115243412Snewton	case AF_LOCAL:
115343412Snewton		skp = &saun;
115443412Snewton		sasize = sizeof(saun);
115543412Snewton		break;
115643412Snewton
115743412Snewton	default:
115843412Snewton		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
115943412Snewton			 st->s_family));
116043412Snewton		return ENOSYS;
116143412Snewton	}
116243412Snewton
116343412Snewton	sg = stackgap_init();
116443412Snewton	sup = stackgap_alloc(&sg, sasize);
116543412Snewton	lenp = stackgap_alloc(&sg, sizeof(*lenp));
116643412Snewton
116743412Snewton	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
116843412Snewton		DPRINTF(("ti_ioctl: error copying out lenp\n"));
116943412Snewton		return error;
117043412Snewton	}
117143412Snewton
117243412Snewton	switch (cmd) {
117343412Snewton	case SVR4_TI_GETMYNAME:
117443412Snewton		DPRINTF(("TI_GETMYNAME\n"));
117543412Snewton		{
117643412Snewton			struct getsockname_args ap;
117743412Snewton			SCARG(&ap, fdes) = fd;
117843412Snewton			SCARG(&ap, asa) = sup;
117943412Snewton			SCARG(&ap, alen) = lenp;
118083366Sjulian			if ((error = getsockname(td, &ap)) != 0) {
118143412Snewton				DPRINTF(("ti_ioctl: getsockname error\n"));
118243412Snewton				return error;
118343412Snewton			}
118443412Snewton		}
118543412Snewton		break;
118643412Snewton
118743412Snewton	case SVR4_TI_GETPEERNAME:
118843412Snewton		DPRINTF(("TI_GETPEERNAME\n"));
118943412Snewton		{
119043412Snewton			struct getpeername_args ap;
119143412Snewton			SCARG(&ap, fdes) = fd;
119243412Snewton			SCARG(&ap, asa) = sup;
119343412Snewton			SCARG(&ap, alen) = lenp;
119483366Sjulian			if ((error = getpeername(td, &ap)) != 0) {
119543412Snewton				DPRINTF(("ti_ioctl: getpeername error\n"));
119643412Snewton				return error;
119743412Snewton			}
119843412Snewton		}
119943412Snewton		break;
120043412Snewton
120143412Snewton	case SVR4_TI_SETMYNAME:
120243412Snewton		DPRINTF(("TI_SETMYNAME\n"));
120343412Snewton		return 0;
120443412Snewton
120543412Snewton	case SVR4_TI_SETPEERNAME:
120643412Snewton		DPRINTF(("TI_SETPEERNAME\n"));
120743412Snewton		return 0;
120843412Snewton	default:
120943412Snewton		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
121043412Snewton		return ENOSYS;
121143412Snewton	}
121243412Snewton
121343412Snewton	if ((error = copyin(sup, skp, sasize)) != 0) {
121443412Snewton		DPRINTF(("ti_ioctl: error copying in socket data\n"));
121543412Snewton		return error;
121643412Snewton	}
121743412Snewton
121843412Snewton	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
121943412Snewton		DPRINTF(("ti_ioctl: error copying in socket size\n"));
122043412Snewton		return error;
122143412Snewton	}
122243412Snewton
122343412Snewton	switch (st->s_family) {
122443412Snewton	case AF_INET:
122543412Snewton		sockaddr_to_netaddr_in(&sc, &sain);
122643412Snewton		skb.len = sasize;
122743412Snewton		break;
122843412Snewton
122943412Snewton	case AF_LOCAL:
123043412Snewton		sockaddr_to_netaddr_un(&sc, &saun);
123143412Snewton		skb.len = sasize + 4;
123243412Snewton		break;
123343412Snewton
123443412Snewton	default:
123543412Snewton		return ENOSYS;
123643412Snewton	}
123743412Snewton
123843412Snewton
123943412Snewton	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
124043412Snewton		DPRINTF(("ti_ioctl: error copying out socket data\n"));
124143412Snewton		return error;
124243412Snewton	}
124343412Snewton
124443412Snewton
124543412Snewton	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
124643412Snewton		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
124743412Snewton		return error;
124843412Snewton	}
124943412Snewton
125043412Snewton	return error;
125143412Snewton}
125243412Snewton
125343412Snewton
125443412Snewton
125543412Snewton
125643412Snewtonstatic int
125783366Sjuliani_nread(fp, td, retval, fd, cmd, dat)
125843412Snewton	struct file *fp;
125983366Sjulian	struct thread *td;
126043412Snewton	register_t *retval;
126143412Snewton	int fd;
126243412Snewton	u_long cmd;
126343412Snewton	caddr_t dat;
126443412Snewton{
126543412Snewton	int error;
126643412Snewton	int nread = 0;
126743412Snewton
126843412Snewton	/*
126943412Snewton	 * We are supposed to return the message length in nread, and the
127043412Snewton	 * number of messages in retval. We don't have the notion of number
127143412Snewton	 * of stream messages, so we just find out if we have any bytes waiting
127243412Snewton	 * for us, and if we do, then we assume that we have at least one
127343412Snewton	 * message waiting for us.
127443412Snewton	 */
127583366Sjulian	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0)
127643412Snewton		return error;
127743412Snewton
127843412Snewton	if (nread != 0)
127943412Snewton		*retval = 1;
128043412Snewton	else
128143412Snewton		*retval = 0;
128243412Snewton
128343412Snewton	return copyout(&nread, dat, sizeof(nread));
128443412Snewton}
128543412Snewton
128643412Snewtonstatic int
128783366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat)
128843412Snewton	struct file *fp;
128983366Sjulian	struct thread *td;
129043412Snewton	register_t *retval;
129143412Snewton	int fd;
129243412Snewton	u_long cmd;
129343412Snewton	caddr_t dat;
129443412Snewton{
129543412Snewton	/*
129643412Snewton	 * Major hack again here. We assume that we are using this to
129743412Snewton	 * implement accept(2). If that is the case, we have already
129843412Snewton	 * called accept, and we have stored the file descriptor in
129943412Snewton	 * afd. We find the file descriptor that the code wants to use
130043412Snewton	 * in fd insert, and then we dup2() our accepted file descriptor
130143412Snewton	 * to it.
130243412Snewton	 */
130343412Snewton	int error;
130443412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
130543412Snewton	struct svr4_strfdinsert fdi;
130643412Snewton	struct dup2_args d2p;
130743412Snewton	struct close_args clp;
130843412Snewton
130943412Snewton	if (st == NULL) {
131043412Snewton		DPRINTF(("fdinsert: bad file type\n"));
131143412Snewton		return EINVAL;
131243412Snewton	}
131343412Snewton
131443412Snewton	if (st->s_afd == -1) {
131543412Snewton		DPRINTF(("fdinsert: accept fd not found\n"));
131643412Snewton		return ENOENT;
131743412Snewton	}
131843412Snewton
131943412Snewton	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
132043412Snewton		DPRINTF(("fdinsert: copyin failed %d\n", error));
132143412Snewton		return error;
132243412Snewton	}
132343412Snewton
132443412Snewton	SCARG(&d2p, from) = st->s_afd;
132543412Snewton	SCARG(&d2p, to) = fdi.fd;
132643412Snewton
132783366Sjulian	if ((error = dup2(td, &d2p)) != 0) {
132843412Snewton		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
132943412Snewton		    st->s_afd, fdi.fd, error));
133043412Snewton		return error;
133143412Snewton	}
133243412Snewton
133343412Snewton	SCARG(&clp, fd) = st->s_afd;
133443412Snewton
133583366Sjulian	if ((error = close(td, &clp)) != 0) {
133643412Snewton		DPRINTF(("fdinsert: close(%d) failed %d\n",
133743412Snewton		    st->s_afd, error));
133843412Snewton		return error;
133943412Snewton	}
134043412Snewton
134143412Snewton	st->s_afd = -1;
134243412Snewton
134343412Snewton	*retval = 0;
134443412Snewton	return 0;
134543412Snewton}
134643412Snewton
134743412Snewton
134843412Snewtonstatic int
134983366Sjulian_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
135043412Snewton	struct file *fp;
135183366Sjulian	struct thread *td;
135243412Snewton	register_t *retval;
135343412Snewton	int fd;
135443412Snewton	u_long cmd;
135543412Snewton	caddr_t dat;
135643412Snewton{
135743412Snewton	struct mkfifo_args ap;
135843412Snewton
135943412Snewton	/*
136043412Snewton	 * This is a supposed to be a kernel and library only ioctl.
136143412Snewton	 * It gets called before ti_bind, when we have a unix
136243412Snewton	 * socket, to physically create the socket transport and
136343412Snewton	 * ``reserve'' it. I don't know how this get reserved inside
136443412Snewton	 * the kernel, but we are going to create it nevertheless.
136543412Snewton	 */
136643412Snewton	SCARG(&ap, path) = dat;
136743412Snewton	SCARG(&ap, mode) = S_IFIFO;
136843412Snewton
136983366Sjulian	return mkfifo(td, &ap);
137043412Snewton}
137143412Snewton
137243412Snewtonstatic int
137383366Sjulian_i_rele_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 unlink_args ap;
138243412Snewton
138343412Snewton	/*
138443412Snewton	 * This is a supposed to be a kernel and library only ioctl.
138543412Snewton	 * I guess it is supposed to release the socket.
138643412Snewton	 */
138743412Snewton	SCARG(&ap, path) = dat;
138843412Snewton
138983366Sjulian	return unlink(td, &ap);
139043412Snewton}
139143412Snewton
139243412Snewtonstatic int
139383366Sjuliani_str(fp, td, retval, fd, cmd, dat)
139443412Snewton	struct file *fp;
139583366Sjulian	struct thread *td;
139643412Snewton	register_t *retval;
139743412Snewton	int fd;
139843412Snewton	u_long cmd;
139943412Snewton	caddr_t dat;
140043412Snewton{
140143412Snewton	int			 error;
140243412Snewton	struct svr4_strioctl	 ioc;
140343412Snewton
140443412Snewton	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
140543412Snewton		return error;
140643412Snewton
140743412Snewton#ifdef DEBUG_SVR4
140843412Snewton	if ((error = show_ioc(">", &ioc)) != 0)
140943412Snewton		return error;
141043412Snewton#endif /* DEBUG_SVR4 */
141143412Snewton
141243412Snewton	switch (ioc.cmd & 0xff00) {
141343412Snewton	case SVR4_SIMOD:
141483366Sjulian		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
141543412Snewton			return error;
141643412Snewton		break;
141743412Snewton
141843412Snewton	case SVR4_TIMOD:
141983366Sjulian		if ((error = timod(fp, fd, &ioc, td)) != 0)
142043412Snewton			return error;
142143412Snewton		break;
142243412Snewton
142343412Snewton	default:
142443412Snewton		DPRINTF(("Unimplemented module %c %ld\n",
142543412Snewton			 (char) (cmd >> 8), cmd & 0xff));
142643412Snewton		return 0;
142743412Snewton	}
142843412Snewton
142943412Snewton#ifdef DEBUG_SVR4
143043412Snewton	if ((error = show_ioc("<", &ioc)) != 0)
143143412Snewton		return error;
143243412Snewton#endif /* DEBUG_SVR4 */
143343412Snewton	return copyout(&ioc, dat, sizeof(ioc));
143443412Snewton}
143543412Snewton
143643412Snewtonstatic int
143783366Sjuliani_setsig(fp, td, retval, fd, cmd, dat)
143843412Snewton	struct file *fp;
143983366Sjulian	struct thread *td;
144043412Snewton	register_t *retval;
144143412Snewton	int fd;
144243412Snewton	u_long cmd;
144343412Snewton	caddr_t dat;
144443412Snewton{
144543412Snewton	/*
144643412Snewton	 * This is the best we can do for now; we cannot generate
144743412Snewton	 * signals only for specific events so the signal mask gets
144843412Snewton	 * ignored; we save it just to pass it to a possible I_GETSIG...
144943412Snewton	 *
145043412Snewton	 * We alse have to fix the O_ASYNC fcntl bit, so the
145143412Snewton	 * process will get SIGPOLLs.
145243412Snewton	 */
145343412Snewton	struct fcntl_args fa;
145443412Snewton	int error;
145543412Snewton	register_t oflags, flags;
145643412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
145743412Snewton
145843412Snewton	if (st == NULL) {
145943412Snewton		DPRINTF(("i_setsig: bad file descriptor\n"));
146043412Snewton		return EINVAL;
146143412Snewton	}
146243412Snewton	/* get old status flags */
146343412Snewton	SCARG(&fa, fd) = fd;
146443412Snewton	SCARG(&fa, cmd) = F_GETFL;
146583366Sjulian	if ((error = fcntl(td, &fa)) != 0)
146643412Snewton		return error;
146743412Snewton
146883366Sjulian	oflags = td->td_retval[0];
146943412Snewton
147043412Snewton	/* update the flags */
147143412Snewton	if (dat != NULL) {
147243412Snewton		int mask;
147343412Snewton
147443412Snewton		flags = oflags | O_ASYNC;
147543412Snewton		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
147643412Snewton			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
147743412Snewton			  return error;
147843412Snewton		}
147943412Snewton		if (mask & SVR4_S_ALLMASK) {
148043412Snewton			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
148143412Snewton			  return EINVAL;
148243412Snewton		}
148343412Snewton		st->s_eventmask = mask;
148443412Snewton	}
148543412Snewton	else {
148643412Snewton		flags = oflags & ~O_ASYNC;
148743412Snewton		st->s_eventmask = 0;
148843412Snewton	}
148943412Snewton
149043412Snewton	/* set the new flags, if changed */
149143412Snewton	if (flags != oflags) {
149243412Snewton		SCARG(&fa, cmd) = F_SETFL;
149343412Snewton		SCARG(&fa, arg) = (long) flags;
149483366Sjulian		if ((error = fcntl(td, &fa)) != 0)
149543412Snewton			  return error;
149683366Sjulian		flags = td->td_retval[0];
149743412Snewton	}
149843412Snewton
149943412Snewton	/* set up SIGIO receiver if needed */
150043412Snewton	if (dat != NULL) {
150143412Snewton		SCARG(&fa, cmd) = F_SETOWN;
150283366Sjulian		SCARG(&fa, arg) = (long) td->td_proc->p_pid;
150383366Sjulian		return fcntl(td, &fa);
150443412Snewton	}
150543412Snewton	return 0;
150643412Snewton}
150743412Snewton
150843412Snewtonstatic int
150983366Sjuliani_getsig(fp, td, retval, fd, cmd, dat)
151043412Snewton	struct file *fp;
151183366Sjulian	struct thread *td;
151243412Snewton	register_t *retval;
151343412Snewton	int fd;
151443412Snewton	u_long cmd;
151543412Snewton	caddr_t dat;
151643412Snewton{
151743412Snewton	int error;
151843412Snewton
151943412Snewton	if (dat != NULL) {
152043412Snewton		struct svr4_strm *st = svr4_stream_get(fp);
152143412Snewton
152243412Snewton		if (st == NULL) {
152343412Snewton			DPRINTF(("i_getsig: bad file descriptor\n"));
152443412Snewton			return EINVAL;
152543412Snewton		}
152643412Snewton		if ((error = copyout(&st->s_eventmask, dat,
152743412Snewton				     sizeof(st->s_eventmask))) != 0) {
152843412Snewton			DPRINTF(("i_getsig: bad eventmask pointer\n"));
152943412Snewton			return error;
153043412Snewton		}
153143412Snewton	}
153243412Snewton	return 0;
153343412Snewton}
153443412Snewton
153543412Snewtonint
153683366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
153743412Snewton	struct file *fp;
153883366Sjulian	struct thread *td;
153943412Snewton	register_t *retval;
154043412Snewton	int fd;
154143412Snewton	u_long cmd;
154243412Snewton	caddr_t dat;
154343412Snewton{
154443412Snewton	*retval = 0;
154543412Snewton
154643412Snewton	/*
154743412Snewton	 * All the following stuff assumes "sockmod" is pushed...
154843412Snewton	 */
154943412Snewton	switch (cmd) {
155043412Snewton	case SVR4_I_NREAD:
155143412Snewton		DPRINTF(("I_NREAD\n"));
155283366Sjulian		return i_nread(fp, td, retval, fd, cmd, dat);
155343412Snewton
155443412Snewton	case SVR4_I_PUSH:
155580114Sassar		DPRINTF(("I_PUSH %p\n", dat));
155643412Snewton#if defined(DEBUG_SVR4)
155780114Sassar		show_strbuf((struct svr4_strbuf *)dat);
155843412Snewton#endif
155943412Snewton		return 0;
156043412Snewton
156143412Snewton	case SVR4_I_POP:
156243412Snewton		DPRINTF(("I_POP\n"));
156343412Snewton		return 0;
156443412Snewton
156543412Snewton	case SVR4_I_LOOK:
156643412Snewton		DPRINTF(("I_LOOK\n"));
156743412Snewton		return 0;
156843412Snewton
156943412Snewton	case SVR4_I_FLUSH:
157043412Snewton		DPRINTF(("I_FLUSH\n"));
157143412Snewton		return 0;
157243412Snewton
157343412Snewton	case SVR4_I_SRDOPT:
157443412Snewton		DPRINTF(("I_SRDOPT\n"));
157543412Snewton		return 0;
157643412Snewton
157743412Snewton	case SVR4_I_GRDOPT:
157843412Snewton		DPRINTF(("I_GRDOPT\n"));
157943412Snewton		return 0;
158043412Snewton
158143412Snewton	case SVR4_I_STR:
158243412Snewton		DPRINTF(("I_STR\n"));
158383366Sjulian		return i_str(fp, td, retval, fd, cmd, dat);
158443412Snewton
158543412Snewton	case SVR4_I_SETSIG:
158643412Snewton		DPRINTF(("I_SETSIG\n"));
158783366Sjulian		return i_setsig(fp, td, retval, fd, cmd, dat);
158843412Snewton
158943412Snewton	case SVR4_I_GETSIG:
159043412Snewton	        DPRINTF(("I_GETSIG\n"));
159183366Sjulian		return i_getsig(fp, td, retval, fd, cmd, dat);
159243412Snewton
159343412Snewton	case SVR4_I_FIND:
159443412Snewton		DPRINTF(("I_FIND\n"));
159543412Snewton		/*
159643412Snewton		 * Here we are not pushing modules really, we just
159743412Snewton		 * pretend all are present
159843412Snewton		 */
159943412Snewton		*retval = 0;
160043412Snewton		return 0;
160143412Snewton
160243412Snewton	case SVR4_I_LINK:
160343412Snewton		DPRINTF(("I_LINK\n"));
160443412Snewton		return 0;
160543412Snewton
160643412Snewton	case SVR4_I_UNLINK:
160743412Snewton		DPRINTF(("I_UNLINK\n"));
160843412Snewton		return 0;
160943412Snewton
161043412Snewton	case SVR4_I_ERECVFD:
161143412Snewton		DPRINTF(("I_ERECVFD\n"));
161243412Snewton		return 0;
161343412Snewton
161443412Snewton	case SVR4_I_PEEK:
161543412Snewton		DPRINTF(("I_PEEK\n"));
161643412Snewton		return 0;
161743412Snewton
161843412Snewton	case SVR4_I_FDINSERT:
161943412Snewton		DPRINTF(("I_FDINSERT\n"));
162083366Sjulian		return i_fdinsert(fp, td, retval, fd, cmd, dat);
162143412Snewton
162243412Snewton	case SVR4_I_SENDFD:
162343412Snewton		DPRINTF(("I_SENDFD\n"));
162443412Snewton		return 0;
162543412Snewton
162643412Snewton	case SVR4_I_RECVFD:
162743412Snewton		DPRINTF(("I_RECVFD\n"));
162843412Snewton		return 0;
162943412Snewton
163043412Snewton	case SVR4_I_SWROPT:
163143412Snewton		DPRINTF(("I_SWROPT\n"));
163243412Snewton		return 0;
163343412Snewton
163443412Snewton	case SVR4_I_GWROPT:
163543412Snewton		DPRINTF(("I_GWROPT\n"));
163643412Snewton		return 0;
163743412Snewton
163843412Snewton	case SVR4_I_LIST:
163943412Snewton		DPRINTF(("I_LIST\n"));
164043412Snewton		return 0;
164143412Snewton
164243412Snewton	case SVR4_I_PLINK:
164343412Snewton		DPRINTF(("I_PLINK\n"));
164443412Snewton		return 0;
164543412Snewton
164643412Snewton	case SVR4_I_PUNLINK:
164743412Snewton		DPRINTF(("I_PUNLINK\n"));
164843412Snewton		return 0;
164943412Snewton
165043412Snewton	case SVR4_I_SETEV:
165143412Snewton		DPRINTF(("I_SETEV\n"));
165243412Snewton		return 0;
165343412Snewton
165443412Snewton	case SVR4_I_GETEV:
165543412Snewton		DPRINTF(("I_GETEV\n"));
165643412Snewton		return 0;
165743412Snewton
165843412Snewton	case SVR4_I_STREV:
165943412Snewton		DPRINTF(("I_STREV\n"));
166043412Snewton		return 0;
166143412Snewton
166243412Snewton	case SVR4_I_UNSTREV:
166343412Snewton		DPRINTF(("I_UNSTREV\n"));
166443412Snewton		return 0;
166543412Snewton
166643412Snewton	case SVR4_I_FLUSHBAND:
166743412Snewton		DPRINTF(("I_FLUSHBAND\n"));
166843412Snewton		return 0;
166943412Snewton
167043412Snewton	case SVR4_I_CKBAND:
167143412Snewton		DPRINTF(("I_CKBAND\n"));
167243412Snewton		return 0;
167343412Snewton
167443412Snewton	case SVR4_I_GETBAND:
167543412Snewton		DPRINTF(("I_GETBANK\n"));
167643412Snewton		return 0;
167743412Snewton
167843412Snewton	case SVR4_I_ATMARK:
167943412Snewton		DPRINTF(("I_ATMARK\n"));
168043412Snewton		return 0;
168143412Snewton
168243412Snewton	case SVR4_I_SETCLTIME:
168343412Snewton		DPRINTF(("I_SETCLTIME\n"));
168443412Snewton		return 0;
168543412Snewton
168643412Snewton	case SVR4_I_GETCLTIME:
168743412Snewton		DPRINTF(("I_GETCLTIME\n"));
168843412Snewton		return 0;
168943412Snewton
169043412Snewton	case SVR4_I_CANPUT:
169143412Snewton		DPRINTF(("I_CANPUT\n"));
169243412Snewton		return 0;
169343412Snewton
169443412Snewton	case SVR4__I_BIND_RSVD:
169543412Snewton		DPRINTF(("_I_BIND_RSVD\n"));
169683366Sjulian		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
169743412Snewton
169843412Snewton	case SVR4__I_RELE_RSVD:
169943412Snewton		DPRINTF(("_I_RELE_RSVD\n"));
170083366Sjulian		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
170143412Snewton
170243412Snewton	default:
170343412Snewton		DPRINTF(("unimpl cmd = %lx\n", cmd));
170443412Snewton		break;
170543412Snewton	}
170643412Snewton
170743412Snewton	return 0;
170843412Snewton}
170943412Snewton
171043412Snewton
171143412Snewton
171243412Snewtonint
171383366Sjuliansvr4_sys_putmsg(td, uap)
171483366Sjulian	register struct thread *td;
171543412Snewton	struct svr4_sys_putmsg_args *uap;
171643412Snewton{
171789306Salfred	struct file     *fp;
171889306Salfred	int error;
171989306Salfred
172089319Salfred	if ((error = fget(td, uap->fd, &fp)) != 0) {
172189306Salfred#ifdef DEBUG_SVR4
172289306Salfred	        uprintf("putmsg: bad fp\n");
172389306Salfred#endif
172489306Salfred		return EBADF;
172589306Salfred	}
172689306Salfred	error = svr4_do_putmsg(td, uap, fp);
172789306Salfred	fdrop(fp, td);
172889306Salfred	return (error);
172989306Salfred}
173089306Salfred
173189306Salfredstatic int
173289306Salfredsvr4_do_putmsg(td, uap, fp)
173389306Salfred	struct thread *td;
173489306Salfred	struct svr4_sys_putmsg_args *uap;
173543412Snewton	struct file	*fp;
173689306Salfred{
173743412Snewton	struct svr4_strbuf dat, ctl;
173843412Snewton	struct svr4_strmcmd sc;
173943412Snewton	struct sockaddr_in sain;
174043412Snewton	struct sockaddr_un saun;
174143412Snewton	void *skp, *sup;
174243412Snewton	int sasize, *retval;
174343412Snewton	struct svr4_strm *st;
174443412Snewton	int error;
174543412Snewton	caddr_t sg;
174643412Snewton
174783366Sjulian	retval = td->td_retval;
174854493Snewton
174943412Snewton#ifdef DEBUG_SVR4
175043412Snewton	show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
175143412Snewton		 SCARG(uap, dat), SCARG(uap, flags));
175243412Snewton#endif /* DEBUG_SVR4 */
175343412Snewton
175489306Salfred	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
175543412Snewton
175643412Snewton	if (SCARG(uap, ctl) != NULL) {
175743412Snewton	  if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
175843412Snewton#ifdef DEBUG_SVR4
175943412Snewton	    uprintf("putmsg: copyin(): %d\n", error);
176043412Snewton#endif
176143412Snewton	    return error;
176243412Snewton	  }
176343412Snewton	}
176443412Snewton	else
176543412Snewton		ctl.len = -1;
176643412Snewton
176743412Snewton	if (SCARG(uap, dat) != NULL) {
176843412Snewton	  if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
176943412Snewton#ifdef DEBUG_SVR4
177043412Snewton	    uprintf("putmsg: copyin(): %d (2)\n", error);
177143412Snewton#endif
177243412Snewton	    return error;
177343412Snewton	  }
177443412Snewton	}
177543412Snewton	else
177643412Snewton		dat.len = -1;
177743412Snewton
177843412Snewton	/*
177943412Snewton	 * Only for sockets for now.
178043412Snewton	 */
178143412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
178243412Snewton		DPRINTF(("putmsg: bad file type\n"));
178343412Snewton		return EINVAL;
178443412Snewton	}
178543412Snewton
178643412Snewton	if (ctl.len > sizeof(sc)) {
178743412Snewton		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
178843412Snewton			 sizeof(struct svr4_strmcmd)));
178943412Snewton		return EINVAL;
179043412Snewton	}
179143412Snewton
179243412Snewton	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
179343412Snewton		return error;
179443412Snewton
179543412Snewton	switch (st->s_family) {
179643412Snewton	case AF_INET:
179743412Snewton	        if (sc.len != sizeof(sain)) {
179843412Snewton		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
179943412Snewton			        struct write_args wa;
180043412Snewton
180143412Snewton				/* Solaris seems to use sc.cmd = 3 to
180243412Snewton				 * send "expedited" data.  telnet uses
180343412Snewton				 * this for options processing, sending EOF,
180443412Snewton				 * etc.  I'm sure other things use it too.
180543412Snewton				 * I don't have any documentation
180643412Snewton				 * on it, so I'm making a guess that this
180743412Snewton				 * is how it works. newton@atdot.dotat.org XXX
180843412Snewton				 */
180951844Speter				DPRINTF(("sending expedited data ??\n"));
181043412Snewton				SCARG(&wa, fd) = SCARG(uap, fd);
181143412Snewton				SCARG(&wa, buf) = dat.buf;
181243412Snewton				SCARG(&wa, nbyte) = dat.len;
181383366Sjulian				return write(td, &wa);
181443412Snewton			}
181543412Snewton	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
181643412Snewton	                return EINVAL;
181743412Snewton	        }
181843412Snewton	        netaddr_to_sockaddr_in(&sain, &sc);
181943412Snewton	        skp = &sain;
182043412Snewton	        sasize = sizeof(sain);
182143412Snewton	        error = sain.sin_family != st->s_family;
182243412Snewton		break;
182343412Snewton
182443412Snewton	case AF_LOCAL:
182543412Snewton		if (ctl.len == 8) {
182643412Snewton			/* We are doing an accept; succeed */
182743412Snewton			DPRINTF(("putmsg: Do nothing\n"));
182843412Snewton			*retval = 0;
182943412Snewton			return 0;
183043412Snewton		}
183143412Snewton		else {
183243412Snewton			/* Maybe we've been given a device/inode pair */
183349267Snewton			udev_t *dev = SVR4_ADDROF(&sc);
183443412Snewton			ino_t *ino = (ino_t *) &dev[1];
183583366Sjulian			skp = svr4_find_socket(td, fp, *dev, *ino);
183643412Snewton			if (skp == NULL) {
183743412Snewton				skp = &saun;
183843412Snewton				/* I guess we have it by name */
183943412Snewton				netaddr_to_sockaddr_un(skp, &sc);
184043412Snewton			}
184143412Snewton			sasize = sizeof(saun);
184243412Snewton		}
184343412Snewton		break;
184443412Snewton
184543412Snewton	default:
184643412Snewton		DPRINTF(("putmsg: Unsupported address family %d\n",
184743412Snewton			 st->s_family));
184843412Snewton		return ENOSYS;
184943412Snewton	}
185043412Snewton
185143412Snewton	sg = stackgap_init();
185243412Snewton	sup = stackgap_alloc(&sg, sasize);
185343412Snewton
185443412Snewton	if ((error = copyout(skp, sup, sasize)) != 0)
185543412Snewton		return error;
185643412Snewton
185743412Snewton	switch (st->s_cmd = sc.cmd) {
185843412Snewton	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
185943412Snewton		{
186043412Snewton			struct connect_args co;
186143412Snewton
186243412Snewton			SCARG(&co, s) = SCARG(uap, fd);
186343412Snewton			SCARG(&co, name) = (void *) sup;
186443412Snewton			SCARG(&co, namelen) = (int) sasize;
186543412Snewton
186683366Sjulian			return connect(td, &co);
186743412Snewton		}
186843412Snewton
186943412Snewton	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
187043412Snewton		{
187143412Snewton			struct msghdr msg;
187243412Snewton			struct iovec aiov;
187343412Snewton
187443412Snewton			msg.msg_name = (caddr_t) sup;
187543412Snewton			msg.msg_namelen = sasize;
187643412Snewton			msg.msg_iov = &aiov;
187743412Snewton			msg.msg_iovlen = 1;
187843412Snewton			msg.msg_control = 0;
187943412Snewton			msg.msg_flags = 0;
188043412Snewton			aiov.iov_base = dat.buf;
188143412Snewton			aiov.iov_len = dat.len;
188243412Snewton#if 0
188343412Snewton			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
188483366Sjulian					      uio, 0, 0, 0, uio->uio_td);
188543412Snewton#endif
188683366Sjulian			error = svr4_sendit(td, SCARG(uap, fd), &msg,
188743412Snewton				       SCARG(uap, flags));
188843412Snewton			DPRINTF(("sendto_request error: %d\n", error));
188943412Snewton			*retval = 0;
189043412Snewton			return error;
189143412Snewton		}
189243412Snewton
189343412Snewton	default:
189443412Snewton		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
189543412Snewton		return ENOSYS;
189643412Snewton	}
189743412Snewton}
189843412Snewton
189943412Snewtonint
190089308Salfredsvr4_sys_getmsg(td, uap)
190189308Salfred	struct thread *td;
190289306Salfred	struct svr4_sys_getmsg_args *uap;
190389306Salfred{
190489306Salfred	struct file     *fp;
190589306Salfred	int error;
190689306Salfred
190789319Salfred	if ((error = fget(td, uap->fd, &fp)) != 0) {
190889306Salfred#ifdef DEBUG_SVR4
190989306Salfred	        uprintf("getmsg: bad fp\n");
191089306Salfred#endif
191189306Salfred		return EBADF;
191289306Salfred	}
191389308Salfred	error = svr4_do_getmsg(td, uap, fp);
191489306Salfred	fdrop(fp, td);
191589306Salfred	return (error);
191689306Salfred}
191789306Salfred
191889306Salfredint
191983366Sjuliansvr4_sys_getmsg(td, uap)
192083366Sjulian	register struct thread *td;
192143412Snewton	struct svr4_sys_getmsg_args *uap;
192289306Salfred	struct file *fp;
192343412Snewton{
192443412Snewton	struct getpeername_args ga;
192543412Snewton	struct accept_args aa;
192643412Snewton	struct svr4_strbuf dat, ctl;
192743412Snewton	struct svr4_strmcmd sc;
192843412Snewton	int error, *retval;
192943412Snewton	struct msghdr msg;
193043412Snewton	struct iovec aiov;
193143412Snewton	struct sockaddr_in sain;
193243412Snewton	struct sockaddr_un saun;
193343412Snewton	void *skp, *sup;
193443412Snewton	int sasize;
193543412Snewton	struct svr4_strm *st;
193643412Snewton	int *flen;
193743412Snewton	int fl;
193843412Snewton	caddr_t sg;
193943412Snewton
194083366Sjulian	retval = td->td_retval;
194154493Snewton
194289306Salfred	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
194343412Snewton
194443412Snewton	memset(&sc, 0, sizeof(sc));
194543412Snewton
194643412Snewton#ifdef DEBUG_SVR4
194743412Snewton	show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
194843412Snewton		 SCARG(uap, dat), 0);
194943412Snewton#endif /* DEBUG_SVR4 */
195043412Snewton
195143412Snewton	if (SCARG(uap, ctl) != NULL) {
195243412Snewton		if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
195343412Snewton			return error;
195443412Snewton	}
195543412Snewton	else {
195643412Snewton		ctl.len = -1;
195743412Snewton		ctl.maxlen = 0;
195843412Snewton	}
195943412Snewton
196043412Snewton	if (SCARG(uap, dat) != NULL) {
196143412Snewton	    	if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
196243412Snewton			return error;
196343412Snewton	}
196443412Snewton	else {
196543412Snewton		dat.len = -1;
196643412Snewton		dat.maxlen = 0;
196743412Snewton	}
196843412Snewton
196943412Snewton	/*
197043412Snewton	 * Only for sockets for now.
197143412Snewton	 */
197243412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
197343412Snewton		DPRINTF(("getmsg: bad file type\n"));
197443412Snewton		return EINVAL;
197543412Snewton	}
197643412Snewton
197743412Snewton	if (ctl.maxlen == -1 || dat.maxlen == -1) {
197843412Snewton		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
197943412Snewton		return ENOSYS;
198043412Snewton	}
198143412Snewton
198243412Snewton	switch (st->s_family) {
198343412Snewton	case AF_INET:
198443412Snewton		skp = &sain;
198543412Snewton		sasize = sizeof(sain);
198643412Snewton		break;
198743412Snewton
198843412Snewton	case AF_LOCAL:
198943412Snewton		skp = &saun;
199043412Snewton		sasize = sizeof(saun);
199143412Snewton		break;
199243412Snewton
199343412Snewton	default:
199443412Snewton		DPRINTF(("getmsg: Unsupported address family %d\n",
199543412Snewton			 st->s_family));
199643412Snewton		return ENOSYS;
199743412Snewton	}
199843412Snewton
199943412Snewton	sg = stackgap_init();
200043412Snewton	sup = stackgap_alloc(&sg, sasize);
200143412Snewton	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
200243412Snewton
200343412Snewton	fl = sasize;
200443412Snewton	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
200543412Snewton		return error;
200643412Snewton
200743412Snewton	switch (st->s_cmd) {
200843412Snewton	case SVR4_TI_CONNECT_REQUEST:
200943412Snewton		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
201043412Snewton		/*
201143412Snewton		 * We do the connect in one step, so the putmsg should
201243412Snewton		 * have gotten the error.
201343412Snewton		 */
201443412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
201543412Snewton		sc.len = 0;
201643412Snewton
201743412Snewton		ctl.len = 8;
201843412Snewton		dat.len = -1;
201943412Snewton		fl = 1;
202043412Snewton		st->s_cmd = sc.cmd;
202143412Snewton		break;
202243412Snewton
202343412Snewton	case SVR4_TI_OK_REPLY:
202443412Snewton		DPRINTF(("getmsg: TI_OK_REPLY\n"));
202543412Snewton		/*
202643412Snewton		 * We are immediately after a connect reply, so we send
202743412Snewton		 * a connect verification.
202843412Snewton		 */
202943412Snewton
203043412Snewton		SCARG(&ga, fdes) = SCARG(uap, fd);
203143412Snewton		SCARG(&ga, asa) = (void *) sup;
203243412Snewton		SCARG(&ga, alen) = flen;
203343412Snewton
203483366Sjulian		if ((error = getpeername(td, &ga)) != 0) {
203543412Snewton			DPRINTF(("getmsg: getpeername failed %d\n", error));
203643412Snewton			return error;
203743412Snewton		}
203843412Snewton
203943412Snewton		if ((error = copyin(sup, skp, sasize)) != 0)
204043412Snewton			return error;
204143412Snewton
204243412Snewton		sc.cmd = SVR4_TI_CONNECT_REPLY;
204343412Snewton		sc.pad[0] = 0x4;
204443412Snewton		sc.offs = 0x18;
204543412Snewton		sc.pad[1] = 0x14;
204643412Snewton		sc.pad[2] = 0x04000402;
204743412Snewton
204843412Snewton		switch (st->s_family) {
204943412Snewton		case AF_INET:
205043412Snewton			sc.len = sasize;
205143412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
205243412Snewton			break;
205343412Snewton
205443412Snewton		case AF_LOCAL:
205543412Snewton			sc.len = sasize + 4;
205643412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
205743412Snewton			break;
205843412Snewton
205943412Snewton		default:
206043412Snewton			return ENOSYS;
206143412Snewton		}
206243412Snewton
206343412Snewton		ctl.len = 40;
206443412Snewton		dat.len = -1;
206543412Snewton		fl = 0;
206643412Snewton		st->s_cmd = sc.cmd;
206743412Snewton		break;
206843412Snewton
206943412Snewton	case SVR4_TI__ACCEPT_OK:
207043412Snewton		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
207143412Snewton		/*
207243412Snewton		 * We do the connect in one step, so the putmsg should
207343412Snewton		 * have gotten the error.
207443412Snewton		 */
207543412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
207643412Snewton		sc.len = 1;
207743412Snewton
207843412Snewton		ctl.len = 8;
207943412Snewton		dat.len = -1;
208043412Snewton		fl = 1;
208143412Snewton		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
208243412Snewton		break;
208343412Snewton
208443412Snewton	case SVR4_TI__ACCEPT_WAIT:
208543412Snewton		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
208643412Snewton		/*
208743412Snewton		 * We are after a listen, so we try to accept...
208843412Snewton		 */
208943412Snewton		SCARG(&aa, s) = SCARG(uap, fd);
209043412Snewton		SCARG(&aa, name) = (void *) sup;
209143412Snewton		SCARG(&aa, anamelen) = flen;
209243412Snewton
209383366Sjulian		if ((error = accept(td, &aa)) != 0) {
209443412Snewton			DPRINTF(("getmsg: accept failed %d\n", error));
209543412Snewton			return error;
209643412Snewton		}
209743412Snewton
209843412Snewton		st->s_afd = *retval;
209943412Snewton
210043412Snewton		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
210143412Snewton
210243412Snewton		if ((error = copyin(sup, skp, sasize)) != 0)
210343412Snewton			return error;
210443412Snewton
210543412Snewton		sc.cmd = SVR4_TI_ACCEPT_REPLY;
210643412Snewton		sc.offs = 0x18;
210743412Snewton		sc.pad[0] = 0x0;
210843412Snewton
210943412Snewton		switch (st->s_family) {
211043412Snewton		case AF_INET:
211143412Snewton			sc.pad[1] = 0x28;
211243412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
211343412Snewton			ctl.len = 40;
211443412Snewton			sc.len = sasize;
211543412Snewton			break;
211643412Snewton
211743412Snewton		case AF_LOCAL:
211843412Snewton			sc.pad[1] = 0x00010000;
211943412Snewton			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
212043412Snewton			sc.pad[3] = 0x00010000;
212143412Snewton			ctl.len = 134;
212243412Snewton			sc.len = sasize + 4;
212343412Snewton			break;
212443412Snewton
212543412Snewton		default:
212643412Snewton			return ENOSYS;
212743412Snewton		}
212843412Snewton
212943412Snewton		dat.len = -1;
213043412Snewton		fl = 0;
213143412Snewton		st->s_cmd = SVR4_TI__ACCEPT_OK;
213243412Snewton		break;
213343412Snewton
213443412Snewton	case SVR4_TI_SENDTO_REQUEST:
213543412Snewton		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
213643412Snewton		if (ctl.maxlen > 36 && ctl.len < 36)
213743412Snewton		    ctl.len = 36;
213843412Snewton
213943412Snewton		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
214043412Snewton			return error;
214143412Snewton
214243412Snewton		switch (st->s_family) {
214343412Snewton		case AF_INET:
214443412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
214543412Snewton			break;
214643412Snewton
214743412Snewton		case AF_LOCAL:
214843412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
214943412Snewton			break;
215043412Snewton
215143412Snewton		default:
215243412Snewton			return ENOSYS;
215343412Snewton		}
215443412Snewton
215543412Snewton		msg.msg_name = (caddr_t) sup;
215643412Snewton		msg.msg_namelen = sasize;
215743412Snewton		msg.msg_iov = &aiov;
215843412Snewton		msg.msg_iovlen = 1;
215943412Snewton		msg.msg_control = 0;
216043412Snewton		aiov.iov_base = dat.buf;
216143412Snewton		aiov.iov_len = dat.maxlen;
216243412Snewton		msg.msg_flags = 0;
216343412Snewton
216483366Sjulian		error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen);
216543412Snewton
216643412Snewton		if (error) {
216743412Snewton			DPRINTF(("getmsg: recvit failed %d\n", error));
216843412Snewton			return error;
216943412Snewton		}
217043412Snewton
217143412Snewton		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
217243412Snewton			return error;
217343412Snewton
217443412Snewton		sc.cmd = SVR4_TI_RECVFROM_IND;
217543412Snewton
217643412Snewton		switch (st->s_family) {
217743412Snewton		case AF_INET:
217843412Snewton			sc.len = sasize;
217943412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
218043412Snewton			break;
218143412Snewton
218243412Snewton		case AF_LOCAL:
218343412Snewton			sc.len = sasize + 4;
218443412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
218543412Snewton			break;
218643412Snewton
218743412Snewton		default:
218843412Snewton			return ENOSYS;
218943412Snewton		}
219043412Snewton
219143412Snewton		dat.len = *retval;
219243412Snewton		fl = 0;
219343412Snewton		st->s_cmd = sc.cmd;
219443412Snewton		break;
219543412Snewton
219643412Snewton	default:
219743412Snewton		st->s_cmd = sc.cmd;
219843412Snewton		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
219943412Snewton		        struct read_args ra;
220043412Snewton
220172082Sasmodai			/* More weirdness:  Again, I can't find documentation
220243412Snewton			 * to back this up, but when a process does a generic
220343412Snewton			 * "getmsg()" call it seems that the command field is
220443412Snewton			 * zero and the length of the data area is zero.  I
220543412Snewton			 * think processes expect getmsg() to fill in dat.len
220643412Snewton			 * after reading at most dat.maxlen octets from the
220743412Snewton			 * stream.  Since we're using sockets I can let
220843412Snewton			 * read() look after it and frob return values
220943412Snewton			 * appropriately (or inappropriately :-)
221043412Snewton			 *   -- newton@atdot.dotat.org        XXX
221143412Snewton			 */
221243412Snewton			SCARG(&ra, fd) = SCARG(uap, fd);
221343412Snewton			SCARG(&ra, buf) = dat.buf;
221443412Snewton			SCARG(&ra, nbyte) = dat.maxlen;
221583366Sjulian			if ((error = read(td, &ra)) != 0) {
221643412Snewton			        return error;
221743412Snewton			}
221843412Snewton			dat.len = *retval;
221943412Snewton			*retval = 0;
222043412Snewton			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
222143412Snewton			break;
222243412Snewton		}
222343412Snewton		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
222443412Snewton		return EINVAL;
222543412Snewton	}
222643412Snewton
222743412Snewton	if (SCARG(uap, ctl)) {
222843412Snewton		if (ctl.len != -1)
222943412Snewton			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
223043412Snewton				return error;
223143412Snewton
223243412Snewton		if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
223343412Snewton			return error;
223443412Snewton	}
223543412Snewton
223643412Snewton	if (SCARG(uap, dat)) {
223743412Snewton		if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
223843412Snewton			return error;
223943412Snewton	}
224043412Snewton
224143412Snewton	if (SCARG(uap, flags)) { /* XXX: Need translation */
224243412Snewton		if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
224343412Snewton			return error;
224443412Snewton	}
224543412Snewton
224643412Snewton	*retval = 0;
224743412Snewton
224843412Snewton#ifdef DEBUG_SVR4
224943412Snewton	show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
225043412Snewton		 SCARG(uap, dat), fl);
225143412Snewton#endif /* DEBUG_SVR4 */
225243412Snewton	return error;
225343412Snewton}
225443412Snewton
225583366Sjulianint svr4_sys_send(td, uap)
225683366Sjulian	struct thread *td;
225743412Snewton	struct svr4_sys_send_args *uap;
225843412Snewton{
225943412Snewton	struct osend_args osa;
226043412Snewton	SCARG(&osa, s) = SCARG(uap, s);
226143412Snewton	SCARG(&osa, buf) = SCARG(uap, buf);
226243412Snewton	SCARG(&osa, len) = SCARG(uap, len);
226343412Snewton	SCARG(&osa, flags) = SCARG(uap, flags);
226483366Sjulian	return osend(td, &osa);
226543412Snewton}
226643412Snewton
226783366Sjulianint svr4_sys_recv(td, uap)
226883366Sjulian	struct thread *td;
226943412Snewton	struct svr4_sys_recv_args *uap;
227043412Snewton{
227143412Snewton	struct orecv_args ora;
227243412Snewton	SCARG(&ora, s) = SCARG(uap, s);
227343412Snewton	SCARG(&ora, buf) = SCARG(uap, buf);
227443412Snewton	SCARG(&ora, len) = SCARG(uap, len);
227543412Snewton	SCARG(&ora, flags) = SCARG(uap, flags);
227683366Sjulian	return orecv(td, &ora);
227743412Snewton}
227843412Snewton
227943412Snewton/*
228043412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into
228143412Snewton * sendto().  Let's leave it here for now...
228243412Snewton */
228343412Snewtonint
228483366Sjuliansvr4_sys_sendto(td, uap)
228583366Sjulian        struct thread *td;
228643412Snewton        struct svr4_sys_sendto_args *uap;
228743412Snewton{
228843412Snewton        struct sendto_args sa;
228943412Snewton
229043412Snewton	SCARG(&sa, s) = SCARG(uap, s);
229143412Snewton	SCARG(&sa, buf) = SCARG(uap, buf);
229243412Snewton	SCARG(&sa, len) = SCARG(uap, len);
229343412Snewton	SCARG(&sa, flags) = SCARG(uap, flags);
229480114Sassar	SCARG(&sa, to) = (caddr_t)SCARG(uap, to);
229543412Snewton	SCARG(&sa, tolen) = SCARG(uap, tolen);
229643412Snewton
229743412Snewton	DPRINTF(("calling sendto()\n"));
229883366Sjulian	return sendto(td, &sa);
229943412Snewton}
230043412Snewton
2301