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