svr4_stream.c revision 92761
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 92761 2002-03-20 05:48:58Z 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 */
7892761Salfredstatic int clean_pipe(struct thread *, const char *);
7992761Salfredstatic void getparm(struct file *, struct svr4_si_sockparms *);
8092761Salfredstatic int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
8192761Salfred			       struct file *);
8292761Salfredstatic int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
8392761Salfred			       struct file *);
8443412Snewton
8543412Snewton/* Address Conversions */
8692761Salfredstatic void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
8792761Salfred					const struct sockaddr_in *);
8892761Salfredstatic void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
8992761Salfred					const struct sockaddr_un *);
9092761Salfredstatic void netaddr_to_sockaddr_in(struct sockaddr_in *,
9192761Salfred					const struct svr4_strmcmd *);
9292761Salfredstatic void netaddr_to_sockaddr_un(struct sockaddr_un *,
9392761Salfred					const struct svr4_strmcmd *);
9443412Snewton
9543412Snewton/* stream ioctls */
9692761Salfredstatic int i_nread(struct file *, struct thread *, register_t *, int,
9792761Salfred			u_long, caddr_t);
9892761Salfredstatic int i_fdinsert(struct file *, struct thread *, register_t *, int,
9992761Salfred			   u_long, caddr_t);
10092761Salfredstatic int i_str(struct file *, struct thread *, register_t *, int,
10192761Salfred			u_long, caddr_t);
10292761Salfredstatic int i_setsig(struct file *, struct thread *, register_t *, int,
10392761Salfred			u_long, caddr_t);
10492761Salfredstatic int i_getsig(struct file *, struct thread *, register_t *, int,
10592761Salfred			u_long, caddr_t);
10692761Salfredstatic int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
10792761Salfred			     u_long, caddr_t);
10892761Salfredstatic int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
10992761Salfred			     u_long, caddr_t);
11043412Snewton
11143412Snewton/* i_str sockmod calls */
11292761Salfredstatic int sockmod(struct file *, int, struct svr4_strioctl *,
11392761Salfred			      struct thread *);
11492761Salfredstatic int si_listen(struct file *, int, struct svr4_strioctl *,
11592761Salfred			      struct thread *);
11692761Salfredstatic int si_ogetudata(struct file *, int, struct svr4_strioctl *,
11792761Salfred			      struct thread *);
11892761Salfredstatic int si_sockparams(struct file *, int, struct svr4_strioctl *,
11992761Salfred			      struct thread *);
12092761Salfredstatic int si_shutdown	(struct file *, int, struct svr4_strioctl *,
12192761Salfred			      struct thread *);
12292761Salfredstatic int si_getudata(struct file *, int, struct svr4_strioctl *,
12392761Salfred			      struct thread *);
12443412Snewton
12543412Snewton/* i_str timod calls */
12692761Salfredstatic int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
12792761Salfredstatic int ti_getinfo(struct file *, int, struct svr4_strioctl *,
12892761Salfred			      struct thread *);
12992761Salfredstatic int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
13043412Snewton
13143412Snewton/* infrastructure */
13292761Salfredstatic int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
13343412Snewton
13492761Salfredstatic int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
13592761Salfred			    caddr_t namelenp);
13643412Snewton
13743412Snewton/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
13843412Snewton * it isn't part of a "public" interface;  We're supposed to use
13943412Snewton * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
14043412Snewton * that matter.  Solution:  Suck sendit()/recvit() into here where we
14143412Snewton * can do what we like.
14243412Snewton *
14343412Snewton * I hate code duplication.
14443412Snewton *
14543412Snewton * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
14643412Snewton */
14743412Snewtonstatic int
14883366Sjuliansvr4_sendit(td, s, mp, flags)
14983366Sjulian	register struct thread *td;
15043412Snewton	int s;
15143412Snewton	register struct msghdr *mp;
15243412Snewton	int flags;
15343412Snewton{
15443412Snewton	struct uio auio;
15543412Snewton	register struct iovec *iov;
15643412Snewton	register int i;
15743412Snewton	struct mbuf *control;
15843412Snewton	struct sockaddr *to;
15943412Snewton	int len, error;
16043412Snewton	struct socket *so;
16143412Snewton#ifdef KTRACE
16243412Snewton	struct iovec *ktriov = NULL;
16362378Sgreen	struct uio ktruio;
16443412Snewton#endif
16543412Snewton
16686487Sdillon	if ((error = fgetsock(td, s, &so, NULL)) != 0)
16743412Snewton		return (error);
16843412Snewton	auio.uio_iov = mp->msg_iov;
16943412Snewton	auio.uio_iovcnt = mp->msg_iovlen;
17043412Snewton	auio.uio_segflg = UIO_USERSPACE;
17143412Snewton	auio.uio_rw = UIO_WRITE;
17283366Sjulian	auio.uio_td = td;
17343412Snewton	auio.uio_offset = 0;			/* XXX */
17443412Snewton	auio.uio_resid = 0;
17543412Snewton	iov = mp->msg_iov;
17643412Snewton	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
17769084Sdillon		if ((auio.uio_resid += iov->iov_len) < 0) {
17886487Sdillon			error = EINVAL;
17986487Sdillon			goto done1;
18069084Sdillon		}
18143412Snewton	}
18243412Snewton	if (mp->msg_name) {
18343412Snewton		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
18486487Sdillon		if (error)
18586487Sdillon			goto done1;
18669084Sdillon	} else {
18743412Snewton		to = 0;
18869084Sdillon	}
18943412Snewton	if (mp->msg_control) {
19043412Snewton		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
19143412Snewton			error = EINVAL;
19243412Snewton			goto bad;
19343412Snewton		}
19443412Snewton		error = sockargs(&control, mp->msg_control,
19543412Snewton		    mp->msg_controllen, MT_CONTROL);
19643412Snewton		if (error)
19743412Snewton			goto bad;
19869084Sdillon	} else {
19943412Snewton		control = 0;
20069084Sdillon	}
20143412Snewton#ifdef KTRACE
20283366Sjulian	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
20343412Snewton		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
20443412Snewton
20543412Snewton		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
20643412Snewton		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
20762378Sgreen		ktruio = auio;
20843412Snewton	}
20943412Snewton#endif
21043412Snewton	len = auio.uio_resid;
21143412Snewton	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
21283366Sjulian						     flags, td);
21343412Snewton	if (error) {
21443412Snewton		if (auio.uio_resid != len && (error == ERESTART ||
21543412Snewton		    error == EINTR || error == EWOULDBLOCK))
21643412Snewton			error = 0;
21773929Sjhb		if (error == EPIPE) {
21883366Sjulian			PROC_LOCK(td->td_proc);
21983366Sjulian			psignal(td->td_proc, SIGPIPE);
22083366Sjulian			PROC_UNLOCK(td->td_proc);
22173929Sjhb		}
22243412Snewton	}
22343412Snewton	if (error == 0)
22483366Sjulian		td->td_retval[0] = len - auio.uio_resid;
22543412Snewton#ifdef KTRACE
22643412Snewton	if (ktriov != NULL) {
22762378Sgreen		if (error == 0) {
22862378Sgreen			ktruio.uio_iov = ktriov;
22983366Sjulian			ktruio.uio_resid = td->td_retval[0];
23083366Sjulian			ktrgenio(td->td_proc->p_tracep, s, UIO_WRITE, &ktruio, error);
23162378Sgreen		}
23243412Snewton		FREE(ktriov, M_TEMP);
23343412Snewton	}
23443412Snewton#endif
23543412Snewtonbad:
23643412Snewton	if (to)
23743412Snewton		FREE(to, M_SONAME);
23886487Sdillondone1:
23986487Sdillon	fputsock(so);
24043412Snewton	return (error);
24143412Snewton}
24243412Snewton
24343412Snewtonstatic int
24483366Sjuliansvr4_recvit(td, s, mp, namelenp)
24583366Sjulian	register struct thread *td;
24643412Snewton	int s;
24743412Snewton	register struct msghdr *mp;
24843412Snewton	caddr_t namelenp;
24943412Snewton{
25043412Snewton	struct uio auio;
25143412Snewton	register struct iovec *iov;
25243412Snewton	register int i;
25343412Snewton	int len, error;
25443412Snewton	struct mbuf *m, *control = 0;
25543412Snewton	caddr_t ctlbuf;
25643412Snewton	struct socket *so;
25743412Snewton	struct sockaddr *fromsa = 0;
25843412Snewton#ifdef KTRACE
25943412Snewton	struct iovec *ktriov = NULL;
26062378Sgreen	struct uio ktruio;
26143412Snewton#endif
26243412Snewton
26386487Sdillon	if ((error = fgetsock(td, s, &so, NULL)) != 0)
26443412Snewton		return (error);
26543412Snewton	auio.uio_iov = mp->msg_iov;
26643412Snewton	auio.uio_iovcnt = mp->msg_iovlen;
26743412Snewton	auio.uio_segflg = UIO_USERSPACE;
26843412Snewton	auio.uio_rw = UIO_READ;
26983366Sjulian	auio.uio_td = td;
27043412Snewton	auio.uio_offset = 0;			/* XXX */
27143412Snewton	auio.uio_resid = 0;
27243412Snewton	iov = mp->msg_iov;
27343412Snewton	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
27469084Sdillon		if ((auio.uio_resid += iov->iov_len) < 0) {
27586487Sdillon			error = EINVAL;
27686487Sdillon			goto done1;
27769084Sdillon		}
27843412Snewton	}
27943412Snewton#ifdef KTRACE
28083366Sjulian	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
28143412Snewton		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
28243412Snewton
28343412Snewton		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
28443412Snewton		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
28562378Sgreen		ktruio = auio;
28643412Snewton	}
28743412Snewton#endif
28843412Snewton	len = auio.uio_resid;
28943412Snewton	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
29043412Snewton	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
29143412Snewton	    &mp->msg_flags);
29243412Snewton	if (error) {
29343412Snewton		if (auio.uio_resid != len && (error == ERESTART ||
29443412Snewton		    error == EINTR || error == EWOULDBLOCK))
29543412Snewton			error = 0;
29643412Snewton	}
29743412Snewton#ifdef KTRACE
29843412Snewton	if (ktriov != NULL) {
29962378Sgreen		if (error == 0) {
30062378Sgreen			ktruio.uio_iov = ktriov;
30162378Sgreen			ktruio.uio_resid = len - auio.uio_resid;
30283366Sjulian			ktrgenio(td->td_proc->p_tracep, s, UIO_READ, &ktruio, error);
30362378Sgreen		}
30443412Snewton		FREE(ktriov, M_TEMP);
30543412Snewton	}
30643412Snewton#endif
30743412Snewton	if (error)
30843412Snewton		goto out;
30983366Sjulian	td->td_retval[0] = len - auio.uio_resid;
31043412Snewton	if (mp->msg_name) {
31143412Snewton		len = mp->msg_namelen;
31243412Snewton		if (len <= 0 || fromsa == 0)
31343412Snewton			len = 0;
31443412Snewton		else {
31543412Snewton#ifndef MIN
31643412Snewton#define MIN(a,b) ((a)>(b)?(b):(a))
31743412Snewton#endif
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{
39443412Snewton	u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK);
39543412Snewton	int error;
39643412Snewton
39743412Snewton	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
39843412Snewton	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
39943412Snewton
40043412Snewton	if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) {
40143412Snewton		free((char *) ptr, M_TEMP);
40243412Snewton		return error;
40343412Snewton	}
40443412Snewton
40543412Snewton	bufprint(ptr, ioc->len);
40643412Snewton
40743412Snewton	uprintf("}\n");
40843412Snewton
40943412Snewton	free((char *) ptr, M_TEMP);
41043412Snewton	return 0;
41143412Snewton}
41243412Snewton
41343412Snewton
41443412Snewtonstatic int
41543412Snewtonshow_strbuf(str)
41643412Snewton	struct svr4_strbuf *str;
41743412Snewton{
41843412Snewton	int error;
41943412Snewton	u_char *ptr = NULL;
42043412Snewton	int maxlen = str->maxlen;
42143412Snewton	int len = str->len;
42243412Snewton
42343412Snewton	if (maxlen < 0)
42443412Snewton		maxlen = 0;
42543412Snewton
42643412Snewton	if (len >= maxlen)
42743412Snewton		len = maxlen;
42843412Snewton
42943412Snewton	if (len > 0) {
43043412Snewton	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
43143412Snewton
43243412Snewton	    if ((error = copyin(str->buf, ptr, len)) != 0) {
43343412Snewton		    free((char *) ptr, M_TEMP);
43443412Snewton		    return error;
43543412Snewton	    }
43643412Snewton	}
43743412Snewton
43843412Snewton	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
43943412Snewton
44043412Snewton	if (ptr)
44143412Snewton		bufprint(ptr, len);
44243412Snewton
44343412Snewton	uprintf("]}");
44443412Snewton
44543412Snewton	if (ptr)
44643412Snewton		free((char *) ptr, M_TEMP);
44743412Snewton
44843412Snewton	return 0;
44943412Snewton}
45043412Snewton
45143412Snewton
45243412Snewtonstatic void
45343412Snewtonshow_msg(str, fd, ctl, dat, flags)
45443412Snewton	const char		*str;
45543412Snewton	int			 fd;
45643412Snewton	struct svr4_strbuf	*ctl;
45743412Snewton	struct svr4_strbuf	*dat;
45843412Snewton	int			 flags;
45943412Snewton{
46043412Snewton	struct svr4_strbuf	buf;
46143412Snewton	int error;
46243412Snewton
46343412Snewton	uprintf("%s(%d", str, fd);
46443412Snewton	if (ctl != NULL) {
46543412Snewton		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
46643412Snewton			return;
46743412Snewton		show_strbuf(&buf);
46843412Snewton	}
46943412Snewton	else
47043412Snewton		uprintf(", NULL");
47143412Snewton
47243412Snewton	if (dat != NULL) {
47343412Snewton		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
47443412Snewton			return;
47543412Snewton		show_strbuf(&buf);
47643412Snewton	}
47743412Snewton	else
47843412Snewton		uprintf(", NULL");
47943412Snewton
48043412Snewton	uprintf(", %x);\n", flags);
48143412Snewton}
48243412Snewton
48343412Snewton#endif /* DEBUG_SVR4 */
48443412Snewton
48543412Snewton/*
48643412Snewton * We are faced with an interesting situation. On svr4 unix sockets
48743412Snewton * are really pipes. But we really have sockets, and we might as
48843412Snewton * well use them. At the point where svr4 calls TI_BIND, it has
48943412Snewton * already created a named pipe for the socket using mknod(2).
49043412Snewton * We need to create a socket with the same name when we bind,
49143412Snewton * so we need to remove the pipe before, otherwise we'll get address
49243412Snewton * already in use. So we *carefully* remove the pipe, to avoid
49343412Snewton * using this as a random file removal tool. We use system calls
49443412Snewton * to avoid code duplication.
49543412Snewton */
49643412Snewtonstatic int
49783366Sjulianclean_pipe(td, path)
49883366Sjulian	struct thread *td;
49943412Snewton	const char *path;
50043412Snewton{
50143412Snewton	struct lstat_args la;
50243412Snewton	struct unlink_args ua;
50343412Snewton	struct stat st;
50443412Snewton	int error;
50543412Snewton	caddr_t sg = stackgap_init();
50643412Snewton	size_t l = strlen(path) + 1;
50743412Snewton	void *tpath;
50843412Snewton
50943412Snewton	tpath = stackgap_alloc(&sg, l);
51043412Snewton	SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
51143412Snewton
51243412Snewton	if ((error = copyout(path, tpath, l)) != 0)
51343412Snewton		return error;
51443412Snewton
51543412Snewton	SCARG(&la, path) = tpath;
51643412Snewton
51783366Sjulian	if ((error = lstat(td, &la)) != 0)
51843412Snewton		return 0;
51943412Snewton
52043412Snewton	if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
52143412Snewton		return 0;
52243412Snewton
52343412Snewton	/*
52443412Snewton	 * Make sure we are dealing with a mode 0 named pipe.
52543412Snewton	 */
52643412Snewton	if ((st.st_mode & S_IFMT) != S_IFIFO)
52743412Snewton		return 0;
52843412Snewton
52943412Snewton	if ((st.st_mode & ALLPERMS) != 0)
53043412Snewton		return 0;
53143412Snewton
53243412Snewton	SCARG(&ua, path) = SCARG(&la, path);
53343412Snewton
53483366Sjulian	if ((error = unlink(td, &ua)) != 0) {
53543412Snewton		DPRINTF(("clean_pipe: unlink failed %d\n", error));
53643412Snewton		return error;
53743412Snewton	}
53843412Snewton
53943412Snewton	return 0;
54043412Snewton}
54143412Snewton
54243412Snewton
54343412Snewtonstatic void
54443412Snewtonsockaddr_to_netaddr_in(sc, sain)
54543412Snewton	struct svr4_strmcmd *sc;
54643412Snewton	const struct sockaddr_in *sain;
54743412Snewton{
54843412Snewton	struct svr4_netaddr_in *na;
54943412Snewton	na = SVR4_ADDROF(sc);
55043412Snewton
55143412Snewton	na->family = sain->sin_family;
55243412Snewton	na->port = sain->sin_port;
55343412Snewton	na->addr = sain->sin_addr.s_addr;
55443412Snewton	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
55543412Snewton		 na->addr));
55643412Snewton}
55743412Snewton
55843412Snewton
55943412Snewtonstatic void
56043412Snewtonsockaddr_to_netaddr_un(sc, saun)
56143412Snewton	struct svr4_strmcmd *sc;
56243412Snewton	const struct sockaddr_un *saun;
56343412Snewton{
56443412Snewton	struct svr4_netaddr_un *na;
56543412Snewton	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
56643412Snewton	    sizeof(*sc);
56743412Snewton	const char *src;
56843412Snewton
56943412Snewton	na = SVR4_ADDROF(sc);
57043412Snewton	na->family = saun->sun_family;
57143412Snewton	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
57243412Snewton		if (dst == edst)
57343412Snewton			break;
57443412Snewton	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
57543412Snewton}
57643412Snewton
57743412Snewton
57843412Snewtonstatic void
57943412Snewtonnetaddr_to_sockaddr_in(sain, sc)
58043412Snewton	struct sockaddr_in *sain;
58143412Snewton	const struct svr4_strmcmd *sc;
58243412Snewton{
58343412Snewton	const struct svr4_netaddr_in *na;
58443412Snewton
58543412Snewton
58643412Snewton	na = SVR4_C_ADDROF(sc);
58743412Snewton	memset(sain, 0, sizeof(*sain));
58843412Snewton	sain->sin_len = sizeof(*sain);
58943412Snewton	sain->sin_family = na->family;
59043412Snewton	sain->sin_port = na->port;
59143412Snewton	sain->sin_addr.s_addr = na->addr;
59243412Snewton	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
59343412Snewton		 sain->sin_port, sain->sin_addr.s_addr));
59443412Snewton}
59543412Snewton
59643412Snewton
59743412Snewtonstatic void
59843412Snewtonnetaddr_to_sockaddr_un(saun, sc)
59943412Snewton	struct sockaddr_un *saun;
60043412Snewton	const struct svr4_strmcmd *sc;
60143412Snewton{
60243412Snewton	const struct svr4_netaddr_un *na;
60343412Snewton	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
60443412Snewton	const char *src;
60543412Snewton
60643412Snewton	na = SVR4_C_ADDROF(sc);
60743412Snewton	memset(saun, 0, sizeof(*saun));
60843412Snewton	saun->sun_family = na->family;
60943412Snewton	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
61043412Snewton		if (dst == edst)
61143412Snewton			break;
61243412Snewton	saun->sun_len = dst - saun->sun_path;
61343412Snewton	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
61443412Snewton		 saun->sun_path));
61543412Snewton}
61643412Snewton
61743412Snewton
61843412Snewtonstatic void
61943412Snewtongetparm(fp, pa)
62043412Snewton	struct file *fp;
62143412Snewton	struct svr4_si_sockparms *pa;
62243412Snewton{
62389306Salfred	struct svr4_strm *st;
62489306Salfred	struct socket *so;
62543412Snewton
62689306Salfred	st = svr4_stream_get(fp);
62743412Snewton	if (st == NULL)
62843412Snewton		return;
62943412Snewton
63089306Salfred	so = (struct socket *) fp->f_data;
63189306Salfred
63243412Snewton	pa->family = st->s_family;
63343412Snewton
63443412Snewton	switch (so->so_type) {
63543412Snewton	case SOCK_DGRAM:
63643412Snewton		pa->type = SVR4_T_CLTS;
63743412Snewton		pa->protocol = IPPROTO_UDP;
63843412Snewton		DPRINTF(("getparm(dgram)\n"));
63943412Snewton		return;
64043412Snewton
64143412Snewton	case SOCK_STREAM:
64243412Snewton	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
64343412Snewton		pa->protocol = IPPROTO_IP;
64443412Snewton		DPRINTF(("getparm(stream)\n"));
64543412Snewton		return;
64643412Snewton
64743412Snewton	case SOCK_RAW:
64843412Snewton		pa->type = SVR4_T_CLTS;
64943412Snewton		pa->protocol = IPPROTO_RAW;
65043412Snewton		DPRINTF(("getparm(raw)\n"));
65143412Snewton		return;
65243412Snewton
65343412Snewton	default:
65443412Snewton		pa->type = 0;
65543412Snewton		pa->protocol = 0;
65643412Snewton		DPRINTF(("getparm(type %d?)\n", so->so_type));
65743412Snewton		return;
65843412Snewton	}
65943412Snewton}
66043412Snewton
66143412Snewton
66243412Snewtonstatic int
66383366Sjuliansi_ogetudata(fp, fd, ioc, td)
66443412Snewton	struct file		*fp;
66543412Snewton	int 			 fd;
66643412Snewton	struct svr4_strioctl	*ioc;
66783366Sjulian	struct thread		*td;
66843412Snewton{
66943412Snewton	int error;
67043412Snewton	struct svr4_si_oudata ud;
67143412Snewton	struct svr4_si_sockparms pa;
67243412Snewton
67343412Snewton	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
67443412Snewton		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
67543412Snewton			 sizeof(ud), ioc->len));
67643412Snewton		return EINVAL;
67743412Snewton	}
67843412Snewton
67943412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
68043412Snewton		return error;
68143412Snewton
68243412Snewton	getparm(fp, &pa);
68343412Snewton
68443412Snewton	switch (pa.family) {
68543412Snewton	case AF_INET:
68643412Snewton	    ud.tidusize = 16384;
68743412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
68843412Snewton	    if (pa.type == SVR4_SOCK_STREAM)
68943412Snewton		    ud.etsdusize = 1;
69043412Snewton	    else
69143412Snewton		    ud.etsdusize = 0;
69243412Snewton	    break;
69343412Snewton
69443412Snewton	case AF_LOCAL:
69543412Snewton	    ud.tidusize = 65536;
69643412Snewton	    ud.addrsize = 128;
69743412Snewton	    ud.etsdusize = 128;
69843412Snewton	    break;
69943412Snewton
70043412Snewton	default:
70143412Snewton	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
70243412Snewton		     pa.family));
70343412Snewton	    return ENOSYS;
70443412Snewton	}
70543412Snewton
70643412Snewton	/* I have no idea what these should be! */
70743412Snewton	ud.optsize = 128;
70843412Snewton	ud.tsdusize = 128;
70943412Snewton
71043412Snewton	ud.servtype = pa.type;
71143412Snewton
71243412Snewton	/* XXX: Fixme */
71343412Snewton	ud.so_state = 0;
71443412Snewton	ud.so_options = 0;
71543412Snewton	return copyout(&ud, ioc->buf, ioc->len);
71643412Snewton}
71743412Snewton
71843412Snewton
71943412Snewtonstatic int
72083366Sjuliansi_sockparams(fp, fd, ioc, td)
72143412Snewton	struct file		*fp;
72243412Snewton	int 			 fd;
72343412Snewton	struct svr4_strioctl	*ioc;
72483366Sjulian	struct thread		*td;
72543412Snewton{
72643412Snewton	struct svr4_si_sockparms pa;
72743412Snewton
72843412Snewton	getparm(fp, &pa);
72943412Snewton	return copyout(&pa, ioc->buf, sizeof(pa));
73043412Snewton}
73143412Snewton
73243412Snewton
73343412Snewtonstatic int
73483366Sjuliansi_listen(fp, fd, ioc, td)
73543412Snewton	struct file		*fp;
73643412Snewton	int 			 fd;
73743412Snewton	struct svr4_strioctl	*ioc;
73883366Sjulian	struct thread		*td;
73943412Snewton{
74043412Snewton	int error;
74143412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
74243412Snewton	struct svr4_strmcmd lst;
74343412Snewton	struct listen_args la;
74443412Snewton
74543412Snewton	if (st == NULL)
74643412Snewton		return EINVAL;
74743412Snewton
74843412Snewton	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
74943412Snewton		return error;
75043412Snewton
75143412Snewton	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
75243412Snewton		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
75343412Snewton		return EINVAL;
75443412Snewton	}
75543412Snewton
75643412Snewton	/*
75743412Snewton	 * We are making assumptions again...
75843412Snewton	 */
75943412Snewton	SCARG(&la, s) = fd;
76043412Snewton	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
76143412Snewton	SCARG(&la, backlog) = 5;
76243412Snewton
76383366Sjulian	if ((error = listen(td, &la)) != 0) {
76443412Snewton		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
76543412Snewton		return error;
76643412Snewton	}
76743412Snewton
76843412Snewton	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
76943412Snewton	lst.cmd = SVR4_TI_BIND_REPLY;
77043412Snewton
77143412Snewton	switch (st->s_family) {
77243412Snewton	case AF_INET:
77343412Snewton		/* XXX: Fill the length here */
77443412Snewton		break;
77543412Snewton
77643412Snewton	case AF_LOCAL:
77743412Snewton		lst.len = 140;
77843412Snewton		lst.pad[28] = 0x00000000;	/* magic again */
77943412Snewton		lst.pad[29] = 0x00000800;	/* magic again */
78043412Snewton		lst.pad[30] = 0x80001400;	/* magic again */
78143412Snewton		break;
78243412Snewton
78343412Snewton	default:
78443412Snewton		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
78543412Snewton		    st->s_family));
78643412Snewton		return ENOSYS;
78743412Snewton	}
78843412Snewton
78943412Snewton
79043412Snewton	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
79143412Snewton		return error;
79243412Snewton
79343412Snewton	return 0;
79443412Snewton}
79543412Snewton
79643412Snewton
79743412Snewtonstatic int
79883366Sjuliansi_getudata(fp, fd, ioc, td)
79943412Snewton	struct file		*fp;
80043412Snewton	int 			 fd;
80143412Snewton	struct svr4_strioctl	*ioc;
80283366Sjulian	struct thread		*td;
80343412Snewton{
80443412Snewton	int error;
80543412Snewton	struct svr4_si_udata ud;
80643412Snewton
80743412Snewton	if (sizeof(ud) != ioc->len) {
80843412Snewton		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
80943412Snewton			 sizeof(ud), ioc->len));
81043412Snewton		return EINVAL;
81143412Snewton	}
81243412Snewton
81343412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
81443412Snewton		return error;
81543412Snewton
81643412Snewton	getparm(fp, &ud.sockparms);
81743412Snewton
81843412Snewton	switch (ud.sockparms.family) {
81943412Snewton	case AF_INET:
82043412Snewton	    DPRINTF(("getudata_inet\n"));
82143412Snewton	    ud.tidusize = 16384;
82243412Snewton	    ud.tsdusize = 16384;
82343412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
82443412Snewton	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
82543412Snewton		    ud.etsdusize = 1;
82643412Snewton	    else
82743412Snewton		    ud.etsdusize = 0;
82843412Snewton	    ud.optsize = 0;
82943412Snewton	    break;
83043412Snewton
83143412Snewton	case AF_LOCAL:
83243412Snewton	    DPRINTF(("getudata_local\n"));
83343412Snewton	    ud.tidusize = 65536;
83443412Snewton	    ud.tsdusize = 128;
83543412Snewton	    ud.addrsize = 128;
83643412Snewton	    ud.etsdusize = 128;
83743412Snewton	    ud.optsize = 128;
83843412Snewton	    break;
83943412Snewton
84043412Snewton	default:
84143412Snewton	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
84243412Snewton		     ud.sockparms.family));
84343412Snewton	    return ENOSYS;
84443412Snewton	}
84543412Snewton
84643412Snewton
84743412Snewton	ud.servtype = ud.sockparms.type;
84843412Snewton	DPRINTF(("ud.servtype = %d\n", ud.servtype));
84943412Snewton	/* XXX: Fixme */
85043412Snewton	ud.so_state = 0;
85143412Snewton	ud.so_options = 0;
85243412Snewton	return copyout(&ud, ioc->buf, sizeof(ud));
85343412Snewton}
85443412Snewton
85543412Snewton
85643412Snewtonstatic int
85783366Sjuliansi_shutdown(fp, fd, ioc, td)
85843412Snewton	struct file		*fp;
85943412Snewton	int 			 fd;
86043412Snewton	struct svr4_strioctl	*ioc;
86183366Sjulian	struct thread		*td;
86243412Snewton{
86343412Snewton	int error;
86443412Snewton	struct shutdown_args ap;
86543412Snewton
86643412Snewton	if (ioc->len != sizeof(SCARG(&ap, how))) {
86743412Snewton		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
86843412Snewton			 sizeof(SCARG(&ap, how)), ioc->len));
86943412Snewton		return EINVAL;
87043412Snewton	}
87143412Snewton
87243412Snewton	if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
87343412Snewton		return error;
87443412Snewton
87543412Snewton	SCARG(&ap, s) = fd;
87643412Snewton
87783366Sjulian	return shutdown(td, &ap);
87843412Snewton}
87943412Snewton
88043412Snewton
88143412Snewtonstatic int
88283366Sjuliansockmod(fp, fd, ioc, td)
88343412Snewton	struct file		*fp;
88443412Snewton	int			 fd;
88543412Snewton	struct svr4_strioctl	*ioc;
88683366Sjulian	struct thread		*td;
88743412Snewton{
88843412Snewton	switch (ioc->cmd) {
88943412Snewton	case SVR4_SI_OGETUDATA:
89043412Snewton		DPRINTF(("SI_OGETUDATA\n"));
89183366Sjulian		return si_ogetudata(fp, fd, ioc, td);
89243412Snewton
89343412Snewton	case SVR4_SI_SHUTDOWN:
89443412Snewton		DPRINTF(("SI_SHUTDOWN\n"));
89583366Sjulian		return si_shutdown(fp, fd, ioc, td);
89643412Snewton
89743412Snewton	case SVR4_SI_LISTEN:
89843412Snewton		DPRINTF(("SI_LISTEN\n"));
89983366Sjulian		return si_listen(fp, fd, ioc, td);
90043412Snewton
90143412Snewton	case SVR4_SI_SETMYNAME:
90243412Snewton		DPRINTF(("SI_SETMYNAME\n"));
90343412Snewton		return 0;
90443412Snewton
90543412Snewton	case SVR4_SI_SETPEERNAME:
90643412Snewton		DPRINTF(("SI_SETPEERNAME\n"));
90743412Snewton		return 0;
90843412Snewton
90943412Snewton	case SVR4_SI_GETINTRANSIT:
91043412Snewton		DPRINTF(("SI_GETINTRANSIT\n"));
91143412Snewton		return 0;
91243412Snewton
91343412Snewton	case SVR4_SI_TCL_LINK:
91443412Snewton		DPRINTF(("SI_TCL_LINK\n"));
91543412Snewton		return 0;
91643412Snewton
91743412Snewton	case SVR4_SI_TCL_UNLINK:
91843412Snewton		DPRINTF(("SI_TCL_UNLINK\n"));
91943412Snewton		return 0;
92043412Snewton
92143412Snewton	case SVR4_SI_SOCKPARAMS:
92243412Snewton		DPRINTF(("SI_SOCKPARAMS\n"));
92383366Sjulian		return si_sockparams(fp, fd, ioc, td);
92443412Snewton
92543412Snewton	case SVR4_SI_GETUDATA:
92643412Snewton		DPRINTF(("SI_GETUDATA\n"));
92783366Sjulian		return si_getudata(fp, fd, ioc, td);
92843412Snewton
92943412Snewton	default:
93043412Snewton		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
93143412Snewton		return 0;
93243412Snewton
93343412Snewton	}
93443412Snewton}
93543412Snewton
93643412Snewton
93743412Snewtonstatic int
93883366Sjulianti_getinfo(fp, fd, ioc, td)
93943412Snewton	struct file		*fp;
94043412Snewton	int 			 fd;
94143412Snewton	struct svr4_strioctl	*ioc;
94283366Sjulian	struct thread		*td;
94343412Snewton{
94443412Snewton	int error;
94543412Snewton	struct svr4_infocmd info;
94643412Snewton
94743412Snewton	memset(&info, 0, sizeof(info));
94843412Snewton
94943412Snewton	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
95043412Snewton		return error;
95143412Snewton
95243412Snewton	if (info.cmd != SVR4_TI_INFO_REQUEST)
95343412Snewton		return EINVAL;
95443412Snewton
95543412Snewton	info.cmd = SVR4_TI_INFO_REPLY;
95643412Snewton	info.tsdu = 0;
95743412Snewton	info.etsdu = 1;
95843412Snewton	info.cdata = -2;
95943412Snewton	info.ddata = -2;
96043412Snewton	info.addr = 16;
96143412Snewton	info.opt = -1;
96243412Snewton	info.tidu = 16384;
96343412Snewton	info.serv = 2;
96443412Snewton	info.current = 0;
96543412Snewton	info.provider = 2;
96643412Snewton
96743412Snewton	ioc->len = sizeof(info);
96843412Snewton	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
96943412Snewton		return error;
97043412Snewton
97143412Snewton	return 0;
97243412Snewton}
97343412Snewton
97443412Snewton
97543412Snewtonstatic int
97683366Sjulianti_bind(fp, fd, ioc, td)
97743412Snewton	struct file		*fp;
97843412Snewton	int 			 fd;
97943412Snewton	struct svr4_strioctl	*ioc;
98083366Sjulian	struct thread		*td;
98143412Snewton{
98243412Snewton	int error;
98343412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
98443412Snewton	struct sockaddr_in sain;
98543412Snewton	struct sockaddr_un saun;
98643412Snewton	caddr_t sg;
98743412Snewton	void *skp, *sup = NULL;
98843412Snewton	int sasize;
98943412Snewton	struct svr4_strmcmd bnd;
99043412Snewton	struct bind_args ba;
99143412Snewton
99243412Snewton	if (st == NULL) {
99343412Snewton		DPRINTF(("ti_bind: bad file descriptor\n"));
99443412Snewton		return EINVAL;
99543412Snewton	}
99643412Snewton
99743412Snewton	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
99843412Snewton		return error;
99943412Snewton
100043412Snewton	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
100143412Snewton		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
100243412Snewton		return EINVAL;
100343412Snewton	}
100443412Snewton
100543412Snewton	switch (st->s_family) {
100643412Snewton	case AF_INET:
100743412Snewton		skp = &sain;
100843412Snewton		sasize = sizeof(sain);
100943412Snewton
101043412Snewton		if (bnd.offs == 0)
101143412Snewton			goto reply;
101243412Snewton
101343412Snewton		netaddr_to_sockaddr_in(&sain, &bnd);
101443412Snewton
101543412Snewton		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
101643412Snewton			 sain.sin_family, sain.sin_port,
101743412Snewton			 sain.sin_addr.s_addr));
101843412Snewton		break;
101943412Snewton
102043412Snewton	case AF_LOCAL:
102143412Snewton		skp = &saun;
102243412Snewton		sasize = sizeof(saun);
102343412Snewton		if (bnd.offs == 0)
102443412Snewton			goto reply;
102543412Snewton
102643412Snewton		netaddr_to_sockaddr_un(&saun, &bnd);
102743412Snewton
102843412Snewton		if (saun.sun_path[0] == '\0')
102943412Snewton			goto reply;
103043412Snewton
103143412Snewton		DPRINTF(("TI_BIND: fam %d, path %s\n",
103243412Snewton			 saun.sun_family, saun.sun_path));
103343412Snewton
103483366Sjulian		if ((error = clean_pipe(td, saun.sun_path)) != 0)
103543412Snewton			return error;
103643412Snewton
103743412Snewton		bnd.pad[28] = 0x00001000;	/* magic again */
103843412Snewton		break;
103943412Snewton
104043412Snewton	default:
104143412Snewton		DPRINTF(("TI_BIND: Unsupported address family %d\n",
104243412Snewton			 st->s_family));
104343412Snewton		return ENOSYS;
104443412Snewton	}
104543412Snewton
104643412Snewton	sg = stackgap_init();
104743412Snewton	sup = stackgap_alloc(&sg, sasize);
104843412Snewton
104943412Snewton	if ((error = copyout(skp, sup, sasize)) != 0)
105043412Snewton		return error;
105143412Snewton
105243412Snewton	SCARG(&ba, s) = fd;
105343412Snewton	DPRINTF(("TI_BIND: fileno %d\n", fd));
105443412Snewton	SCARG(&ba, name) = (void *) sup;
105543412Snewton	SCARG(&ba, namelen) = sasize;
105643412Snewton
105783366Sjulian	if ((error = bind(td, &ba)) != 0) {
105843412Snewton		DPRINTF(("TI_BIND: bind failed %d\n", error));
105943412Snewton		return error;
106043412Snewton	}
106143412Snewton
106243412Snewtonreply:
106343412Snewton	if (sup == NULL) {
106443412Snewton		memset(&bnd, 0, sizeof(bnd));
106543412Snewton		bnd.len = sasize + 4;
106643412Snewton		bnd.offs = 0x10;	/* XXX */
106743412Snewton	}
106843412Snewton
106943412Snewton	bnd.cmd = SVR4_TI_BIND_REPLY;
107043412Snewton
107143412Snewton	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
107243412Snewton		return error;
107343412Snewton
107443412Snewton	return 0;
107543412Snewton}
107643412Snewton
107743412Snewton
107843412Snewtonstatic int
107983366Sjuliantimod(fp, fd, ioc, td)
108043412Snewton	struct file		*fp;
108143412Snewton	int			 fd;
108243412Snewton	struct svr4_strioctl	*ioc;
108383366Sjulian	struct thread		*td;
108443412Snewton{
108543412Snewton	switch (ioc->cmd) {
108643412Snewton	case SVR4_TI_GETINFO:
108743412Snewton		DPRINTF(("TI_GETINFO\n"));
108883366Sjulian		return ti_getinfo(fp, fd, ioc, td);
108943412Snewton
109043412Snewton	case SVR4_TI_OPTMGMT:
109143412Snewton		DPRINTF(("TI_OPTMGMT\n"));
109243412Snewton		return 0;
109343412Snewton
109443412Snewton	case SVR4_TI_BIND:
109543412Snewton		DPRINTF(("TI_BIND\n"));
109683366Sjulian		return ti_bind(fp, fd, ioc, td);
109743412Snewton
109843412Snewton	case SVR4_TI_UNBIND:
109943412Snewton		DPRINTF(("TI_UNBIND\n"));
110043412Snewton		return 0;
110143412Snewton
110243412Snewton	default:
110343412Snewton		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
110443412Snewton		return 0;
110543412Snewton	}
110643412Snewton}
110743412Snewton
110843412Snewton
110943412Snewtonint
111083366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
111143412Snewton	struct file *fp;
111283366Sjulian	struct thread *td;
111343412Snewton	register_t *retval;
111443412Snewton	int fd;
111543412Snewton	u_long cmd;
111643412Snewton	caddr_t dat;
111743412Snewton{
111843412Snewton	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
111943412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
112043412Snewton	int error;
112143412Snewton	void *skp, *sup;
112243412Snewton	struct sockaddr_in sain;
112343412Snewton	struct sockaddr_un saun;
112443412Snewton	struct svr4_strmcmd sc;
112543412Snewton	int sasize;
112643412Snewton	caddr_t sg;
112743412Snewton	int *lenp;
112843412Snewton
112943412Snewton	DPRINTF(("svr4_stream_ti_ioctl\n"));
113043412Snewton
113143412Snewton	if (st == NULL)
113243412Snewton		return EINVAL;
113343412Snewton
113443412Snewton	sc.offs = 0x10;
113543412Snewton
113643412Snewton	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
113743412Snewton		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
113843412Snewton		return error;
113943412Snewton	}
114043412Snewton
114143412Snewton	switch (st->s_family) {
114243412Snewton	case AF_INET:
114343412Snewton		skp = &sain;
114443412Snewton		sasize = sizeof(sain);
114543412Snewton		break;
114643412Snewton
114743412Snewton	case AF_LOCAL:
114843412Snewton		skp = &saun;
114943412Snewton		sasize = sizeof(saun);
115043412Snewton		break;
115143412Snewton
115243412Snewton	default:
115343412Snewton		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
115443412Snewton			 st->s_family));
115543412Snewton		return ENOSYS;
115643412Snewton	}
115743412Snewton
115843412Snewton	sg = stackgap_init();
115943412Snewton	sup = stackgap_alloc(&sg, sasize);
116043412Snewton	lenp = stackgap_alloc(&sg, sizeof(*lenp));
116143412Snewton
116243412Snewton	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
116343412Snewton		DPRINTF(("ti_ioctl: error copying out lenp\n"));
116443412Snewton		return error;
116543412Snewton	}
116643412Snewton
116743412Snewton	switch (cmd) {
116843412Snewton	case SVR4_TI_GETMYNAME:
116943412Snewton		DPRINTF(("TI_GETMYNAME\n"));
117043412Snewton		{
117143412Snewton			struct getsockname_args ap;
117243412Snewton			SCARG(&ap, fdes) = fd;
117343412Snewton			SCARG(&ap, asa) = sup;
117443412Snewton			SCARG(&ap, alen) = lenp;
117583366Sjulian			if ((error = getsockname(td, &ap)) != 0) {
117643412Snewton				DPRINTF(("ti_ioctl: getsockname error\n"));
117743412Snewton				return error;
117843412Snewton			}
117943412Snewton		}
118043412Snewton		break;
118143412Snewton
118243412Snewton	case SVR4_TI_GETPEERNAME:
118343412Snewton		DPRINTF(("TI_GETPEERNAME\n"));
118443412Snewton		{
118543412Snewton			struct getpeername_args ap;
118643412Snewton			SCARG(&ap, fdes) = fd;
118743412Snewton			SCARG(&ap, asa) = sup;
118843412Snewton			SCARG(&ap, alen) = lenp;
118983366Sjulian			if ((error = getpeername(td, &ap)) != 0) {
119043412Snewton				DPRINTF(("ti_ioctl: getpeername error\n"));
119143412Snewton				return error;
119243412Snewton			}
119343412Snewton		}
119443412Snewton		break;
119543412Snewton
119643412Snewton	case SVR4_TI_SETMYNAME:
119743412Snewton		DPRINTF(("TI_SETMYNAME\n"));
119843412Snewton		return 0;
119943412Snewton
120043412Snewton	case SVR4_TI_SETPEERNAME:
120143412Snewton		DPRINTF(("TI_SETPEERNAME\n"));
120243412Snewton		return 0;
120343412Snewton	default:
120443412Snewton		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
120543412Snewton		return ENOSYS;
120643412Snewton	}
120743412Snewton
120843412Snewton	if ((error = copyin(sup, skp, sasize)) != 0) {
120943412Snewton		DPRINTF(("ti_ioctl: error copying in socket data\n"));
121043412Snewton		return error;
121143412Snewton	}
121243412Snewton
121343412Snewton	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
121443412Snewton		DPRINTF(("ti_ioctl: error copying in socket size\n"));
121543412Snewton		return error;
121643412Snewton	}
121743412Snewton
121843412Snewton	switch (st->s_family) {
121943412Snewton	case AF_INET:
122043412Snewton		sockaddr_to_netaddr_in(&sc, &sain);
122143412Snewton		skb.len = sasize;
122243412Snewton		break;
122343412Snewton
122443412Snewton	case AF_LOCAL:
122543412Snewton		sockaddr_to_netaddr_un(&sc, &saun);
122643412Snewton		skb.len = sasize + 4;
122743412Snewton		break;
122843412Snewton
122943412Snewton	default:
123043412Snewton		return ENOSYS;
123143412Snewton	}
123243412Snewton
123343412Snewton
123443412Snewton	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
123543412Snewton		DPRINTF(("ti_ioctl: error copying out socket data\n"));
123643412Snewton		return error;
123743412Snewton	}
123843412Snewton
123943412Snewton
124043412Snewton	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
124143412Snewton		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
124243412Snewton		return error;
124343412Snewton	}
124443412Snewton
124543412Snewton	return error;
124643412Snewton}
124743412Snewton
124843412Snewton
124943412Snewton
125043412Snewton
125143412Snewtonstatic int
125283366Sjuliani_nread(fp, td, retval, fd, cmd, dat)
125343412Snewton	struct file *fp;
125483366Sjulian	struct thread *td;
125543412Snewton	register_t *retval;
125643412Snewton	int fd;
125743412Snewton	u_long cmd;
125843412Snewton	caddr_t dat;
125943412Snewton{
126043412Snewton	int error;
126143412Snewton	int nread = 0;
126243412Snewton
126343412Snewton	/*
126443412Snewton	 * We are supposed to return the message length in nread, and the
126543412Snewton	 * number of messages in retval. We don't have the notion of number
126643412Snewton	 * of stream messages, so we just find out if we have any bytes waiting
126743412Snewton	 * for us, and if we do, then we assume that we have at least one
126843412Snewton	 * message waiting for us.
126943412Snewton	 */
127083366Sjulian	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0)
127143412Snewton		return error;
127243412Snewton
127343412Snewton	if (nread != 0)
127443412Snewton		*retval = 1;
127543412Snewton	else
127643412Snewton		*retval = 0;
127743412Snewton
127843412Snewton	return copyout(&nread, dat, sizeof(nread));
127943412Snewton}
128043412Snewton
128143412Snewtonstatic int
128283366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat)
128343412Snewton	struct file *fp;
128483366Sjulian	struct thread *td;
128543412Snewton	register_t *retval;
128643412Snewton	int fd;
128743412Snewton	u_long cmd;
128843412Snewton	caddr_t dat;
128943412Snewton{
129043412Snewton	/*
129143412Snewton	 * Major hack again here. We assume that we are using this to
129243412Snewton	 * implement accept(2). If that is the case, we have already
129343412Snewton	 * called accept, and we have stored the file descriptor in
129443412Snewton	 * afd. We find the file descriptor that the code wants to use
129543412Snewton	 * in fd insert, and then we dup2() our accepted file descriptor
129643412Snewton	 * to it.
129743412Snewton	 */
129843412Snewton	int error;
129943412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
130043412Snewton	struct svr4_strfdinsert fdi;
130143412Snewton	struct dup2_args d2p;
130243412Snewton	struct close_args clp;
130343412Snewton
130443412Snewton	if (st == NULL) {
130543412Snewton		DPRINTF(("fdinsert: bad file type\n"));
130643412Snewton		return EINVAL;
130743412Snewton	}
130843412Snewton
130943412Snewton	if (st->s_afd == -1) {
131043412Snewton		DPRINTF(("fdinsert: accept fd not found\n"));
131143412Snewton		return ENOENT;
131243412Snewton	}
131343412Snewton
131443412Snewton	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
131543412Snewton		DPRINTF(("fdinsert: copyin failed %d\n", error));
131643412Snewton		return error;
131743412Snewton	}
131843412Snewton
131943412Snewton	SCARG(&d2p, from) = st->s_afd;
132043412Snewton	SCARG(&d2p, to) = fdi.fd;
132143412Snewton
132283366Sjulian	if ((error = dup2(td, &d2p)) != 0) {
132343412Snewton		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
132443412Snewton		    st->s_afd, fdi.fd, error));
132543412Snewton		return error;
132643412Snewton	}
132743412Snewton
132843412Snewton	SCARG(&clp, fd) = st->s_afd;
132943412Snewton
133083366Sjulian	if ((error = close(td, &clp)) != 0) {
133143412Snewton		DPRINTF(("fdinsert: close(%d) failed %d\n",
133243412Snewton		    st->s_afd, error));
133343412Snewton		return error;
133443412Snewton	}
133543412Snewton
133643412Snewton	st->s_afd = -1;
133743412Snewton
133843412Snewton	*retval = 0;
133943412Snewton	return 0;
134043412Snewton}
134143412Snewton
134243412Snewton
134343412Snewtonstatic int
134483366Sjulian_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
134543412Snewton	struct file *fp;
134683366Sjulian	struct thread *td;
134743412Snewton	register_t *retval;
134843412Snewton	int fd;
134943412Snewton	u_long cmd;
135043412Snewton	caddr_t dat;
135143412Snewton{
135243412Snewton	struct mkfifo_args ap;
135343412Snewton
135443412Snewton	/*
135543412Snewton	 * This is a supposed to be a kernel and library only ioctl.
135643412Snewton	 * It gets called before ti_bind, when we have a unix
135743412Snewton	 * socket, to physically create the socket transport and
135843412Snewton	 * ``reserve'' it. I don't know how this get reserved inside
135943412Snewton	 * the kernel, but we are going to create it nevertheless.
136043412Snewton	 */
136143412Snewton	SCARG(&ap, path) = dat;
136243412Snewton	SCARG(&ap, mode) = S_IFIFO;
136343412Snewton
136483366Sjulian	return mkfifo(td, &ap);
136543412Snewton}
136643412Snewton
136743412Snewtonstatic int
136883366Sjulian_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
136943412Snewton	struct file *fp;
137083366Sjulian	struct thread *td;
137143412Snewton	register_t *retval;
137243412Snewton	int fd;
137343412Snewton	u_long cmd;
137443412Snewton	caddr_t dat;
137543412Snewton{
137643412Snewton	struct unlink_args ap;
137743412Snewton
137843412Snewton	/*
137943412Snewton	 * This is a supposed to be a kernel and library only ioctl.
138043412Snewton	 * I guess it is supposed to release the socket.
138143412Snewton	 */
138243412Snewton	SCARG(&ap, path) = dat;
138343412Snewton
138483366Sjulian	return unlink(td, &ap);
138543412Snewton}
138643412Snewton
138743412Snewtonstatic int
138883366Sjuliani_str(fp, td, retval, fd, cmd, dat)
138943412Snewton	struct file *fp;
139083366Sjulian	struct thread *td;
139143412Snewton	register_t *retval;
139243412Snewton	int fd;
139343412Snewton	u_long cmd;
139443412Snewton	caddr_t dat;
139543412Snewton{
139643412Snewton	int			 error;
139743412Snewton	struct svr4_strioctl	 ioc;
139843412Snewton
139943412Snewton	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
140043412Snewton		return error;
140143412Snewton
140243412Snewton#ifdef DEBUG_SVR4
140343412Snewton	if ((error = show_ioc(">", &ioc)) != 0)
140443412Snewton		return error;
140543412Snewton#endif /* DEBUG_SVR4 */
140643412Snewton
140743412Snewton	switch (ioc.cmd & 0xff00) {
140843412Snewton	case SVR4_SIMOD:
140983366Sjulian		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
141043412Snewton			return error;
141143412Snewton		break;
141243412Snewton
141343412Snewton	case SVR4_TIMOD:
141483366Sjulian		if ((error = timod(fp, fd, &ioc, td)) != 0)
141543412Snewton			return error;
141643412Snewton		break;
141743412Snewton
141843412Snewton	default:
141943412Snewton		DPRINTF(("Unimplemented module %c %ld\n",
142043412Snewton			 (char) (cmd >> 8), cmd & 0xff));
142143412Snewton		return 0;
142243412Snewton	}
142343412Snewton
142443412Snewton#ifdef DEBUG_SVR4
142543412Snewton	if ((error = show_ioc("<", &ioc)) != 0)
142643412Snewton		return error;
142743412Snewton#endif /* DEBUG_SVR4 */
142843412Snewton	return copyout(&ioc, dat, sizeof(ioc));
142943412Snewton}
143043412Snewton
143143412Snewtonstatic int
143283366Sjuliani_setsig(fp, td, retval, fd, cmd, dat)
143343412Snewton	struct file *fp;
143483366Sjulian	struct thread *td;
143543412Snewton	register_t *retval;
143643412Snewton	int fd;
143743412Snewton	u_long cmd;
143843412Snewton	caddr_t dat;
143943412Snewton{
144043412Snewton	/*
144143412Snewton	 * This is the best we can do for now; we cannot generate
144243412Snewton	 * signals only for specific events so the signal mask gets
144343412Snewton	 * ignored; we save it just to pass it to a possible I_GETSIG...
144443412Snewton	 *
144543412Snewton	 * We alse have to fix the O_ASYNC fcntl bit, so the
144643412Snewton	 * process will get SIGPOLLs.
144743412Snewton	 */
144843412Snewton	struct fcntl_args fa;
144943412Snewton	int error;
145043412Snewton	register_t oflags, flags;
145143412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
145243412Snewton
145343412Snewton	if (st == NULL) {
145443412Snewton		DPRINTF(("i_setsig: bad file descriptor\n"));
145543412Snewton		return EINVAL;
145643412Snewton	}
145743412Snewton	/* get old status flags */
145843412Snewton	SCARG(&fa, fd) = fd;
145943412Snewton	SCARG(&fa, cmd) = F_GETFL;
146083366Sjulian	if ((error = fcntl(td, &fa)) != 0)
146143412Snewton		return error;
146243412Snewton
146383366Sjulian	oflags = td->td_retval[0];
146443412Snewton
146543412Snewton	/* update the flags */
146643412Snewton	if (dat != NULL) {
146743412Snewton		int mask;
146843412Snewton
146943412Snewton		flags = oflags | O_ASYNC;
147043412Snewton		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
147143412Snewton			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
147243412Snewton			  return error;
147343412Snewton		}
147443412Snewton		if (mask & SVR4_S_ALLMASK) {
147543412Snewton			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
147643412Snewton			  return EINVAL;
147743412Snewton		}
147843412Snewton		st->s_eventmask = mask;
147943412Snewton	}
148043412Snewton	else {
148143412Snewton		flags = oflags & ~O_ASYNC;
148243412Snewton		st->s_eventmask = 0;
148343412Snewton	}
148443412Snewton
148543412Snewton	/* set the new flags, if changed */
148643412Snewton	if (flags != oflags) {
148743412Snewton		SCARG(&fa, cmd) = F_SETFL;
148843412Snewton		SCARG(&fa, arg) = (long) flags;
148983366Sjulian		if ((error = fcntl(td, &fa)) != 0)
149043412Snewton			  return error;
149183366Sjulian		flags = td->td_retval[0];
149243412Snewton	}
149343412Snewton
149443412Snewton	/* set up SIGIO receiver if needed */
149543412Snewton	if (dat != NULL) {
149643412Snewton		SCARG(&fa, cmd) = F_SETOWN;
149783366Sjulian		SCARG(&fa, arg) = (long) td->td_proc->p_pid;
149883366Sjulian		return fcntl(td, &fa);
149943412Snewton	}
150043412Snewton	return 0;
150143412Snewton}
150243412Snewton
150343412Snewtonstatic int
150483366Sjuliani_getsig(fp, td, retval, fd, cmd, dat)
150543412Snewton	struct file *fp;
150683366Sjulian	struct thread *td;
150743412Snewton	register_t *retval;
150843412Snewton	int fd;
150943412Snewton	u_long cmd;
151043412Snewton	caddr_t dat;
151143412Snewton{
151243412Snewton	int error;
151343412Snewton
151443412Snewton	if (dat != NULL) {
151543412Snewton		struct svr4_strm *st = svr4_stream_get(fp);
151643412Snewton
151743412Snewton		if (st == NULL) {
151843412Snewton			DPRINTF(("i_getsig: bad file descriptor\n"));
151943412Snewton			return EINVAL;
152043412Snewton		}
152143412Snewton		if ((error = copyout(&st->s_eventmask, dat,
152243412Snewton				     sizeof(st->s_eventmask))) != 0) {
152343412Snewton			DPRINTF(("i_getsig: bad eventmask pointer\n"));
152443412Snewton			return error;
152543412Snewton		}
152643412Snewton	}
152743412Snewton	return 0;
152843412Snewton}
152943412Snewton
153043412Snewtonint
153183366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
153243412Snewton	struct file *fp;
153383366Sjulian	struct thread *td;
153443412Snewton	register_t *retval;
153543412Snewton	int fd;
153643412Snewton	u_long cmd;
153743412Snewton	caddr_t dat;
153843412Snewton{
153943412Snewton	*retval = 0;
154043412Snewton
154143412Snewton	/*
154243412Snewton	 * All the following stuff assumes "sockmod" is pushed...
154343412Snewton	 */
154443412Snewton	switch (cmd) {
154543412Snewton	case SVR4_I_NREAD:
154643412Snewton		DPRINTF(("I_NREAD\n"));
154783366Sjulian		return i_nread(fp, td, retval, fd, cmd, dat);
154843412Snewton
154943412Snewton	case SVR4_I_PUSH:
155080114Sassar		DPRINTF(("I_PUSH %p\n", dat));
155143412Snewton#if defined(DEBUG_SVR4)
155280114Sassar		show_strbuf((struct svr4_strbuf *)dat);
155343412Snewton#endif
155443412Snewton		return 0;
155543412Snewton
155643412Snewton	case SVR4_I_POP:
155743412Snewton		DPRINTF(("I_POP\n"));
155843412Snewton		return 0;
155943412Snewton
156043412Snewton	case SVR4_I_LOOK:
156143412Snewton		DPRINTF(("I_LOOK\n"));
156243412Snewton		return 0;
156343412Snewton
156443412Snewton	case SVR4_I_FLUSH:
156543412Snewton		DPRINTF(("I_FLUSH\n"));
156643412Snewton		return 0;
156743412Snewton
156843412Snewton	case SVR4_I_SRDOPT:
156943412Snewton		DPRINTF(("I_SRDOPT\n"));
157043412Snewton		return 0;
157143412Snewton
157243412Snewton	case SVR4_I_GRDOPT:
157343412Snewton		DPRINTF(("I_GRDOPT\n"));
157443412Snewton		return 0;
157543412Snewton
157643412Snewton	case SVR4_I_STR:
157743412Snewton		DPRINTF(("I_STR\n"));
157883366Sjulian		return i_str(fp, td, retval, fd, cmd, dat);
157943412Snewton
158043412Snewton	case SVR4_I_SETSIG:
158143412Snewton		DPRINTF(("I_SETSIG\n"));
158283366Sjulian		return i_setsig(fp, td, retval, fd, cmd, dat);
158343412Snewton
158443412Snewton	case SVR4_I_GETSIG:
158543412Snewton	        DPRINTF(("I_GETSIG\n"));
158683366Sjulian		return i_getsig(fp, td, retval, fd, cmd, dat);
158743412Snewton
158843412Snewton	case SVR4_I_FIND:
158943412Snewton		DPRINTF(("I_FIND\n"));
159043412Snewton		/*
159143412Snewton		 * Here we are not pushing modules really, we just
159243412Snewton		 * pretend all are present
159343412Snewton		 */
159443412Snewton		*retval = 0;
159543412Snewton		return 0;
159643412Snewton
159743412Snewton	case SVR4_I_LINK:
159843412Snewton		DPRINTF(("I_LINK\n"));
159943412Snewton		return 0;
160043412Snewton
160143412Snewton	case SVR4_I_UNLINK:
160243412Snewton		DPRINTF(("I_UNLINK\n"));
160343412Snewton		return 0;
160443412Snewton
160543412Snewton	case SVR4_I_ERECVFD:
160643412Snewton		DPRINTF(("I_ERECVFD\n"));
160743412Snewton		return 0;
160843412Snewton
160943412Snewton	case SVR4_I_PEEK:
161043412Snewton		DPRINTF(("I_PEEK\n"));
161143412Snewton		return 0;
161243412Snewton
161343412Snewton	case SVR4_I_FDINSERT:
161443412Snewton		DPRINTF(("I_FDINSERT\n"));
161583366Sjulian		return i_fdinsert(fp, td, retval, fd, cmd, dat);
161643412Snewton
161743412Snewton	case SVR4_I_SENDFD:
161843412Snewton		DPRINTF(("I_SENDFD\n"));
161943412Snewton		return 0;
162043412Snewton
162143412Snewton	case SVR4_I_RECVFD:
162243412Snewton		DPRINTF(("I_RECVFD\n"));
162343412Snewton		return 0;
162443412Snewton
162543412Snewton	case SVR4_I_SWROPT:
162643412Snewton		DPRINTF(("I_SWROPT\n"));
162743412Snewton		return 0;
162843412Snewton
162943412Snewton	case SVR4_I_GWROPT:
163043412Snewton		DPRINTF(("I_GWROPT\n"));
163143412Snewton		return 0;
163243412Snewton
163343412Snewton	case SVR4_I_LIST:
163443412Snewton		DPRINTF(("I_LIST\n"));
163543412Snewton		return 0;
163643412Snewton
163743412Snewton	case SVR4_I_PLINK:
163843412Snewton		DPRINTF(("I_PLINK\n"));
163943412Snewton		return 0;
164043412Snewton
164143412Snewton	case SVR4_I_PUNLINK:
164243412Snewton		DPRINTF(("I_PUNLINK\n"));
164343412Snewton		return 0;
164443412Snewton
164543412Snewton	case SVR4_I_SETEV:
164643412Snewton		DPRINTF(("I_SETEV\n"));
164743412Snewton		return 0;
164843412Snewton
164943412Snewton	case SVR4_I_GETEV:
165043412Snewton		DPRINTF(("I_GETEV\n"));
165143412Snewton		return 0;
165243412Snewton
165343412Snewton	case SVR4_I_STREV:
165443412Snewton		DPRINTF(("I_STREV\n"));
165543412Snewton		return 0;
165643412Snewton
165743412Snewton	case SVR4_I_UNSTREV:
165843412Snewton		DPRINTF(("I_UNSTREV\n"));
165943412Snewton		return 0;
166043412Snewton
166143412Snewton	case SVR4_I_FLUSHBAND:
166243412Snewton		DPRINTF(("I_FLUSHBAND\n"));
166343412Snewton		return 0;
166443412Snewton
166543412Snewton	case SVR4_I_CKBAND:
166643412Snewton		DPRINTF(("I_CKBAND\n"));
166743412Snewton		return 0;
166843412Snewton
166943412Snewton	case SVR4_I_GETBAND:
167043412Snewton		DPRINTF(("I_GETBANK\n"));
167143412Snewton		return 0;
167243412Snewton
167343412Snewton	case SVR4_I_ATMARK:
167443412Snewton		DPRINTF(("I_ATMARK\n"));
167543412Snewton		return 0;
167643412Snewton
167743412Snewton	case SVR4_I_SETCLTIME:
167843412Snewton		DPRINTF(("I_SETCLTIME\n"));
167943412Snewton		return 0;
168043412Snewton
168143412Snewton	case SVR4_I_GETCLTIME:
168243412Snewton		DPRINTF(("I_GETCLTIME\n"));
168343412Snewton		return 0;
168443412Snewton
168543412Snewton	case SVR4_I_CANPUT:
168643412Snewton		DPRINTF(("I_CANPUT\n"));
168743412Snewton		return 0;
168843412Snewton
168943412Snewton	case SVR4__I_BIND_RSVD:
169043412Snewton		DPRINTF(("_I_BIND_RSVD\n"));
169183366Sjulian		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
169243412Snewton
169343412Snewton	case SVR4__I_RELE_RSVD:
169443412Snewton		DPRINTF(("_I_RELE_RSVD\n"));
169583366Sjulian		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
169643412Snewton
169743412Snewton	default:
169843412Snewton		DPRINTF(("unimpl cmd = %lx\n", cmd));
169943412Snewton		break;
170043412Snewton	}
170143412Snewton
170243412Snewton	return 0;
170343412Snewton}
170443412Snewton
170543412Snewton
170643412Snewton
170743412Snewtonint
170883366Sjuliansvr4_sys_putmsg(td, uap)
170983366Sjulian	register struct thread *td;
171043412Snewton	struct svr4_sys_putmsg_args *uap;
171143412Snewton{
171289306Salfred	struct file     *fp;
171389306Salfred	int error;
171489306Salfred
171589319Salfred	if ((error = fget(td, uap->fd, &fp)) != 0) {
171689306Salfred#ifdef DEBUG_SVR4
171789306Salfred	        uprintf("putmsg: bad fp\n");
171889306Salfred#endif
171989306Salfred		return EBADF;
172089306Salfred	}
172189306Salfred	error = svr4_do_putmsg(td, uap, fp);
172289306Salfred	fdrop(fp, td);
172389306Salfred	return (error);
172489306Salfred}
172589306Salfred
172689306Salfredstatic int
172789306Salfredsvr4_do_putmsg(td, uap, fp)
172889306Salfred	struct thread *td;
172989306Salfred	struct svr4_sys_putmsg_args *uap;
173043412Snewton	struct file	*fp;
173189306Salfred{
173243412Snewton	struct svr4_strbuf dat, ctl;
173343412Snewton	struct svr4_strmcmd sc;
173443412Snewton	struct sockaddr_in sain;
173543412Snewton	struct sockaddr_un saun;
173643412Snewton	void *skp, *sup;
173743412Snewton	int sasize, *retval;
173843412Snewton	struct svr4_strm *st;
173943412Snewton	int error;
174043412Snewton	caddr_t sg;
174143412Snewton
174283366Sjulian	retval = td->td_retval;
174354493Snewton
174443412Snewton#ifdef DEBUG_SVR4
174543412Snewton	show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
174643412Snewton		 SCARG(uap, dat), SCARG(uap, flags));
174743412Snewton#endif /* DEBUG_SVR4 */
174843412Snewton
174989306Salfred	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
175043412Snewton
175143412Snewton	if (SCARG(uap, ctl) != NULL) {
175243412Snewton	  if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
175343412Snewton#ifdef DEBUG_SVR4
175443412Snewton	    uprintf("putmsg: copyin(): %d\n", error);
175543412Snewton#endif
175643412Snewton	    return error;
175743412Snewton	  }
175843412Snewton	}
175943412Snewton	else
176043412Snewton		ctl.len = -1;
176143412Snewton
176243412Snewton	if (SCARG(uap, dat) != NULL) {
176343412Snewton	  if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
176443412Snewton#ifdef DEBUG_SVR4
176543412Snewton	    uprintf("putmsg: copyin(): %d (2)\n", error);
176643412Snewton#endif
176743412Snewton	    return error;
176843412Snewton	  }
176943412Snewton	}
177043412Snewton	else
177143412Snewton		dat.len = -1;
177243412Snewton
177343412Snewton	/*
177443412Snewton	 * Only for sockets for now.
177543412Snewton	 */
177643412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
177743412Snewton		DPRINTF(("putmsg: bad file type\n"));
177843412Snewton		return EINVAL;
177943412Snewton	}
178043412Snewton
178143412Snewton	if (ctl.len > sizeof(sc)) {
178243412Snewton		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
178343412Snewton			 sizeof(struct svr4_strmcmd)));
178443412Snewton		return EINVAL;
178543412Snewton	}
178643412Snewton
178743412Snewton	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
178843412Snewton		return error;
178943412Snewton
179043412Snewton	switch (st->s_family) {
179143412Snewton	case AF_INET:
179243412Snewton	        if (sc.len != sizeof(sain)) {
179343412Snewton		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
179443412Snewton			        struct write_args wa;
179543412Snewton
179643412Snewton				/* Solaris seems to use sc.cmd = 3 to
179743412Snewton				 * send "expedited" data.  telnet uses
179843412Snewton				 * this for options processing, sending EOF,
179943412Snewton				 * etc.  I'm sure other things use it too.
180043412Snewton				 * I don't have any documentation
180143412Snewton				 * on it, so I'm making a guess that this
180243412Snewton				 * is how it works. newton@atdot.dotat.org XXX
180343412Snewton				 */
180451844Speter				DPRINTF(("sending expedited data ??\n"));
180543412Snewton				SCARG(&wa, fd) = SCARG(uap, fd);
180643412Snewton				SCARG(&wa, buf) = dat.buf;
180743412Snewton				SCARG(&wa, nbyte) = dat.len;
180883366Sjulian				return write(td, &wa);
180943412Snewton			}
181043412Snewton	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
181143412Snewton	                return EINVAL;
181243412Snewton	        }
181343412Snewton	        netaddr_to_sockaddr_in(&sain, &sc);
181443412Snewton	        skp = &sain;
181543412Snewton	        sasize = sizeof(sain);
181643412Snewton	        error = sain.sin_family != st->s_family;
181743412Snewton		break;
181843412Snewton
181943412Snewton	case AF_LOCAL:
182043412Snewton		if (ctl.len == 8) {
182143412Snewton			/* We are doing an accept; succeed */
182243412Snewton			DPRINTF(("putmsg: Do nothing\n"));
182343412Snewton			*retval = 0;
182443412Snewton			return 0;
182543412Snewton		}
182643412Snewton		else {
182743412Snewton			/* Maybe we've been given a device/inode pair */
182849267Snewton			udev_t *dev = SVR4_ADDROF(&sc);
182943412Snewton			ino_t *ino = (ino_t *) &dev[1];
183083366Sjulian			skp = svr4_find_socket(td, fp, *dev, *ino);
183143412Snewton			if (skp == NULL) {
183243412Snewton				skp = &saun;
183343412Snewton				/* I guess we have it by name */
183443412Snewton				netaddr_to_sockaddr_un(skp, &sc);
183543412Snewton			}
183643412Snewton			sasize = sizeof(saun);
183743412Snewton		}
183843412Snewton		break;
183943412Snewton
184043412Snewton	default:
184143412Snewton		DPRINTF(("putmsg: Unsupported address family %d\n",
184243412Snewton			 st->s_family));
184343412Snewton		return ENOSYS;
184443412Snewton	}
184543412Snewton
184643412Snewton	sg = stackgap_init();
184743412Snewton	sup = stackgap_alloc(&sg, sasize);
184843412Snewton
184943412Snewton	if ((error = copyout(skp, sup, sasize)) != 0)
185043412Snewton		return error;
185143412Snewton
185243412Snewton	switch (st->s_cmd = sc.cmd) {
185343412Snewton	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
185443412Snewton		{
185543412Snewton			struct connect_args co;
185643412Snewton
185743412Snewton			SCARG(&co, s) = SCARG(uap, fd);
185843412Snewton			SCARG(&co, name) = (void *) sup;
185943412Snewton			SCARG(&co, namelen) = (int) sasize;
186043412Snewton
186183366Sjulian			return connect(td, &co);
186243412Snewton		}
186343412Snewton
186443412Snewton	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
186543412Snewton		{
186643412Snewton			struct msghdr msg;
186743412Snewton			struct iovec aiov;
186843412Snewton
186943412Snewton			msg.msg_name = (caddr_t) sup;
187043412Snewton			msg.msg_namelen = sasize;
187143412Snewton			msg.msg_iov = &aiov;
187243412Snewton			msg.msg_iovlen = 1;
187343412Snewton			msg.msg_control = 0;
187443412Snewton			msg.msg_flags = 0;
187543412Snewton			aiov.iov_base = dat.buf;
187643412Snewton			aiov.iov_len = dat.len;
187743412Snewton#if 0
187843412Snewton			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
187983366Sjulian					      uio, 0, 0, 0, uio->uio_td);
188043412Snewton#endif
188183366Sjulian			error = svr4_sendit(td, SCARG(uap, fd), &msg,
188243412Snewton				       SCARG(uap, flags));
188343412Snewton			DPRINTF(("sendto_request error: %d\n", error));
188443412Snewton			*retval = 0;
188543412Snewton			return error;
188643412Snewton		}
188743412Snewton
188843412Snewton	default:
188943412Snewton		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
189043412Snewton		return ENOSYS;
189143412Snewton	}
189243412Snewton}
189343412Snewton
189443412Snewtonint
189589308Salfredsvr4_sys_getmsg(td, uap)
189689308Salfred	struct thread *td;
189789306Salfred	struct svr4_sys_getmsg_args *uap;
189889306Salfred{
189989306Salfred	struct file     *fp;
190089306Salfred	int error;
190189306Salfred
190289319Salfred	if ((error = fget(td, uap->fd, &fp)) != 0) {
190389306Salfred#ifdef DEBUG_SVR4
190489306Salfred	        uprintf("getmsg: bad fp\n");
190589306Salfred#endif
190689306Salfred		return EBADF;
190789306Salfred	}
190889308Salfred	error = svr4_do_getmsg(td, uap, fp);
190989306Salfred	fdrop(fp, td);
191089306Salfred	return (error);
191189306Salfred}
191289306Salfred
191389306Salfredint
191489536Salfredsvr4_do_getmsg(td, uap, fp)
191583366Sjulian	register struct thread *td;
191643412Snewton	struct svr4_sys_getmsg_args *uap;
191789306Salfred	struct file *fp;
191843412Snewton{
191943412Snewton	struct getpeername_args ga;
192043412Snewton	struct accept_args aa;
192143412Snewton	struct svr4_strbuf dat, ctl;
192243412Snewton	struct svr4_strmcmd sc;
192343412Snewton	int error, *retval;
192443412Snewton	struct msghdr msg;
192543412Snewton	struct iovec aiov;
192643412Snewton	struct sockaddr_in sain;
192743412Snewton	struct sockaddr_un saun;
192843412Snewton	void *skp, *sup;
192943412Snewton	int sasize;
193043412Snewton	struct svr4_strm *st;
193143412Snewton	int *flen;
193243412Snewton	int fl;
193343412Snewton	caddr_t sg;
193443412Snewton
193583366Sjulian	retval = td->td_retval;
193654493Snewton
193789306Salfred	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
193843412Snewton
193943412Snewton	memset(&sc, 0, sizeof(sc));
194043412Snewton
194143412Snewton#ifdef DEBUG_SVR4
194243412Snewton	show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
194343412Snewton		 SCARG(uap, dat), 0);
194443412Snewton#endif /* DEBUG_SVR4 */
194543412Snewton
194643412Snewton	if (SCARG(uap, ctl) != NULL) {
194743412Snewton		if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
194843412Snewton			return error;
194943412Snewton	}
195043412Snewton	else {
195143412Snewton		ctl.len = -1;
195243412Snewton		ctl.maxlen = 0;
195343412Snewton	}
195443412Snewton
195543412Snewton	if (SCARG(uap, dat) != NULL) {
195643412Snewton	    	if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
195743412Snewton			return error;
195843412Snewton	}
195943412Snewton	else {
196043412Snewton		dat.len = -1;
196143412Snewton		dat.maxlen = 0;
196243412Snewton	}
196343412Snewton
196443412Snewton	/*
196543412Snewton	 * Only for sockets for now.
196643412Snewton	 */
196743412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
196843412Snewton		DPRINTF(("getmsg: bad file type\n"));
196943412Snewton		return EINVAL;
197043412Snewton	}
197143412Snewton
197243412Snewton	if (ctl.maxlen == -1 || dat.maxlen == -1) {
197343412Snewton		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
197443412Snewton		return ENOSYS;
197543412Snewton	}
197643412Snewton
197743412Snewton	switch (st->s_family) {
197843412Snewton	case AF_INET:
197943412Snewton		skp = &sain;
198043412Snewton		sasize = sizeof(sain);
198143412Snewton		break;
198243412Snewton
198343412Snewton	case AF_LOCAL:
198443412Snewton		skp = &saun;
198543412Snewton		sasize = sizeof(saun);
198643412Snewton		break;
198743412Snewton
198843412Snewton	default:
198943412Snewton		DPRINTF(("getmsg: Unsupported address family %d\n",
199043412Snewton			 st->s_family));
199143412Snewton		return ENOSYS;
199243412Snewton	}
199343412Snewton
199443412Snewton	sg = stackgap_init();
199543412Snewton	sup = stackgap_alloc(&sg, sasize);
199643412Snewton	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
199743412Snewton
199843412Snewton	fl = sasize;
199943412Snewton	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
200043412Snewton		return error;
200143412Snewton
200243412Snewton	switch (st->s_cmd) {
200343412Snewton	case SVR4_TI_CONNECT_REQUEST:
200443412Snewton		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
200543412Snewton		/*
200643412Snewton		 * We do the connect in one step, so the putmsg should
200743412Snewton		 * have gotten the error.
200843412Snewton		 */
200943412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
201043412Snewton		sc.len = 0;
201143412Snewton
201243412Snewton		ctl.len = 8;
201343412Snewton		dat.len = -1;
201443412Snewton		fl = 1;
201543412Snewton		st->s_cmd = sc.cmd;
201643412Snewton		break;
201743412Snewton
201843412Snewton	case SVR4_TI_OK_REPLY:
201943412Snewton		DPRINTF(("getmsg: TI_OK_REPLY\n"));
202043412Snewton		/*
202143412Snewton		 * We are immediately after a connect reply, so we send
202243412Snewton		 * a connect verification.
202343412Snewton		 */
202443412Snewton
202543412Snewton		SCARG(&ga, fdes) = SCARG(uap, fd);
202643412Snewton		SCARG(&ga, asa) = (void *) sup;
202743412Snewton		SCARG(&ga, alen) = flen;
202843412Snewton
202983366Sjulian		if ((error = getpeername(td, &ga)) != 0) {
203043412Snewton			DPRINTF(("getmsg: getpeername failed %d\n", error));
203143412Snewton			return error;
203243412Snewton		}
203343412Snewton
203443412Snewton		if ((error = copyin(sup, skp, sasize)) != 0)
203543412Snewton			return error;
203643412Snewton
203743412Snewton		sc.cmd = SVR4_TI_CONNECT_REPLY;
203843412Snewton		sc.pad[0] = 0x4;
203943412Snewton		sc.offs = 0x18;
204043412Snewton		sc.pad[1] = 0x14;
204143412Snewton		sc.pad[2] = 0x04000402;
204243412Snewton
204343412Snewton		switch (st->s_family) {
204443412Snewton		case AF_INET:
204543412Snewton			sc.len = sasize;
204643412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
204743412Snewton			break;
204843412Snewton
204943412Snewton		case AF_LOCAL:
205043412Snewton			sc.len = sasize + 4;
205143412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
205243412Snewton			break;
205343412Snewton
205443412Snewton		default:
205543412Snewton			return ENOSYS;
205643412Snewton		}
205743412Snewton
205843412Snewton		ctl.len = 40;
205943412Snewton		dat.len = -1;
206043412Snewton		fl = 0;
206143412Snewton		st->s_cmd = sc.cmd;
206243412Snewton		break;
206343412Snewton
206443412Snewton	case SVR4_TI__ACCEPT_OK:
206543412Snewton		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
206643412Snewton		/*
206743412Snewton		 * We do the connect in one step, so the putmsg should
206843412Snewton		 * have gotten the error.
206943412Snewton		 */
207043412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
207143412Snewton		sc.len = 1;
207243412Snewton
207343412Snewton		ctl.len = 8;
207443412Snewton		dat.len = -1;
207543412Snewton		fl = 1;
207643412Snewton		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
207743412Snewton		break;
207843412Snewton
207943412Snewton	case SVR4_TI__ACCEPT_WAIT:
208043412Snewton		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
208143412Snewton		/*
208243412Snewton		 * We are after a listen, so we try to accept...
208343412Snewton		 */
208443412Snewton		SCARG(&aa, s) = SCARG(uap, fd);
208543412Snewton		SCARG(&aa, name) = (void *) sup;
208643412Snewton		SCARG(&aa, anamelen) = flen;
208743412Snewton
208883366Sjulian		if ((error = accept(td, &aa)) != 0) {
208943412Snewton			DPRINTF(("getmsg: accept failed %d\n", error));
209043412Snewton			return error;
209143412Snewton		}
209243412Snewton
209343412Snewton		st->s_afd = *retval;
209443412Snewton
209543412Snewton		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
209643412Snewton
209743412Snewton		if ((error = copyin(sup, skp, sasize)) != 0)
209843412Snewton			return error;
209943412Snewton
210043412Snewton		sc.cmd = SVR4_TI_ACCEPT_REPLY;
210143412Snewton		sc.offs = 0x18;
210243412Snewton		sc.pad[0] = 0x0;
210343412Snewton
210443412Snewton		switch (st->s_family) {
210543412Snewton		case AF_INET:
210643412Snewton			sc.pad[1] = 0x28;
210743412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
210843412Snewton			ctl.len = 40;
210943412Snewton			sc.len = sasize;
211043412Snewton			break;
211143412Snewton
211243412Snewton		case AF_LOCAL:
211343412Snewton			sc.pad[1] = 0x00010000;
211443412Snewton			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
211543412Snewton			sc.pad[3] = 0x00010000;
211643412Snewton			ctl.len = 134;
211743412Snewton			sc.len = sasize + 4;
211843412Snewton			break;
211943412Snewton
212043412Snewton		default:
212143412Snewton			return ENOSYS;
212243412Snewton		}
212343412Snewton
212443412Snewton		dat.len = -1;
212543412Snewton		fl = 0;
212643412Snewton		st->s_cmd = SVR4_TI__ACCEPT_OK;
212743412Snewton		break;
212843412Snewton
212943412Snewton	case SVR4_TI_SENDTO_REQUEST:
213043412Snewton		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
213143412Snewton		if (ctl.maxlen > 36 && ctl.len < 36)
213243412Snewton		    ctl.len = 36;
213343412Snewton
213443412Snewton		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
213543412Snewton			return error;
213643412Snewton
213743412Snewton		switch (st->s_family) {
213843412Snewton		case AF_INET:
213943412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
214043412Snewton			break;
214143412Snewton
214243412Snewton		case AF_LOCAL:
214343412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
214443412Snewton			break;
214543412Snewton
214643412Snewton		default:
214743412Snewton			return ENOSYS;
214843412Snewton		}
214943412Snewton
215043412Snewton		msg.msg_name = (caddr_t) sup;
215143412Snewton		msg.msg_namelen = sasize;
215243412Snewton		msg.msg_iov = &aiov;
215343412Snewton		msg.msg_iovlen = 1;
215443412Snewton		msg.msg_control = 0;
215543412Snewton		aiov.iov_base = dat.buf;
215643412Snewton		aiov.iov_len = dat.maxlen;
215743412Snewton		msg.msg_flags = 0;
215843412Snewton
215983366Sjulian		error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen);
216043412Snewton
216143412Snewton		if (error) {
216243412Snewton			DPRINTF(("getmsg: recvit failed %d\n", error));
216343412Snewton			return error;
216443412Snewton		}
216543412Snewton
216643412Snewton		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
216743412Snewton			return error;
216843412Snewton
216943412Snewton		sc.cmd = SVR4_TI_RECVFROM_IND;
217043412Snewton
217143412Snewton		switch (st->s_family) {
217243412Snewton		case AF_INET:
217343412Snewton			sc.len = sasize;
217443412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
217543412Snewton			break;
217643412Snewton
217743412Snewton		case AF_LOCAL:
217843412Snewton			sc.len = sasize + 4;
217943412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
218043412Snewton			break;
218143412Snewton
218243412Snewton		default:
218343412Snewton			return ENOSYS;
218443412Snewton		}
218543412Snewton
218643412Snewton		dat.len = *retval;
218743412Snewton		fl = 0;
218843412Snewton		st->s_cmd = sc.cmd;
218943412Snewton		break;
219043412Snewton
219143412Snewton	default:
219243412Snewton		st->s_cmd = sc.cmd;
219343412Snewton		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
219443412Snewton		        struct read_args ra;
219543412Snewton
219672082Sasmodai			/* More weirdness:  Again, I can't find documentation
219743412Snewton			 * to back this up, but when a process does a generic
219843412Snewton			 * "getmsg()" call it seems that the command field is
219943412Snewton			 * zero and the length of the data area is zero.  I
220043412Snewton			 * think processes expect getmsg() to fill in dat.len
220143412Snewton			 * after reading at most dat.maxlen octets from the
220243412Snewton			 * stream.  Since we're using sockets I can let
220343412Snewton			 * read() look after it and frob return values
220443412Snewton			 * appropriately (or inappropriately :-)
220543412Snewton			 *   -- newton@atdot.dotat.org        XXX
220643412Snewton			 */
220743412Snewton			SCARG(&ra, fd) = SCARG(uap, fd);
220843412Snewton			SCARG(&ra, buf) = dat.buf;
220943412Snewton			SCARG(&ra, nbyte) = dat.maxlen;
221083366Sjulian			if ((error = read(td, &ra)) != 0) {
221143412Snewton			        return error;
221243412Snewton			}
221343412Snewton			dat.len = *retval;
221443412Snewton			*retval = 0;
221543412Snewton			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
221643412Snewton			break;
221743412Snewton		}
221843412Snewton		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
221943412Snewton		return EINVAL;
222043412Snewton	}
222143412Snewton
222243412Snewton	if (SCARG(uap, ctl)) {
222343412Snewton		if (ctl.len != -1)
222443412Snewton			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
222543412Snewton				return error;
222643412Snewton
222743412Snewton		if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
222843412Snewton			return error;
222943412Snewton	}
223043412Snewton
223143412Snewton	if (SCARG(uap, dat)) {
223243412Snewton		if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
223343412Snewton			return error;
223443412Snewton	}
223543412Snewton
223643412Snewton	if (SCARG(uap, flags)) { /* XXX: Need translation */
223743412Snewton		if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
223843412Snewton			return error;
223943412Snewton	}
224043412Snewton
224143412Snewton	*retval = 0;
224243412Snewton
224343412Snewton#ifdef DEBUG_SVR4
224443412Snewton	show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
224543412Snewton		 SCARG(uap, dat), fl);
224643412Snewton#endif /* DEBUG_SVR4 */
224743412Snewton	return error;
224843412Snewton}
224943412Snewton
225083366Sjulianint svr4_sys_send(td, uap)
225183366Sjulian	struct thread *td;
225243412Snewton	struct svr4_sys_send_args *uap;
225343412Snewton{
225443412Snewton	struct osend_args osa;
225543412Snewton	SCARG(&osa, s) = SCARG(uap, s);
225643412Snewton	SCARG(&osa, buf) = SCARG(uap, buf);
225743412Snewton	SCARG(&osa, len) = SCARG(uap, len);
225843412Snewton	SCARG(&osa, flags) = SCARG(uap, flags);
225983366Sjulian	return osend(td, &osa);
226043412Snewton}
226143412Snewton
226283366Sjulianint svr4_sys_recv(td, uap)
226383366Sjulian	struct thread *td;
226443412Snewton	struct svr4_sys_recv_args *uap;
226543412Snewton{
226643412Snewton	struct orecv_args ora;
226743412Snewton	SCARG(&ora, s) = SCARG(uap, s);
226843412Snewton	SCARG(&ora, buf) = SCARG(uap, buf);
226943412Snewton	SCARG(&ora, len) = SCARG(uap, len);
227043412Snewton	SCARG(&ora, flags) = SCARG(uap, flags);
227183366Sjulian	return orecv(td, &ora);
227243412Snewton}
227343412Snewton
227443412Snewton/*
227543412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into
227643412Snewton * sendto().  Let's leave it here for now...
227743412Snewton */
227843412Snewtonint
227983366Sjuliansvr4_sys_sendto(td, uap)
228083366Sjulian        struct thread *td;
228143412Snewton        struct svr4_sys_sendto_args *uap;
228243412Snewton{
228343412Snewton        struct sendto_args sa;
228443412Snewton
228543412Snewton	SCARG(&sa, s) = SCARG(uap, s);
228643412Snewton	SCARG(&sa, buf) = SCARG(uap, buf);
228743412Snewton	SCARG(&sa, len) = SCARG(uap, len);
228843412Snewton	SCARG(&sa, flags) = SCARG(uap, flags);
228980114Sassar	SCARG(&sa, to) = (caddr_t)SCARG(uap, to);
229043412Snewton	SCARG(&sa, tolen) = SCARG(uap, tolen);
229143412Snewton
229243412Snewton	DPRINTF(("calling sendto()\n"));
229383366Sjulian	return sendto(td, &sa);
229443412Snewton}
229543412Snewton
2296