1139743Simp/*-
243412Snewton * Copyright (c) 1998 Mark Newton.  All rights reserved.
343412Snewton * Copyright (c) 1994, 1996 Christos Zoulas.  All rights reserved.
443412Snewton *
543412Snewton * Redistribution and use in source and binary forms, with or without
643412Snewton * modification, are permitted provided that the following conditions
743412Snewton * are met:
843412Snewton * 1. Redistributions of source code must retain the above copyright
943412Snewton *    notice, this list of conditions and the following disclaimer.
1043412Snewton * 2. Redistributions in binary form must reproduce the above copyright
1143412Snewton *    notice, this list of conditions and the following disclaimer in the
1243412Snewton *    documentation and/or other materials provided with the distribution.
1343412Snewton * 3. All advertising materials mentioning features or use of this software
1443412Snewton *    must display the following acknowledgement:
1543412Snewton *	This product includes software developed by Christos Zoulas.
1643412Snewton * 4. The name of the author may not be used to endorse or promote products
1743412Snewton *    derived from this software without specific prior written permission.
1843412Snewton *
1943412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2043412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2143412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2243412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2343412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2443412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2543412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2643412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2743412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2843412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2943412Snewton */
3043412Snewton
3143412Snewton/*
3243412Snewton * Pretend that we have streams...
3343412Snewton * Yes, this is gross.
3443412Snewton *
3543412Snewton * ToDo: The state machine for getmsg needs re-thinking
3643412Snewton */
3743412Snewton
38116174Sobrien#include <sys/cdefs.h>
39116174Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/compat/svr4/svr4_stream.c 280258 2015-03-19 13:37:36Z rwatson $");
40116174Sobrien
41147965Sjhb#include "opt_compat.h"
42147965Sjhb#include "opt_ktrace.h"
43104571Srwatson
4443412Snewton#include <sys/param.h>
4543412Snewton#include <sys/systm.h>
46280258Srwatson#include <sys/capsicum.h>
4776166Smarkm#include <sys/fcntl.h>
4843412Snewton#include <sys/filedesc.h>
4943412Snewton#include <sys/filio.h>
5076166Smarkm#include <sys/lock.h>
5176166Smarkm#include <sys/malloc.h>
5276166Smarkm#include <sys/file.h> 		/* Must come after sys/malloc.h */
5343412Snewton#include <sys/mbuf.h>
5476166Smarkm#include <sys/mutex.h>
5576166Smarkm#include <sys/proc.h>
5643412Snewton#include <sys/protosw.h>
5743412Snewton#include <sys/signal.h>
5843412Snewton#include <sys/signalvar.h>
5976166Smarkm#include <sys/socket.h>
6076166Smarkm#include <sys/socketvar.h>
6143412Snewton#include <sys/stat.h>
62134266Sjhb#include <sys/syscallsubr.h>
6343412Snewton#include <sys/sysproto.h>
6476166Smarkm#include <sys/uio.h>
6576166Smarkm#include <sys/ktrace.h>		/* Must come after sys/uio.h */
6676166Smarkm#include <sys/un.h>
6743412Snewton
6876166Smarkm#include <netinet/in.h>
6976166Smarkm
7065302Sobrien#include <compat/svr4/svr4.h>
7165302Sobrien#include <compat/svr4/svr4_types.h>
7265302Sobrien#include <compat/svr4/svr4_util.h>
7365302Sobrien#include <compat/svr4/svr4_signal.h>
7465302Sobrien#include <compat/svr4/svr4_proto.h>
7565302Sobrien#include <compat/svr4/svr4_stropts.h>
7665302Sobrien#include <compat/svr4/svr4_timod.h>
7765302Sobrien#include <compat/svr4/svr4_sockmod.h>
7865302Sobrien#include <compat/svr4/svr4_ioctl.h>
7965302Sobrien#include <compat/svr4/svr4_socket.h>
8043412Snewton
8143412Snewton/* Utils */
82141486Sjhbstatic int clean_pipe(struct thread *, char *);
8392761Salfredstatic void getparm(struct file *, struct svr4_si_sockparms *);
8492761Salfredstatic int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
8592761Salfred			       struct file *);
8692761Salfredstatic int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
8792761Salfred			       struct file *);
8843412Snewton
8943412Snewton/* Address Conversions */
9092761Salfredstatic void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
9192761Salfred					const struct sockaddr_in *);
9292761Salfredstatic void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
9392761Salfred					const struct sockaddr_un *);
9492761Salfredstatic void netaddr_to_sockaddr_in(struct sockaddr_in *,
9592761Salfred					const struct svr4_strmcmd *);
9692761Salfredstatic void netaddr_to_sockaddr_un(struct sockaddr_un *,
9792761Salfred					const struct svr4_strmcmd *);
9843412Snewton
9943412Snewton/* stream ioctls */
10092761Salfredstatic int i_nread(struct file *, struct thread *, register_t *, int,
10192761Salfred			u_long, caddr_t);
10292761Salfredstatic int i_fdinsert(struct file *, struct thread *, register_t *, int,
10392761Salfred			   u_long, caddr_t);
10492761Salfredstatic int i_str(struct file *, struct thread *, register_t *, int,
10592761Salfred			u_long, caddr_t);
10692761Salfredstatic int i_setsig(struct file *, struct thread *, register_t *, int,
10792761Salfred			u_long, caddr_t);
10892761Salfredstatic int i_getsig(struct file *, struct thread *, register_t *, int,
10992761Salfred			u_long, caddr_t);
11092761Salfredstatic int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
11192761Salfred			     u_long, caddr_t);
11292761Salfredstatic int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
11392761Salfred			     u_long, caddr_t);
11443412Snewton
11543412Snewton/* i_str sockmod calls */
11692761Salfredstatic int sockmod(struct file *, int, struct svr4_strioctl *,
11792761Salfred			      struct thread *);
11892761Salfredstatic int si_listen(struct file *, int, struct svr4_strioctl *,
11992761Salfred			      struct thread *);
12092761Salfredstatic int si_ogetudata(struct file *, int, struct svr4_strioctl *,
12192761Salfred			      struct thread *);
12292761Salfredstatic int si_sockparams(struct file *, int, struct svr4_strioctl *,
12392761Salfred			      struct thread *);
12492761Salfredstatic int si_shutdown	(struct file *, int, struct svr4_strioctl *,
12592761Salfred			      struct thread *);
12692761Salfredstatic int si_getudata(struct file *, int, struct svr4_strioctl *,
12792761Salfred			      struct thread *);
12843412Snewton
12943412Snewton/* i_str timod calls */
13092761Salfredstatic int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
13192761Salfredstatic int ti_getinfo(struct file *, int, struct svr4_strioctl *,
13292761Salfred			      struct thread *);
13392761Salfredstatic int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
13443412Snewton
13543412Snewton#ifdef DEBUG_SVR4
13692761Salfredstatic void bufprint(u_char *, size_t);
13792761Salfredstatic int show_ioc(const char *, struct svr4_strioctl *);
13892761Salfredstatic int show_strbuf(struct svr4_strbuf *);
13992761Salfredstatic void show_msg(const char *, int, struct svr4_strbuf *,
14092761Salfred			  struct svr4_strbuf *, int);
14143412Snewton
14243412Snewtonstatic void
14343412Snewtonbufprint(buf, len)
14443412Snewton	u_char *buf;
14543412Snewton	size_t len;
14643412Snewton{
14743412Snewton	size_t i;
14843412Snewton
14943412Snewton	uprintf("\n\t");
15043412Snewton	for (i = 0; i < len; i++) {
15143412Snewton		uprintf("%x ", buf[i]);
15243412Snewton		if (i && (i % 16) == 0)
15343412Snewton			uprintf("\n\t");
15443412Snewton	}
15543412Snewton}
15643412Snewton
15743412Snewtonstatic int
15843412Snewtonshow_ioc(str, ioc)
15943412Snewton	const char		*str;
16043412Snewton	struct svr4_strioctl	*ioc;
16143412Snewton{
162121275Stjr	u_char *ptr = NULL;
163121275Stjr	int len;
16443412Snewton	int error;
16543412Snewton
166121275Stjr	len = ioc->len;
167121275Stjr	if (len > 1024)
168121275Stjr		len = 1024;
169121275Stjr
170121275Stjr	if (len > 0) {
171121275Stjr		ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
172121275Stjr		if ((error = copyin(ioc->buf, ptr, len)) != 0) {
173121275Stjr			free((char *) ptr, M_TEMP);
174121275Stjr			return error;
175121275Stjr		}
176121275Stjr	}
177121275Stjr
17843412Snewton	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
17943412Snewton	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
18043412Snewton
181121275Stjr	if (ptr != NULL)
182121275Stjr		bufprint(ptr, len);
18343412Snewton
18443412Snewton	uprintf("}\n");
18543412Snewton
186121275Stjr	if (ptr != NULL)
187121275Stjr		free((char *) ptr, M_TEMP);
18843412Snewton	return 0;
18943412Snewton}
19043412Snewton
19143412Snewton
19243412Snewtonstatic int
19343412Snewtonshow_strbuf(str)
19443412Snewton	struct svr4_strbuf *str;
19543412Snewton{
19643412Snewton	int error;
19743412Snewton	u_char *ptr = NULL;
19843412Snewton	int maxlen = str->maxlen;
19943412Snewton	int len = str->len;
20043412Snewton
201121275Stjr	if (maxlen > 8192)
202121275Stjr		maxlen = 8192;
203121275Stjr
20443412Snewton	if (maxlen < 0)
20543412Snewton		maxlen = 0;
20643412Snewton
20743412Snewton	if (len >= maxlen)
20843412Snewton		len = maxlen;
20943412Snewton
21043412Snewton	if (len > 0) {
211111119Simp	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
21243412Snewton
21343412Snewton	    if ((error = copyin(str->buf, ptr, len)) != 0) {
21443412Snewton		    free((char *) ptr, M_TEMP);
21543412Snewton		    return error;
21643412Snewton	    }
21743412Snewton	}
21843412Snewton
21943412Snewton	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
22043412Snewton
22143412Snewton	if (ptr)
22243412Snewton		bufprint(ptr, len);
22343412Snewton
22443412Snewton	uprintf("]}");
22543412Snewton
22643412Snewton	if (ptr)
22743412Snewton		free((char *) ptr, M_TEMP);
22843412Snewton
22943412Snewton	return 0;
23043412Snewton}
23143412Snewton
23243412Snewton
23343412Snewtonstatic void
23443412Snewtonshow_msg(str, fd, ctl, dat, flags)
23543412Snewton	const char		*str;
23643412Snewton	int			 fd;
23743412Snewton	struct svr4_strbuf	*ctl;
23843412Snewton	struct svr4_strbuf	*dat;
23943412Snewton	int			 flags;
24043412Snewton{
24143412Snewton	struct svr4_strbuf	buf;
24243412Snewton	int error;
24343412Snewton
24443412Snewton	uprintf("%s(%d", str, fd);
24543412Snewton	if (ctl != NULL) {
24643412Snewton		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
24743412Snewton			return;
24843412Snewton		show_strbuf(&buf);
24943412Snewton	}
25043412Snewton	else
25143412Snewton		uprintf(", NULL");
25243412Snewton
25343412Snewton	if (dat != NULL) {
25443412Snewton		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
25543412Snewton			return;
25643412Snewton		show_strbuf(&buf);
25743412Snewton	}
25843412Snewton	else
25943412Snewton		uprintf(", NULL");
26043412Snewton
26143412Snewton	uprintf(", %x);\n", flags);
26243412Snewton}
26343412Snewton
26443412Snewton#endif /* DEBUG_SVR4 */
26543412Snewton
26643412Snewton/*
26743412Snewton * We are faced with an interesting situation. On svr4 unix sockets
26843412Snewton * are really pipes. But we really have sockets, and we might as
26943412Snewton * well use them. At the point where svr4 calls TI_BIND, it has
27043412Snewton * already created a named pipe for the socket using mknod(2).
27143412Snewton * We need to create a socket with the same name when we bind,
27243412Snewton * so we need to remove the pipe before, otherwise we'll get address
27343412Snewton * already in use. So we *carefully* remove the pipe, to avoid
27443412Snewton * using this as a random file removal tool. We use system calls
27543412Snewton * to avoid code duplication.
27643412Snewton */
27743412Snewtonstatic int
27883366Sjulianclean_pipe(td, path)
27983366Sjulian	struct thread *td;
280141486Sjhb	char *path;
28143412Snewton{
28243412Snewton	struct stat st;
28343412Snewton	int error;
28443412Snewton
285141486Sjhb	error = kern_lstat(td, path, UIO_SYSSPACE, &st);
28643412Snewton
28743412Snewton	/*
28843412Snewton	 * Make sure we are dealing with a mode 0 named pipe.
28943412Snewton	 */
29043412Snewton	if ((st.st_mode & S_IFMT) != S_IFIFO)
291141486Sjhb		return (0);
29243412Snewton
29343412Snewton	if ((st.st_mode & ALLPERMS) != 0)
294141486Sjhb		return (0);
29543412Snewton
296141486Sjhb	error = kern_unlink(td, path, UIO_SYSSPACE);
297141486Sjhb	if (error)
29843412Snewton		DPRINTF(("clean_pipe: unlink failed %d\n", error));
299141486Sjhb	return (error);
30043412Snewton}
30143412Snewton
30243412Snewton
30343412Snewtonstatic void
30443412Snewtonsockaddr_to_netaddr_in(sc, sain)
30543412Snewton	struct svr4_strmcmd *sc;
30643412Snewton	const struct sockaddr_in *sain;
30743412Snewton{
30843412Snewton	struct svr4_netaddr_in *na;
30943412Snewton	na = SVR4_ADDROF(sc);
31043412Snewton
31143412Snewton	na->family = sain->sin_family;
31243412Snewton	na->port = sain->sin_port;
31343412Snewton	na->addr = sain->sin_addr.s_addr;
31443412Snewton	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
31543412Snewton		 na->addr));
31643412Snewton}
31743412Snewton
31843412Snewton
31943412Snewtonstatic void
32043412Snewtonsockaddr_to_netaddr_un(sc, saun)
32143412Snewton	struct svr4_strmcmd *sc;
32243412Snewton	const struct sockaddr_un *saun;
32343412Snewton{
32443412Snewton	struct svr4_netaddr_un *na;
32543412Snewton	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
32643412Snewton	    sizeof(*sc);
32743412Snewton	const char *src;
32843412Snewton
32943412Snewton	na = SVR4_ADDROF(sc);
33043412Snewton	na->family = saun->sun_family;
33143412Snewton	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
33243412Snewton		if (dst == edst)
33343412Snewton			break;
33443412Snewton	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
33543412Snewton}
33643412Snewton
33743412Snewton
33843412Snewtonstatic void
33943412Snewtonnetaddr_to_sockaddr_in(sain, sc)
34043412Snewton	struct sockaddr_in *sain;
34143412Snewton	const struct svr4_strmcmd *sc;
34243412Snewton{
34343412Snewton	const struct svr4_netaddr_in *na;
34443412Snewton
34543412Snewton
34643412Snewton	na = SVR4_C_ADDROF(sc);
34743412Snewton	memset(sain, 0, sizeof(*sain));
34843412Snewton	sain->sin_len = sizeof(*sain);
34943412Snewton	sain->sin_family = na->family;
35043412Snewton	sain->sin_port = na->port;
35143412Snewton	sain->sin_addr.s_addr = na->addr;
35243412Snewton	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
35343412Snewton		 sain->sin_port, sain->sin_addr.s_addr));
35443412Snewton}
35543412Snewton
35643412Snewton
35743412Snewtonstatic void
35843412Snewtonnetaddr_to_sockaddr_un(saun, sc)
35943412Snewton	struct sockaddr_un *saun;
36043412Snewton	const struct svr4_strmcmd *sc;
36143412Snewton{
36243412Snewton	const struct svr4_netaddr_un *na;
36343412Snewton	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
36443412Snewton	const char *src;
36543412Snewton
36643412Snewton	na = SVR4_C_ADDROF(sc);
36743412Snewton	memset(saun, 0, sizeof(*saun));
36843412Snewton	saun->sun_family = na->family;
36943412Snewton	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
37043412Snewton		if (dst == edst)
37143412Snewton			break;
37243412Snewton	saun->sun_len = dst - saun->sun_path;
37343412Snewton	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
37443412Snewton		 saun->sun_path));
37543412Snewton}
37643412Snewton
37743412Snewton
37843412Snewtonstatic void
37943412Snewtongetparm(fp, pa)
38043412Snewton	struct file *fp;
38143412Snewton	struct svr4_si_sockparms *pa;
38243412Snewton{
38389306Salfred	struct svr4_strm *st;
38489306Salfred	struct socket *so;
38543412Snewton
38689306Salfred	st = svr4_stream_get(fp);
38743412Snewton	if (st == NULL)
38843412Snewton		return;
38943412Snewton
390109153Sdillon	so = fp->f_data;
39189306Salfred
39243412Snewton	pa->family = st->s_family;
39343412Snewton
39443412Snewton	switch (so->so_type) {
39543412Snewton	case SOCK_DGRAM:
39643412Snewton		pa->type = SVR4_T_CLTS;
39743412Snewton		pa->protocol = IPPROTO_UDP;
39843412Snewton		DPRINTF(("getparm(dgram)\n"));
39943412Snewton		return;
40043412Snewton
40143412Snewton	case SOCK_STREAM:
40243412Snewton	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
40343412Snewton		pa->protocol = IPPROTO_IP;
40443412Snewton		DPRINTF(("getparm(stream)\n"));
40543412Snewton		return;
40643412Snewton
40743412Snewton	case SOCK_RAW:
40843412Snewton		pa->type = SVR4_T_CLTS;
40943412Snewton		pa->protocol = IPPROTO_RAW;
41043412Snewton		DPRINTF(("getparm(raw)\n"));
41143412Snewton		return;
41243412Snewton
41343412Snewton	default:
41443412Snewton		pa->type = 0;
41543412Snewton		pa->protocol = 0;
41643412Snewton		DPRINTF(("getparm(type %d?)\n", so->so_type));
41743412Snewton		return;
41843412Snewton	}
41943412Snewton}
42043412Snewton
42143412Snewton
42243412Snewtonstatic int
42383366Sjuliansi_ogetudata(fp, fd, ioc, td)
42443412Snewton	struct file		*fp;
42543412Snewton	int 			 fd;
42643412Snewton	struct svr4_strioctl	*ioc;
42783366Sjulian	struct thread		*td;
42843412Snewton{
42943412Snewton	int error;
43043412Snewton	struct svr4_si_oudata ud;
43143412Snewton	struct svr4_si_sockparms pa;
43243412Snewton
43343412Snewton	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
43443412Snewton		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
43543412Snewton			 sizeof(ud), ioc->len));
43643412Snewton		return EINVAL;
43743412Snewton	}
43843412Snewton
43943412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
44043412Snewton		return error;
44143412Snewton
44243412Snewton	getparm(fp, &pa);
44343412Snewton
44443412Snewton	switch (pa.family) {
44543412Snewton	case AF_INET:
44643412Snewton	    ud.tidusize = 16384;
44743412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
44843412Snewton	    if (pa.type == SVR4_SOCK_STREAM)
44943412Snewton		    ud.etsdusize = 1;
45043412Snewton	    else
45143412Snewton		    ud.etsdusize = 0;
45243412Snewton	    break;
45343412Snewton
45443412Snewton	case AF_LOCAL:
45543412Snewton	    ud.tidusize = 65536;
45643412Snewton	    ud.addrsize = 128;
45743412Snewton	    ud.etsdusize = 128;
45843412Snewton	    break;
45943412Snewton
46043412Snewton	default:
46143412Snewton	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
46243412Snewton		     pa.family));
46343412Snewton	    return ENOSYS;
46443412Snewton	}
46543412Snewton
46643412Snewton	/* I have no idea what these should be! */
46743412Snewton	ud.optsize = 128;
46843412Snewton	ud.tsdusize = 128;
46943412Snewton
47043412Snewton	ud.servtype = pa.type;
47143412Snewton
47243412Snewton	/* XXX: Fixme */
47343412Snewton	ud.so_state = 0;
47443412Snewton	ud.so_options = 0;
47543412Snewton	return copyout(&ud, ioc->buf, ioc->len);
47643412Snewton}
47743412Snewton
47843412Snewton
47943412Snewtonstatic int
48083366Sjuliansi_sockparams(fp, fd, ioc, td)
48143412Snewton	struct file		*fp;
48243412Snewton	int 			 fd;
48343412Snewton	struct svr4_strioctl	*ioc;
48483366Sjulian	struct thread		*td;
48543412Snewton{
48643412Snewton	struct svr4_si_sockparms pa;
48743412Snewton
48843412Snewton	getparm(fp, &pa);
48943412Snewton	return copyout(&pa, ioc->buf, sizeof(pa));
49043412Snewton}
49143412Snewton
49243412Snewton
49343412Snewtonstatic int
49483366Sjuliansi_listen(fp, fd, ioc, td)
49543412Snewton	struct file		*fp;
49643412Snewton	int 			 fd;
49743412Snewton	struct svr4_strioctl	*ioc;
49883366Sjulian	struct thread		*td;
49943412Snewton{
50043412Snewton	int error;
50143412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
50243412Snewton	struct svr4_strmcmd lst;
50343412Snewton	struct listen_args la;
50443412Snewton
50543412Snewton	if (st == NULL)
50643412Snewton		return EINVAL;
50743412Snewton
508121275Stjr	if (ioc->len < 0 || ioc->len > sizeof(lst))
509121275Stjr		return EINVAL;
510121275Stjr
51143412Snewton	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
51243412Snewton		return error;
51343412Snewton
51443412Snewton	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
51543412Snewton		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
51643412Snewton		return EINVAL;
51743412Snewton	}
51843412Snewton
51943412Snewton	/*
52043412Snewton	 * We are making assumptions again...
52143412Snewton	 */
522107849Salfred	la.s = fd;
52343412Snewton	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
524107849Salfred	la.backlog = 5;
52543412Snewton
526225617Skmacy	if ((error = sys_listen(td, &la)) != 0) {
52743412Snewton		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
52843412Snewton		return error;
52943412Snewton	}
53043412Snewton
53143412Snewton	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
53243412Snewton	lst.cmd = SVR4_TI_BIND_REPLY;
53343412Snewton
53443412Snewton	switch (st->s_family) {
53543412Snewton	case AF_INET:
53643412Snewton		/* XXX: Fill the length here */
53743412Snewton		break;
53843412Snewton
53943412Snewton	case AF_LOCAL:
54043412Snewton		lst.len = 140;
54143412Snewton		lst.pad[28] = 0x00000000;	/* magic again */
54243412Snewton		lst.pad[29] = 0x00000800;	/* magic again */
54343412Snewton		lst.pad[30] = 0x80001400;	/* magic again */
54443412Snewton		break;
54543412Snewton
54643412Snewton	default:
54743412Snewton		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
54843412Snewton		    st->s_family));
54943412Snewton		return ENOSYS;
55043412Snewton	}
55143412Snewton
55243412Snewton
55343412Snewton	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
55443412Snewton		return error;
55543412Snewton
55643412Snewton	return 0;
55743412Snewton}
55843412Snewton
55943412Snewton
56043412Snewtonstatic int
56183366Sjuliansi_getudata(fp, fd, ioc, td)
56243412Snewton	struct file		*fp;
56343412Snewton	int 			 fd;
56443412Snewton	struct svr4_strioctl	*ioc;
56583366Sjulian	struct thread		*td;
56643412Snewton{
56743412Snewton	int error;
56843412Snewton	struct svr4_si_udata ud;
56943412Snewton
57043412Snewton	if (sizeof(ud) != ioc->len) {
57143412Snewton		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
57243412Snewton			 sizeof(ud), ioc->len));
57343412Snewton		return EINVAL;
57443412Snewton	}
57543412Snewton
57643412Snewton	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
57743412Snewton		return error;
57843412Snewton
57943412Snewton	getparm(fp, &ud.sockparms);
58043412Snewton
58143412Snewton	switch (ud.sockparms.family) {
58243412Snewton	case AF_INET:
58343412Snewton	    DPRINTF(("getudata_inet\n"));
58443412Snewton	    ud.tidusize = 16384;
58543412Snewton	    ud.tsdusize = 16384;
58643412Snewton	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
58743412Snewton	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
58843412Snewton		    ud.etsdusize = 1;
58943412Snewton	    else
59043412Snewton		    ud.etsdusize = 0;
59143412Snewton	    ud.optsize = 0;
59243412Snewton	    break;
59343412Snewton
59443412Snewton	case AF_LOCAL:
59543412Snewton	    DPRINTF(("getudata_local\n"));
59643412Snewton	    ud.tidusize = 65536;
59743412Snewton	    ud.tsdusize = 128;
59843412Snewton	    ud.addrsize = 128;
59943412Snewton	    ud.etsdusize = 128;
60043412Snewton	    ud.optsize = 128;
60143412Snewton	    break;
60243412Snewton
60343412Snewton	default:
60443412Snewton	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
60543412Snewton		     ud.sockparms.family));
60643412Snewton	    return ENOSYS;
60743412Snewton	}
60843412Snewton
60943412Snewton
61043412Snewton	ud.servtype = ud.sockparms.type;
61143412Snewton	DPRINTF(("ud.servtype = %d\n", ud.servtype));
61243412Snewton	/* XXX: Fixme */
61343412Snewton	ud.so_state = 0;
61443412Snewton	ud.so_options = 0;
61543412Snewton	return copyout(&ud, ioc->buf, sizeof(ud));
61643412Snewton}
61743412Snewton
61843412Snewton
61943412Snewtonstatic int
62083366Sjuliansi_shutdown(fp, fd, ioc, td)
62143412Snewton	struct file		*fp;
62243412Snewton	int 			 fd;
62343412Snewton	struct svr4_strioctl	*ioc;
62483366Sjulian	struct thread		*td;
62543412Snewton{
62643412Snewton	int error;
62743412Snewton	struct shutdown_args ap;
62843412Snewton
629107849Salfred	if (ioc->len != sizeof(ap.how)) {
63043412Snewton		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
631107849Salfred			 sizeof(ap.how), ioc->len));
63243412Snewton		return EINVAL;
63343412Snewton	}
63443412Snewton
635107849Salfred	if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0)
63643412Snewton		return error;
63743412Snewton
638107849Salfred	ap.s = fd;
63943412Snewton
640225617Skmacy	return sys_shutdown(td, &ap);
64143412Snewton}
64243412Snewton
64343412Snewton
64443412Snewtonstatic int
64583366Sjuliansockmod(fp, fd, ioc, td)
64643412Snewton	struct file		*fp;
64743412Snewton	int			 fd;
64843412Snewton	struct svr4_strioctl	*ioc;
64983366Sjulian	struct thread		*td;
65043412Snewton{
65143412Snewton	switch (ioc->cmd) {
65243412Snewton	case SVR4_SI_OGETUDATA:
65343412Snewton		DPRINTF(("SI_OGETUDATA\n"));
65483366Sjulian		return si_ogetudata(fp, fd, ioc, td);
65543412Snewton
65643412Snewton	case SVR4_SI_SHUTDOWN:
65743412Snewton		DPRINTF(("SI_SHUTDOWN\n"));
65883366Sjulian		return si_shutdown(fp, fd, ioc, td);
65943412Snewton
66043412Snewton	case SVR4_SI_LISTEN:
66143412Snewton		DPRINTF(("SI_LISTEN\n"));
66283366Sjulian		return si_listen(fp, fd, ioc, td);
66343412Snewton
66443412Snewton	case SVR4_SI_SETMYNAME:
66543412Snewton		DPRINTF(("SI_SETMYNAME\n"));
66643412Snewton		return 0;
66743412Snewton
66843412Snewton	case SVR4_SI_SETPEERNAME:
66943412Snewton		DPRINTF(("SI_SETPEERNAME\n"));
67043412Snewton		return 0;
67143412Snewton
67243412Snewton	case SVR4_SI_GETINTRANSIT:
67343412Snewton		DPRINTF(("SI_GETINTRANSIT\n"));
67443412Snewton		return 0;
67543412Snewton
67643412Snewton	case SVR4_SI_TCL_LINK:
67743412Snewton		DPRINTF(("SI_TCL_LINK\n"));
67843412Snewton		return 0;
67943412Snewton
68043412Snewton	case SVR4_SI_TCL_UNLINK:
68143412Snewton		DPRINTF(("SI_TCL_UNLINK\n"));
68243412Snewton		return 0;
68343412Snewton
68443412Snewton	case SVR4_SI_SOCKPARAMS:
68543412Snewton		DPRINTF(("SI_SOCKPARAMS\n"));
68683366Sjulian		return si_sockparams(fp, fd, ioc, td);
68743412Snewton
68843412Snewton	case SVR4_SI_GETUDATA:
68943412Snewton		DPRINTF(("SI_GETUDATA\n"));
69083366Sjulian		return si_getudata(fp, fd, ioc, td);
69143412Snewton
69243412Snewton	default:
69343412Snewton		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
69443412Snewton		return 0;
69543412Snewton
69643412Snewton	}
69743412Snewton}
69843412Snewton
69943412Snewton
70043412Snewtonstatic int
70183366Sjulianti_getinfo(fp, fd, ioc, td)
70243412Snewton	struct file		*fp;
70343412Snewton	int 			 fd;
70443412Snewton	struct svr4_strioctl	*ioc;
70583366Sjulian	struct thread		*td;
70643412Snewton{
70743412Snewton	int error;
70843412Snewton	struct svr4_infocmd info;
70943412Snewton
71043412Snewton	memset(&info, 0, sizeof(info));
71143412Snewton
712121275Stjr	if (ioc->len < 0 || ioc->len > sizeof(info))
713121275Stjr		return EINVAL;
714121275Stjr
71543412Snewton	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
71643412Snewton		return error;
71743412Snewton
71843412Snewton	if (info.cmd != SVR4_TI_INFO_REQUEST)
71943412Snewton		return EINVAL;
72043412Snewton
72143412Snewton	info.cmd = SVR4_TI_INFO_REPLY;
72243412Snewton	info.tsdu = 0;
72343412Snewton	info.etsdu = 1;
72443412Snewton	info.cdata = -2;
72543412Snewton	info.ddata = -2;
72643412Snewton	info.addr = 16;
72743412Snewton	info.opt = -1;
72843412Snewton	info.tidu = 16384;
72943412Snewton	info.serv = 2;
73043412Snewton	info.current = 0;
73143412Snewton	info.provider = 2;
73243412Snewton
73343412Snewton	ioc->len = sizeof(info);
73443412Snewton	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
73543412Snewton		return error;
73643412Snewton
73743412Snewton	return 0;
73843412Snewton}
73943412Snewton
74043412Snewton
74143412Snewtonstatic int
74283366Sjulianti_bind(fp, fd, ioc, td)
74343412Snewton	struct file		*fp;
74443412Snewton	int 			 fd;
74543412Snewton	struct svr4_strioctl	*ioc;
74683366Sjulian	struct thread		*td;
74743412Snewton{
74843412Snewton	int error;
74943412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
75043412Snewton	struct sockaddr_in sain;
75143412Snewton	struct sockaddr_un saun;
752160249Sjhb	struct sockaddr *skp;
75343412Snewton	int sasize;
75443412Snewton	struct svr4_strmcmd bnd;
75543412Snewton
75643412Snewton	if (st == NULL) {
75743412Snewton		DPRINTF(("ti_bind: bad file descriptor\n"));
75843412Snewton		return EINVAL;
75943412Snewton	}
76043412Snewton
761121275Stjr	if (ioc->len < 0 || ioc->len > sizeof(bnd))
762121275Stjr		return EINVAL;
763121275Stjr
76443412Snewton	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
76543412Snewton		return error;
76643412Snewton
76743412Snewton	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
76843412Snewton		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
76943412Snewton		return EINVAL;
77043412Snewton	}
77143412Snewton
77243412Snewton	switch (st->s_family) {
77343412Snewton	case AF_INET:
774160249Sjhb		skp = (struct sockaddr *)&sain;
77543412Snewton		sasize = sizeof(sain);
77643412Snewton
77743412Snewton		if (bnd.offs == 0)
778160249Sjhb			goto error;
77943412Snewton
78043412Snewton		netaddr_to_sockaddr_in(&sain, &bnd);
78143412Snewton
78243412Snewton		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
78343412Snewton			 sain.sin_family, sain.sin_port,
78443412Snewton			 sain.sin_addr.s_addr));
78543412Snewton		break;
78643412Snewton
78743412Snewton	case AF_LOCAL:
788160249Sjhb		skp = (struct sockaddr *)&saun;
78943412Snewton		sasize = sizeof(saun);
79043412Snewton		if (bnd.offs == 0)
791160249Sjhb			goto error;
79243412Snewton
79343412Snewton		netaddr_to_sockaddr_un(&saun, &bnd);
79443412Snewton
79543412Snewton		if (saun.sun_path[0] == '\0')
796160249Sjhb			goto error;
79743412Snewton
79843412Snewton		DPRINTF(("TI_BIND: fam %d, path %s\n",
79943412Snewton			 saun.sun_family, saun.sun_path));
80043412Snewton
80183366Sjulian		if ((error = clean_pipe(td, saun.sun_path)) != 0)
80243412Snewton			return error;
80343412Snewton
80443412Snewton		bnd.pad[28] = 0x00001000;	/* magic again */
80543412Snewton		break;
80643412Snewton
80743412Snewton	default:
80843412Snewton		DPRINTF(("TI_BIND: Unsupported address family %d\n",
80943412Snewton			 st->s_family));
81043412Snewton		return ENOSYS;
81143412Snewton	}
81243412Snewton
81343412Snewton	DPRINTF(("TI_BIND: fileno %d\n", fd));
81443412Snewton
815160249Sjhb	if ((error = kern_bind(td, fd, skp)) != 0) {
81643412Snewton		DPRINTF(("TI_BIND: bind failed %d\n", error));
81743412Snewton		return error;
81843412Snewton	}
819160249Sjhb	goto reply;
82043412Snewton
821160249Sjhberror:
822160249Sjhb	memset(&bnd, 0, sizeof(bnd));
823160249Sjhb	bnd.len = sasize + 4;
824160249Sjhb	bnd.offs = 0x10;	/* XXX */
825160249Sjhb
82643412Snewtonreply:
82743412Snewton	bnd.cmd = SVR4_TI_BIND_REPLY;
82843412Snewton
82943412Snewton	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
83043412Snewton		return error;
83143412Snewton
83243412Snewton	return 0;
83343412Snewton}
83443412Snewton
83543412Snewton
83643412Snewtonstatic int
83783366Sjuliantimod(fp, fd, ioc, td)
83843412Snewton	struct file		*fp;
83943412Snewton	int			 fd;
84043412Snewton	struct svr4_strioctl	*ioc;
84183366Sjulian	struct thread		*td;
84243412Snewton{
84343412Snewton	switch (ioc->cmd) {
84443412Snewton	case SVR4_TI_GETINFO:
84543412Snewton		DPRINTF(("TI_GETINFO\n"));
84683366Sjulian		return ti_getinfo(fp, fd, ioc, td);
84743412Snewton
84843412Snewton	case SVR4_TI_OPTMGMT:
84943412Snewton		DPRINTF(("TI_OPTMGMT\n"));
85043412Snewton		return 0;
85143412Snewton
85243412Snewton	case SVR4_TI_BIND:
85343412Snewton		DPRINTF(("TI_BIND\n"));
85483366Sjulian		return ti_bind(fp, fd, ioc, td);
85543412Snewton
85643412Snewton	case SVR4_TI_UNBIND:
85743412Snewton		DPRINTF(("TI_UNBIND\n"));
85843412Snewton		return 0;
85943412Snewton
86043412Snewton	default:
86143412Snewton		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
86243412Snewton		return 0;
86343412Snewton	}
86443412Snewton}
86543412Snewton
86643412Snewton
86743412Snewtonint
86883366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
86943412Snewton	struct file *fp;
87083366Sjulian	struct thread *td;
87143412Snewton	register_t *retval;
87243412Snewton	int fd;
87343412Snewton	u_long cmd;
87443412Snewton	caddr_t dat;
87543412Snewton{
87643412Snewton	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
87743412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
87843412Snewton	int error;
879160249Sjhb	struct sockaddr *sa;
880160249Sjhb	socklen_t sasize, oldsasize;
88143412Snewton	struct svr4_strmcmd sc;
88243412Snewton
88343412Snewton	DPRINTF(("svr4_stream_ti_ioctl\n"));
88443412Snewton
88543412Snewton	if (st == NULL)
88643412Snewton		return EINVAL;
88743412Snewton
88843412Snewton	sc.offs = 0x10;
88943412Snewton
89043412Snewton	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
89143412Snewton		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
89243412Snewton		return error;
89343412Snewton	}
89443412Snewton
89543412Snewton	switch (st->s_family) {
89643412Snewton	case AF_INET:
897160249Sjhb		sasize = sizeof(struct sockaddr_in);
89843412Snewton		break;
89943412Snewton
90043412Snewton	case AF_LOCAL:
901160249Sjhb		sasize = sizeof(struct sockaddr_un);
90243412Snewton		break;
90343412Snewton
90443412Snewton	default:
90543412Snewton		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
90643412Snewton			 st->s_family));
90743412Snewton		return ENOSYS;
90843412Snewton	}
909160249Sjhb	oldsasize = sasize;
91043412Snewton
91143412Snewton	switch (cmd) {
91243412Snewton	case SVR4_TI_GETMYNAME:
91343412Snewton		DPRINTF(("TI_GETMYNAME\n"));
91443412Snewton		{
915160249Sjhb			error = kern_getsockname(td, fd, &sa, &sasize);
916160249Sjhb			if (error) {
91743412Snewton				DPRINTF(("ti_ioctl: getsockname error\n"));
91843412Snewton				return error;
91943412Snewton			}
92043412Snewton		}
92143412Snewton		break;
92243412Snewton
92343412Snewton	case SVR4_TI_GETPEERNAME:
92443412Snewton		DPRINTF(("TI_GETPEERNAME\n"));
92543412Snewton		{
926160249Sjhb			error = kern_getpeername(td, fd, &sa, &sasize);
927160249Sjhb			if (error) {
92843412Snewton				DPRINTF(("ti_ioctl: getpeername error\n"));
92943412Snewton				return error;
93043412Snewton			}
93143412Snewton		}
93243412Snewton		break;
93343412Snewton
93443412Snewton	case SVR4_TI_SETMYNAME:
93543412Snewton		DPRINTF(("TI_SETMYNAME\n"));
93643412Snewton		return 0;
93743412Snewton
93843412Snewton	case SVR4_TI_SETPEERNAME:
93943412Snewton		DPRINTF(("TI_SETPEERNAME\n"));
94043412Snewton		return 0;
94143412Snewton	default:
94243412Snewton		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
94343412Snewton		return ENOSYS;
94443412Snewton	}
94543412Snewton
946160249Sjhb	if (sasize < 0 || sasize > oldsasize) {
947160249Sjhb		free(sa, M_SONAME);
948160249Sjhb		return EINVAL;
94943412Snewton	}
95043412Snewton
95143412Snewton	switch (st->s_family) {
95243412Snewton	case AF_INET:
953160249Sjhb		sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
95443412Snewton		skb.len = sasize;
95543412Snewton		break;
95643412Snewton
95743412Snewton	case AF_LOCAL:
958160249Sjhb		sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
95943412Snewton		skb.len = sasize + 4;
96043412Snewton		break;
96143412Snewton
96243412Snewton	default:
963160249Sjhb		free(sa, M_SONAME);
96443412Snewton		return ENOSYS;
96543412Snewton	}
966160249Sjhb	free(sa, M_SONAME);
96743412Snewton
96843412Snewton	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
96943412Snewton		DPRINTF(("ti_ioctl: error copying out socket data\n"));
97043412Snewton		return error;
97143412Snewton	}
97243412Snewton
97343412Snewton
97443412Snewton	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
97543412Snewton		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
97643412Snewton		return error;
97743412Snewton	}
97843412Snewton
97943412Snewton	return error;
98043412Snewton}
98143412Snewton
98243412Snewton
98343412Snewton
98443412Snewton
98543412Snewtonstatic int
98683366Sjuliani_nread(fp, td, retval, fd, cmd, dat)
98743412Snewton	struct file *fp;
98883366Sjulian	struct thread *td;
98943412Snewton	register_t *retval;
99043412Snewton	int fd;
99143412Snewton	u_long cmd;
99243412Snewton	caddr_t dat;
99343412Snewton{
99443412Snewton	int error;
99543412Snewton	int nread = 0;
99643412Snewton
99743412Snewton	/*
99843412Snewton	 * We are supposed to return the message length in nread, and the
99943412Snewton	 * number of messages in retval. We don't have the notion of number
100043412Snewton	 * of stream messages, so we just find out if we have any bytes waiting
100143412Snewton	 * for us, and if we do, then we assume that we have at least one
100243412Snewton	 * message waiting for us.
100343412Snewton	 */
1004102003Srwatson	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred,
1005102003Srwatson	    td)) != 0)
100643412Snewton		return error;
100743412Snewton
100843412Snewton	if (nread != 0)
100943412Snewton		*retval = 1;
101043412Snewton	else
101143412Snewton		*retval = 0;
101243412Snewton
101343412Snewton	return copyout(&nread, dat, sizeof(nread));
101443412Snewton}
101543412Snewton
101643412Snewtonstatic int
101783366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat)
101843412Snewton	struct file *fp;
101983366Sjulian	struct thread *td;
102043412Snewton	register_t *retval;
102143412Snewton	int fd;
102243412Snewton	u_long cmd;
102343412Snewton	caddr_t dat;
102443412Snewton{
102543412Snewton	/*
102643412Snewton	 * Major hack again here. We assume that we are using this to
102743412Snewton	 * implement accept(2). If that is the case, we have already
102843412Snewton	 * called accept, and we have stored the file descriptor in
102943412Snewton	 * afd. We find the file descriptor that the code wants to use
103043412Snewton	 * in fd insert, and then we dup2() our accepted file descriptor
103143412Snewton	 * to it.
103243412Snewton	 */
103343412Snewton	int error;
103443412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
103543412Snewton	struct svr4_strfdinsert fdi;
103643412Snewton	struct dup2_args d2p;
103743412Snewton
103843412Snewton	if (st == NULL) {
103943412Snewton		DPRINTF(("fdinsert: bad file type\n"));
104043412Snewton		return EINVAL;
104143412Snewton	}
104243412Snewton
1043160794Sjhb	mtx_lock(&Giant);
104443412Snewton	if (st->s_afd == -1) {
104543412Snewton		DPRINTF(("fdinsert: accept fd not found\n"));
1046160794Sjhb		mtx_unlock(&Giant);
104743412Snewton		return ENOENT;
104843412Snewton	}
104943412Snewton
105043412Snewton	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
105143412Snewton		DPRINTF(("fdinsert: copyin failed %d\n", error));
1052160794Sjhb		mtx_unlock(&Giant);
105343412Snewton		return error;
105443412Snewton	}
105543412Snewton
1056107849Salfred	d2p.from = st->s_afd;
1057107849Salfred	d2p.to = fdi.fd;
105843412Snewton
1059225617Skmacy	if ((error = sys_dup2(td, &d2p)) != 0) {
106043412Snewton		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
106143412Snewton		    st->s_afd, fdi.fd, error));
1062160794Sjhb		mtx_unlock(&Giant);
106343412Snewton		return error;
106443412Snewton	}
106543412Snewton
1066160249Sjhb	if ((error = kern_close(td, st->s_afd)) != 0) {
106743412Snewton		DPRINTF(("fdinsert: close(%d) failed %d\n",
106843412Snewton		    st->s_afd, error));
1069160794Sjhb		mtx_unlock(&Giant);
107043412Snewton		return error;
107143412Snewton	}
107243412Snewton
107343412Snewton	st->s_afd = -1;
1074160794Sjhb	mtx_unlock(&Giant);
107543412Snewton
107643412Snewton	*retval = 0;
107743412Snewton	return 0;
107843412Snewton}
107943412Snewton
108043412Snewton
108143412Snewtonstatic int
108283366Sjulian_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
108343412Snewton	struct file *fp;
108483366Sjulian	struct thread *td;
108543412Snewton	register_t *retval;
108643412Snewton	int fd;
108743412Snewton	u_long cmd;
108843412Snewton	caddr_t dat;
108943412Snewton{
109043412Snewton	struct mkfifo_args ap;
109143412Snewton
109243412Snewton	/*
109343412Snewton	 * This is a supposed to be a kernel and library only ioctl.
109443412Snewton	 * It gets called before ti_bind, when we have a unix
109543412Snewton	 * socket, to physically create the socket transport and
109643412Snewton	 * ``reserve'' it. I don't know how this get reserved inside
109743412Snewton	 * the kernel, but we are going to create it nevertheless.
109843412Snewton	 */
1099107849Salfred	ap.path = dat;
1100107849Salfred	ap.mode = S_IFIFO;
110143412Snewton
1102225617Skmacy	return sys_mkfifo(td, &ap);
110343412Snewton}
110443412Snewton
110543412Snewtonstatic int
110683366Sjulian_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
110743412Snewton	struct file *fp;
110883366Sjulian	struct thread *td;
110943412Snewton	register_t *retval;
111043412Snewton	int fd;
111143412Snewton	u_long cmd;
111243412Snewton	caddr_t dat;
111343412Snewton{
111443412Snewton	struct unlink_args ap;
111543412Snewton
111643412Snewton	/*
111743412Snewton	 * This is a supposed to be a kernel and library only ioctl.
111843412Snewton	 * I guess it is supposed to release the socket.
111943412Snewton	 */
1120107849Salfred	ap.path = dat;
112143412Snewton
1122225617Skmacy	return sys_unlink(td, &ap);
112343412Snewton}
112443412Snewton
112543412Snewtonstatic int
112683366Sjuliani_str(fp, td, retval, fd, cmd, dat)
112743412Snewton	struct file *fp;
112883366Sjulian	struct thread *td;
112943412Snewton	register_t *retval;
113043412Snewton	int fd;
113143412Snewton	u_long cmd;
113243412Snewton	caddr_t dat;
113343412Snewton{
113443412Snewton	int			 error;
113543412Snewton	struct svr4_strioctl	 ioc;
113643412Snewton
113743412Snewton	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
113843412Snewton		return error;
113943412Snewton
114043412Snewton#ifdef DEBUG_SVR4
1141150663Srwatson	if ((error = show_ioc(">", &ioc)) != 0)
114243412Snewton		return error;
114343412Snewton#endif /* DEBUG_SVR4 */
114443412Snewton
114543412Snewton	switch (ioc.cmd & 0xff00) {
114643412Snewton	case SVR4_SIMOD:
114783366Sjulian		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
114843412Snewton			return error;
114943412Snewton		break;
115043412Snewton
115143412Snewton	case SVR4_TIMOD:
115283366Sjulian		if ((error = timod(fp, fd, &ioc, td)) != 0)
115343412Snewton			return error;
115443412Snewton		break;
115543412Snewton
115643412Snewton	default:
115743412Snewton		DPRINTF(("Unimplemented module %c %ld\n",
115843412Snewton			 (char) (cmd >> 8), cmd & 0xff));
115943412Snewton		return 0;
116043412Snewton	}
116143412Snewton
116243412Snewton#ifdef DEBUG_SVR4
1163150663Srwatson	if ((error = show_ioc("<", &ioc)) != 0)
116443412Snewton		return error;
116543412Snewton#endif /* DEBUG_SVR4 */
116643412Snewton	return copyout(&ioc, dat, sizeof(ioc));
116743412Snewton}
116843412Snewton
116943412Snewtonstatic int
117083366Sjuliani_setsig(fp, td, retval, fd, cmd, dat)
117143412Snewton	struct file *fp;
117283366Sjulian	struct thread *td;
117343412Snewton	register_t *retval;
117443412Snewton	int fd;
117543412Snewton	u_long cmd;
117643412Snewton	caddr_t dat;
117743412Snewton{
117843412Snewton	/*
117943412Snewton	 * This is the best we can do for now; we cannot generate
118043412Snewton	 * signals only for specific events so the signal mask gets
118143412Snewton	 * ignored; we save it just to pass it to a possible I_GETSIG...
118243412Snewton	 *
118343412Snewton	 * We alse have to fix the O_ASYNC fcntl bit, so the
118443412Snewton	 * process will get SIGPOLLs.
118543412Snewton	 */
118643412Snewton	int error;
118743412Snewton	register_t oflags, flags;
118843412Snewton	struct svr4_strm *st = svr4_stream_get(fp);
118943412Snewton
119043412Snewton	if (st == NULL) {
119143412Snewton		DPRINTF(("i_setsig: bad file descriptor\n"));
119243412Snewton		return EINVAL;
119343412Snewton	}
119443412Snewton	/* get old status flags */
1195134266Sjhb	error = kern_fcntl(td, fd, F_GETFL, 0);
1196134266Sjhb	if (error)
1197134266Sjhb		return (error);
119843412Snewton
119983366Sjulian	oflags = td->td_retval[0];
120043412Snewton
120143412Snewton	/* update the flags */
1202160794Sjhb	mtx_lock(&Giant);
120343412Snewton	if (dat != NULL) {
120443412Snewton		int mask;
120543412Snewton
120643412Snewton		flags = oflags | O_ASYNC;
120743412Snewton		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
120843412Snewton			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
120943412Snewton			  return error;
121043412Snewton		}
121143412Snewton		if (mask & SVR4_S_ALLMASK) {
121243412Snewton			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
121343412Snewton			  return EINVAL;
121443412Snewton		}
121543412Snewton		st->s_eventmask = mask;
121643412Snewton	}
121743412Snewton	else {
121843412Snewton		flags = oflags & ~O_ASYNC;
121943412Snewton		st->s_eventmask = 0;
122043412Snewton	}
1221160794Sjhb	mtx_unlock(&Giant);
122243412Snewton
122343412Snewton	/* set the new flags, if changed */
122443412Snewton	if (flags != oflags) {
1225134266Sjhb		error = kern_fcntl(td, fd, F_SETFL, flags);
1226134266Sjhb		if (error)
1227134266Sjhb			return (error);
122883366Sjulian		flags = td->td_retval[0];
122943412Snewton	}
123043412Snewton
123143412Snewton	/* set up SIGIO receiver if needed */
1232134266Sjhb	if (dat != NULL)
1233134266Sjhb		return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid));
123443412Snewton	return 0;
123543412Snewton}
123643412Snewton
123743412Snewtonstatic int
123883366Sjuliani_getsig(fp, td, retval, fd, cmd, dat)
123943412Snewton	struct file *fp;
124083366Sjulian	struct thread *td;
124143412Snewton	register_t *retval;
124243412Snewton	int fd;
124343412Snewton	u_long cmd;
124443412Snewton	caddr_t dat;
124543412Snewton{
1246160794Sjhb	int error, eventmask;
124743412Snewton
124843412Snewton	if (dat != NULL) {
124943412Snewton		struct svr4_strm *st = svr4_stream_get(fp);
125043412Snewton
125143412Snewton		if (st == NULL) {
125243412Snewton			DPRINTF(("i_getsig: bad file descriptor\n"));
125343412Snewton			return EINVAL;
125443412Snewton		}
1255160794Sjhb		mtx_lock(&Giant);
1256160794Sjhb		eventmask = st->s_eventmask;
1257160794Sjhb		mtx_unlock(&Giant);
1258160794Sjhb		if ((error = copyout(&eventmask, dat,
1259160794Sjhb				     sizeof(eventmask))) != 0) {
126043412Snewton			DPRINTF(("i_getsig: bad eventmask pointer\n"));
126143412Snewton			return error;
126243412Snewton		}
126343412Snewton	}
126443412Snewton	return 0;
126543412Snewton}
126643412Snewton
126743412Snewtonint
126883366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
126943412Snewton	struct file *fp;
127083366Sjulian	struct thread *td;
127143412Snewton	register_t *retval;
127243412Snewton	int fd;
127343412Snewton	u_long cmd;
127443412Snewton	caddr_t dat;
127543412Snewton{
127643412Snewton	*retval = 0;
127743412Snewton
127843412Snewton	/*
127943412Snewton	 * All the following stuff assumes "sockmod" is pushed...
128043412Snewton	 */
128143412Snewton	switch (cmd) {
128243412Snewton	case SVR4_I_NREAD:
128343412Snewton		DPRINTF(("I_NREAD\n"));
128483366Sjulian		return i_nread(fp, td, retval, fd, cmd, dat);
128543412Snewton
128643412Snewton	case SVR4_I_PUSH:
128780114Sassar		DPRINTF(("I_PUSH %p\n", dat));
128843412Snewton#if defined(DEBUG_SVR4)
128980114Sassar		show_strbuf((struct svr4_strbuf *)dat);
129043412Snewton#endif
129143412Snewton		return 0;
129243412Snewton
129343412Snewton	case SVR4_I_POP:
129443412Snewton		DPRINTF(("I_POP\n"));
129543412Snewton		return 0;
129643412Snewton
129743412Snewton	case SVR4_I_LOOK:
129843412Snewton		DPRINTF(("I_LOOK\n"));
129943412Snewton		return 0;
130043412Snewton
130143412Snewton	case SVR4_I_FLUSH:
130243412Snewton		DPRINTF(("I_FLUSH\n"));
130343412Snewton		return 0;
130443412Snewton
130543412Snewton	case SVR4_I_SRDOPT:
130643412Snewton		DPRINTF(("I_SRDOPT\n"));
130743412Snewton		return 0;
130843412Snewton
130943412Snewton	case SVR4_I_GRDOPT:
131043412Snewton		DPRINTF(("I_GRDOPT\n"));
131143412Snewton		return 0;
131243412Snewton
131343412Snewton	case SVR4_I_STR:
131443412Snewton		DPRINTF(("I_STR\n"));
131583366Sjulian		return i_str(fp, td, retval, fd, cmd, dat);
131643412Snewton
131743412Snewton	case SVR4_I_SETSIG:
131843412Snewton		DPRINTF(("I_SETSIG\n"));
131983366Sjulian		return i_setsig(fp, td, retval, fd, cmd, dat);
132043412Snewton
132143412Snewton	case SVR4_I_GETSIG:
132243412Snewton	        DPRINTF(("I_GETSIG\n"));
132383366Sjulian		return i_getsig(fp, td, retval, fd, cmd, dat);
132443412Snewton
132543412Snewton	case SVR4_I_FIND:
132643412Snewton		DPRINTF(("I_FIND\n"));
132743412Snewton		/*
132843412Snewton		 * Here we are not pushing modules really, we just
132943412Snewton		 * pretend all are present
133043412Snewton		 */
133143412Snewton		*retval = 0;
133243412Snewton		return 0;
133343412Snewton
133443412Snewton	case SVR4_I_LINK:
133543412Snewton		DPRINTF(("I_LINK\n"));
133643412Snewton		return 0;
133743412Snewton
133843412Snewton	case SVR4_I_UNLINK:
133943412Snewton		DPRINTF(("I_UNLINK\n"));
134043412Snewton		return 0;
134143412Snewton
134243412Snewton	case SVR4_I_ERECVFD:
134343412Snewton		DPRINTF(("I_ERECVFD\n"));
134443412Snewton		return 0;
134543412Snewton
134643412Snewton	case SVR4_I_PEEK:
134743412Snewton		DPRINTF(("I_PEEK\n"));
134843412Snewton		return 0;
134943412Snewton
135043412Snewton	case SVR4_I_FDINSERT:
135143412Snewton		DPRINTF(("I_FDINSERT\n"));
135283366Sjulian		return i_fdinsert(fp, td, retval, fd, cmd, dat);
135343412Snewton
135443412Snewton	case SVR4_I_SENDFD:
135543412Snewton		DPRINTF(("I_SENDFD\n"));
135643412Snewton		return 0;
135743412Snewton
135843412Snewton	case SVR4_I_RECVFD:
135943412Snewton		DPRINTF(("I_RECVFD\n"));
136043412Snewton		return 0;
136143412Snewton
136243412Snewton	case SVR4_I_SWROPT:
136343412Snewton		DPRINTF(("I_SWROPT\n"));
136443412Snewton		return 0;
136543412Snewton
136643412Snewton	case SVR4_I_GWROPT:
136743412Snewton		DPRINTF(("I_GWROPT\n"));
136843412Snewton		return 0;
136943412Snewton
137043412Snewton	case SVR4_I_LIST:
137143412Snewton		DPRINTF(("I_LIST\n"));
137243412Snewton		return 0;
137343412Snewton
137443412Snewton	case SVR4_I_PLINK:
137543412Snewton		DPRINTF(("I_PLINK\n"));
137643412Snewton		return 0;
137743412Snewton
137843412Snewton	case SVR4_I_PUNLINK:
137943412Snewton		DPRINTF(("I_PUNLINK\n"));
138043412Snewton		return 0;
138143412Snewton
138243412Snewton	case SVR4_I_SETEV:
138343412Snewton		DPRINTF(("I_SETEV\n"));
138443412Snewton		return 0;
138543412Snewton
138643412Snewton	case SVR4_I_GETEV:
138743412Snewton		DPRINTF(("I_GETEV\n"));
138843412Snewton		return 0;
138943412Snewton
139043412Snewton	case SVR4_I_STREV:
139143412Snewton		DPRINTF(("I_STREV\n"));
139243412Snewton		return 0;
139343412Snewton
139443412Snewton	case SVR4_I_UNSTREV:
139543412Snewton		DPRINTF(("I_UNSTREV\n"));
139643412Snewton		return 0;
139743412Snewton
139843412Snewton	case SVR4_I_FLUSHBAND:
139943412Snewton		DPRINTF(("I_FLUSHBAND\n"));
140043412Snewton		return 0;
140143412Snewton
140243412Snewton	case SVR4_I_CKBAND:
140343412Snewton		DPRINTF(("I_CKBAND\n"));
140443412Snewton		return 0;
140543412Snewton
140643412Snewton	case SVR4_I_GETBAND:
140743412Snewton		DPRINTF(("I_GETBANK\n"));
140843412Snewton		return 0;
140943412Snewton
141043412Snewton	case SVR4_I_ATMARK:
141143412Snewton		DPRINTF(("I_ATMARK\n"));
141243412Snewton		return 0;
141343412Snewton
141443412Snewton	case SVR4_I_SETCLTIME:
141543412Snewton		DPRINTF(("I_SETCLTIME\n"));
141643412Snewton		return 0;
141743412Snewton
141843412Snewton	case SVR4_I_GETCLTIME:
141943412Snewton		DPRINTF(("I_GETCLTIME\n"));
142043412Snewton		return 0;
142143412Snewton
142243412Snewton	case SVR4_I_CANPUT:
142343412Snewton		DPRINTF(("I_CANPUT\n"));
142443412Snewton		return 0;
142543412Snewton
142643412Snewton	case SVR4__I_BIND_RSVD:
142743412Snewton		DPRINTF(("_I_BIND_RSVD\n"));
142883366Sjulian		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
142943412Snewton
143043412Snewton	case SVR4__I_RELE_RSVD:
143143412Snewton		DPRINTF(("_I_RELE_RSVD\n"));
143283366Sjulian		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
143343412Snewton
143443412Snewton	default:
143543412Snewton		DPRINTF(("unimpl cmd = %lx\n", cmd));
143643412Snewton		break;
143743412Snewton	}
143843412Snewton
143943412Snewton	return 0;
144043412Snewton}
144143412Snewton
144243412Snewton
144343412Snewton
144443412Snewtonint
144583366Sjuliansvr4_sys_putmsg(td, uap)
1446193014Sdelphij	struct thread *td;
144743412Snewton	struct svr4_sys_putmsg_args *uap;
144843412Snewton{
1449255219Spjd	cap_rights_t rights;
1450255219Spjd	struct file *fp;
145189306Salfred	int error;
145289306Salfred
1453255219Spjd	error = fget(td, uap->fd, cap_rights_init(&rights, CAP_SEND), &fp);
1454255219Spjd	if (error != 0) {
145589306Salfred#ifdef DEBUG_SVR4
145689306Salfred	        uprintf("putmsg: bad fp\n");
145789306Salfred#endif
145889306Salfred		return EBADF;
145989306Salfred	}
146089306Salfred	error = svr4_do_putmsg(td, uap, fp);
146189306Salfred	fdrop(fp, td);
146289306Salfred	return (error);
146389306Salfred}
146489306Salfred
146589306Salfredstatic int
146689306Salfredsvr4_do_putmsg(td, uap, fp)
146789306Salfred	struct thread *td;
146889306Salfred	struct svr4_sys_putmsg_args *uap;
146943412Snewton	struct file	*fp;
147089306Salfred{
147143412Snewton	struct svr4_strbuf dat, ctl;
147243412Snewton	struct svr4_strmcmd sc;
147343412Snewton	struct sockaddr_in sain;
147443412Snewton	struct sockaddr_un saun;
1475160249Sjhb	struct sockaddr *sa;
147643412Snewton	int sasize, *retval;
147743412Snewton	struct svr4_strm *st;
147843412Snewton	int error;
147943412Snewton
148083366Sjulian	retval = td->td_retval;
148154493Snewton
148243412Snewton#ifdef DEBUG_SVR4
1483107849Salfred	show_msg(">putmsg", uap->fd, uap->ctl,
1484107849Salfred		 uap->dat, uap->flags);
148543412Snewton#endif /* DEBUG_SVR4 */
148643412Snewton
1487107849Salfred	if (uap->ctl != NULL) {
1488107849Salfred	  if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) {
148943412Snewton#ifdef DEBUG_SVR4
149043412Snewton	    uprintf("putmsg: copyin(): %d\n", error);
149143412Snewton#endif
149243412Snewton	    return error;
149343412Snewton	  }
149443412Snewton	}
149543412Snewton	else
149643412Snewton		ctl.len = -1;
149743412Snewton
1498107849Salfred	if (uap->dat != NULL) {
1499107849Salfred	  if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) {
150043412Snewton#ifdef DEBUG_SVR4
150143412Snewton	    uprintf("putmsg: copyin(): %d (2)\n", error);
150243412Snewton#endif
150343412Snewton	    return error;
150443412Snewton	  }
150543412Snewton	}
150643412Snewton	else
150743412Snewton		dat.len = -1;
150843412Snewton
150943412Snewton	/*
151043412Snewton	 * Only for sockets for now.
151143412Snewton	 */
151243412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
151343412Snewton		DPRINTF(("putmsg: bad file type\n"));
151443412Snewton		return EINVAL;
151543412Snewton	}
151643412Snewton
1517121275Stjr	if (ctl.len < 0 || ctl.len > sizeof(sc)) {
151843412Snewton		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
151943412Snewton			 sizeof(struct svr4_strmcmd)));
152043412Snewton		return EINVAL;
152143412Snewton	}
152243412Snewton
152343412Snewton	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
152443412Snewton		return error;
152543412Snewton
152643412Snewton	switch (st->s_family) {
152743412Snewton	case AF_INET:
152843412Snewton	        if (sc.len != sizeof(sain)) {
152943412Snewton		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
153043412Snewton			        struct write_args wa;
153143412Snewton
153243412Snewton				/* Solaris seems to use sc.cmd = 3 to
153343412Snewton				 * send "expedited" data.  telnet uses
153443412Snewton				 * this for options processing, sending EOF,
153543412Snewton				 * etc.  I'm sure other things use it too.
153643412Snewton				 * I don't have any documentation
153743412Snewton				 * on it, so I'm making a guess that this
153843412Snewton				 * is how it works. newton@atdot.dotat.org XXX
153943412Snewton				 */
154051844Speter				DPRINTF(("sending expedited data ??\n"));
1541107849Salfred				wa.fd = uap->fd;
1542107849Salfred				wa.buf = dat.buf;
1543107849Salfred				wa.nbyte = dat.len;
1544225617Skmacy				return sys_write(td, &wa);
154543412Snewton			}
154643412Snewton	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
154743412Snewton	                return EINVAL;
154843412Snewton	        }
154943412Snewton	        netaddr_to_sockaddr_in(&sain, &sc);
1550160249Sjhb		sa = (struct sockaddr *)&sain;
155143412Snewton	        sasize = sizeof(sain);
1552160249Sjhb		if (sain.sin_family != st->s_family)
1553160249Sjhb			error = EINVAL;
155443412Snewton		break;
155543412Snewton
155643412Snewton	case AF_LOCAL:
155743412Snewton		if (ctl.len == 8) {
155843412Snewton			/* We are doing an accept; succeed */
155943412Snewton			DPRINTF(("putmsg: Do nothing\n"));
156043412Snewton			*retval = 0;
156143412Snewton			return 0;
156243412Snewton		}
156343412Snewton		else {
156443412Snewton			/* Maybe we've been given a device/inode pair */
1565130640Sphk			dev_t *dev = SVR4_ADDROF(&sc);
156643412Snewton			ino_t *ino = (ino_t *) &dev[1];
1567160558Sjhb			if (svr4_find_socket(td, fp, *dev, *ino, &saun) != 0) {
156843412Snewton				/* I guess we have it by name */
1569160249Sjhb				netaddr_to_sockaddr_un(&saun, &sc);
157043412Snewton			}
1571160558Sjhb			sa = (struct sockaddr *)&saun;
157243412Snewton			sasize = sizeof(saun);
157343412Snewton		}
157443412Snewton		break;
157543412Snewton
157643412Snewton	default:
157743412Snewton		DPRINTF(("putmsg: Unsupported address family %d\n",
157843412Snewton			 st->s_family));
157943412Snewton		return ENOSYS;
158043412Snewton	}
158143412Snewton
1582160794Sjhb	mtx_lock(&Giant);
1583160794Sjhb	st->s_cmd = sc.cmd;
1584160794Sjhb	mtx_unlock(&Giant);
1585160794Sjhb	switch (sc.cmd) {
158643412Snewton	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
158743412Snewton		{
158843412Snewton
1589160249Sjhb			return (kern_connect(td, uap->fd, sa));
159043412Snewton		}
159143412Snewton
159243412Snewton	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
159343412Snewton		{
159443412Snewton			struct msghdr msg;
159543412Snewton			struct iovec aiov;
159643412Snewton
1597160249Sjhb			msg.msg_name = sa;
159843412Snewton			msg.msg_namelen = sasize;
159943412Snewton			msg.msg_iov = &aiov;
160043412Snewton			msg.msg_iovlen = 1;
160143412Snewton			msg.msg_control = 0;
160243412Snewton			msg.msg_flags = 0;
160343412Snewton			aiov.iov_base = dat.buf;
160443412Snewton			aiov.iov_len = dat.len;
1605160249Sjhb			error = kern_sendit(td, uap->fd, &msg, uap->flags,
1606160249Sjhb			    NULL, UIO_USERSPACE);
160743412Snewton			DPRINTF(("sendto_request error: %d\n", error));
160843412Snewton			*retval = 0;
160943412Snewton			return error;
161043412Snewton		}
161143412Snewton
161243412Snewton	default:
161343412Snewton		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
161443412Snewton		return ENOSYS;
161543412Snewton	}
161643412Snewton}
161743412Snewton
161843412Snewtonint
161989308Salfredsvr4_sys_getmsg(td, uap)
162089308Salfred	struct thread *td;
162189306Salfred	struct svr4_sys_getmsg_args *uap;
162289306Salfred{
1623255219Spjd	cap_rights_t rights;
1624255219Spjd	struct file *fp;
162589306Salfred	int error;
162689306Salfred
1627255219Spjd	error = fget(td, uap->fd, cap_rights_init(&rights, CAP_RECV), &fp);
1628255219Spjd	if (error != 0) {
162989306Salfred#ifdef DEBUG_SVR4
163089306Salfred	        uprintf("getmsg: bad fp\n");
163189306Salfred#endif
163289306Salfred		return EBADF;
163389306Salfred	}
163489308Salfred	error = svr4_do_getmsg(td, uap, fp);
163589306Salfred	fdrop(fp, td);
163689306Salfred	return (error);
163789306Salfred}
163889306Salfred
163989306Salfredint
164089536Salfredsvr4_do_getmsg(td, uap, fp)
1641193014Sdelphij	struct thread *td;
164243412Snewton	struct svr4_sys_getmsg_args *uap;
164389306Salfred	struct file *fp;
164443412Snewton{
164543412Snewton	struct svr4_strbuf dat, ctl;
164643412Snewton	struct svr4_strmcmd sc;
164743412Snewton	int error, *retval;
164843412Snewton	struct msghdr msg;
164943412Snewton	struct iovec aiov;
165043412Snewton	struct sockaddr_in sain;
165143412Snewton	struct sockaddr_un saun;
1652160249Sjhb	struct sockaddr *sa;
1653160249Sjhb	socklen_t sasize;
165443412Snewton	struct svr4_strm *st;
1655160765Sjhb	struct file *afp;
165643412Snewton	int fl;
165743412Snewton
165883366Sjulian	retval = td->td_retval;
1659160249Sjhb	error = 0;
1660160765Sjhb	afp = NULL;
166154493Snewton
166243412Snewton	memset(&sc, 0, sizeof(sc));
166343412Snewton
166443412Snewton#ifdef DEBUG_SVR4
1665107849Salfred	show_msg(">getmsg", uap->fd, uap->ctl,
1666107849Salfred		 uap->dat, 0);
166743412Snewton#endif /* DEBUG_SVR4 */
166843412Snewton
1669107849Salfred	if (uap->ctl != NULL) {
1670107849Salfred		if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
167143412Snewton			return error;
1672121275Stjr		if (ctl.len < 0)
1673121275Stjr			return EINVAL;
167443412Snewton	}
167543412Snewton	else {
167643412Snewton		ctl.len = -1;
167743412Snewton		ctl.maxlen = 0;
167843412Snewton	}
167943412Snewton
1680107849Salfred	if (uap->dat != NULL) {
1681107849Salfred	    	if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0)
168243412Snewton			return error;
168343412Snewton	}
168443412Snewton	else {
168543412Snewton		dat.len = -1;
168643412Snewton		dat.maxlen = 0;
168743412Snewton	}
168843412Snewton
168943412Snewton	/*
169043412Snewton	 * Only for sockets for now.
169143412Snewton	 */
169243412Snewton	if ((st = svr4_stream_get(fp)) == NULL) {
169343412Snewton		DPRINTF(("getmsg: bad file type\n"));
169443412Snewton		return EINVAL;
169543412Snewton	}
169643412Snewton
169743412Snewton	if (ctl.maxlen == -1 || dat.maxlen == -1) {
169843412Snewton		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
169943412Snewton		return ENOSYS;
170043412Snewton	}
170143412Snewton
170243412Snewton	switch (st->s_family) {
170343412Snewton	case AF_INET:
170443412Snewton		sasize = sizeof(sain);
170543412Snewton		break;
170643412Snewton
170743412Snewton	case AF_LOCAL:
170843412Snewton		sasize = sizeof(saun);
170943412Snewton		break;
171043412Snewton
171143412Snewton	default:
171243412Snewton		DPRINTF(("getmsg: Unsupported address family %d\n",
171343412Snewton			 st->s_family));
171443412Snewton		return ENOSYS;
171543412Snewton	}
171643412Snewton
1717160794Sjhb	mtx_lock(&Giant);
171843412Snewton	switch (st->s_cmd) {
171943412Snewton	case SVR4_TI_CONNECT_REQUEST:
172043412Snewton		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
172143412Snewton		/*
172243412Snewton		 * We do the connect in one step, so the putmsg should
172343412Snewton		 * have gotten the error.
172443412Snewton		 */
172543412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
172643412Snewton		sc.len = 0;
172743412Snewton
172843412Snewton		ctl.len = 8;
172943412Snewton		dat.len = -1;
173043412Snewton		fl = 1;
173143412Snewton		st->s_cmd = sc.cmd;
173243412Snewton		break;
173343412Snewton
173443412Snewton	case SVR4_TI_OK_REPLY:
173543412Snewton		DPRINTF(("getmsg: TI_OK_REPLY\n"));
173643412Snewton		/*
173743412Snewton		 * We are immediately after a connect reply, so we send
173843412Snewton		 * a connect verification.
173943412Snewton		 */
174043412Snewton
1741160249Sjhb		error = kern_getpeername(td, uap->fd, &sa, &sasize);
1742160249Sjhb		if (error) {
1743160794Sjhb			mtx_unlock(&Giant);
174443412Snewton			DPRINTF(("getmsg: getpeername failed %d\n", error));
174543412Snewton			return error;
174643412Snewton		}
174743412Snewton
174843412Snewton		sc.cmd = SVR4_TI_CONNECT_REPLY;
174943412Snewton		sc.pad[0] = 0x4;
175043412Snewton		sc.offs = 0x18;
175143412Snewton		sc.pad[1] = 0x14;
175243412Snewton		sc.pad[2] = 0x04000402;
175343412Snewton
175443412Snewton		switch (st->s_family) {
175543412Snewton		case AF_INET:
175643412Snewton			sc.len = sasize;
1757160249Sjhb			sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
175843412Snewton			break;
175943412Snewton
176043412Snewton		case AF_LOCAL:
176143412Snewton			sc.len = sasize + 4;
1762160249Sjhb			sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
176343412Snewton			break;
176443412Snewton
176543412Snewton		default:
1766160794Sjhb			mtx_unlock(&Giant);
1767160249Sjhb			free(sa, M_SONAME);
176843412Snewton			return ENOSYS;
176943412Snewton		}
1770160249Sjhb		free(sa, M_SONAME);
177143412Snewton
177243412Snewton		ctl.len = 40;
177343412Snewton		dat.len = -1;
177443412Snewton		fl = 0;
177543412Snewton		st->s_cmd = sc.cmd;
177643412Snewton		break;
177743412Snewton
177843412Snewton	case SVR4_TI__ACCEPT_OK:
177943412Snewton		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
178043412Snewton		/*
178143412Snewton		 * We do the connect in one step, so the putmsg should
178243412Snewton		 * have gotten the error.
178343412Snewton		 */
178443412Snewton		sc.cmd = SVR4_TI_OK_REPLY;
178543412Snewton		sc.len = 1;
178643412Snewton
178743412Snewton		ctl.len = 8;
178843412Snewton		dat.len = -1;
178943412Snewton		fl = 1;
179043412Snewton		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
179143412Snewton		break;
179243412Snewton
179343412Snewton	case SVR4_TI__ACCEPT_WAIT:
179443412Snewton		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
179543412Snewton		/*
179643412Snewton		 * We are after a listen, so we try to accept...
179743412Snewton		 */
1798160249Sjhb
1799160765Sjhb		error = kern_accept(td, uap->fd, &sa, &sasize, &afp);
1800160249Sjhb		if (error) {
1801160794Sjhb			mtx_unlock(&Giant);
180243412Snewton			DPRINTF(("getmsg: accept failed %d\n", error));
180343412Snewton			return error;
180443412Snewton		}
180543412Snewton
180643412Snewton		st->s_afd = *retval;
180743412Snewton
180843412Snewton		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
180943412Snewton
181043412Snewton		sc.cmd = SVR4_TI_ACCEPT_REPLY;
181143412Snewton		sc.offs = 0x18;
181243412Snewton		sc.pad[0] = 0x0;
181343412Snewton
181443412Snewton		switch (st->s_family) {
181543412Snewton		case AF_INET:
181643412Snewton			sc.pad[1] = 0x28;
1817160249Sjhb			sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)&sa);
181843412Snewton			ctl.len = 40;
181943412Snewton			sc.len = sasize;
182043412Snewton			break;
182143412Snewton
182243412Snewton		case AF_LOCAL:
182343412Snewton			sc.pad[1] = 0x00010000;
182443412Snewton			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
182543412Snewton			sc.pad[3] = 0x00010000;
182643412Snewton			ctl.len = 134;
182743412Snewton			sc.len = sasize + 4;
182843412Snewton			break;
182943412Snewton
183043412Snewton		default:
1831160765Sjhb			fdclose(td->td_proc->p_fd, afp, st->s_afd, td);
1832160765Sjhb			fdrop(afp, td);
1833160765Sjhb			st->s_afd = -1;
1834160794Sjhb			mtx_unlock(&Giant);
1835160249Sjhb			free(sa, M_SONAME);
183643412Snewton			return ENOSYS;
183743412Snewton		}
1838160249Sjhb		free(sa, M_SONAME);
183943412Snewton
184043412Snewton		dat.len = -1;
184143412Snewton		fl = 0;
184243412Snewton		st->s_cmd = SVR4_TI__ACCEPT_OK;
184343412Snewton		break;
184443412Snewton
184543412Snewton	case SVR4_TI_SENDTO_REQUEST:
184643412Snewton		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
184743412Snewton		if (ctl.maxlen > 36 && ctl.len < 36)
184843412Snewton		    ctl.len = 36;
184943412Snewton
1850121275Stjr		if (ctl.len > sizeof(sc))
1851121275Stjr			ctl.len = sizeof(sc);
1852121275Stjr
1853160794Sjhb		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) {
1854160794Sjhb			mtx_unlock(&Giant);
185543412Snewton			return error;
1856160794Sjhb		}
185743412Snewton
185843412Snewton		switch (st->s_family) {
185943412Snewton		case AF_INET:
1860160249Sjhb			sa = (struct sockaddr *)&sain;
186143412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
186243412Snewton			break;
186343412Snewton
186443412Snewton		case AF_LOCAL:
1865160249Sjhb			sa = (struct sockaddr *)&saun;
186643412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
186743412Snewton			break;
186843412Snewton
186943412Snewton		default:
1870160794Sjhb			mtx_unlock(&Giant);
187143412Snewton			return ENOSYS;
187243412Snewton		}
187343412Snewton
1874160249Sjhb		msg.msg_name = sa;
187543412Snewton		msg.msg_namelen = sasize;
187643412Snewton		msg.msg_iov = &aiov;
187743412Snewton		msg.msg_iovlen = 1;
187843412Snewton		msg.msg_control = 0;
187943412Snewton		aiov.iov_base = dat.buf;
188043412Snewton		aiov.iov_len = dat.maxlen;
188143412Snewton		msg.msg_flags = 0;
188243412Snewton
1883160249Sjhb		error = kern_recvit(td, uap->fd, &msg, UIO_SYSSPACE, NULL);
188443412Snewton
188543412Snewton		if (error) {
1886160794Sjhb			mtx_unlock(&Giant);
188743412Snewton			DPRINTF(("getmsg: recvit failed %d\n", error));
188843412Snewton			return error;
188943412Snewton		}
189043412Snewton
189143412Snewton		sc.cmd = SVR4_TI_RECVFROM_IND;
189243412Snewton
189343412Snewton		switch (st->s_family) {
189443412Snewton		case AF_INET:
189543412Snewton			sc.len = sasize;
189643412Snewton			sockaddr_to_netaddr_in(&sc, &sain);
189743412Snewton			break;
189843412Snewton
189943412Snewton		case AF_LOCAL:
190043412Snewton			sc.len = sasize + 4;
190143412Snewton			sockaddr_to_netaddr_un(&sc, &saun);
190243412Snewton			break;
190343412Snewton
190443412Snewton		default:
1905160794Sjhb			mtx_unlock(&Giant);
190643412Snewton			return ENOSYS;
190743412Snewton		}
190843412Snewton
190943412Snewton		dat.len = *retval;
191043412Snewton		fl = 0;
191143412Snewton		st->s_cmd = sc.cmd;
191243412Snewton		break;
191343412Snewton
191443412Snewton	default:
191543412Snewton		st->s_cmd = sc.cmd;
191643412Snewton		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
191743412Snewton		        struct read_args ra;
191843412Snewton
191972082Sasmodai			/* More weirdness:  Again, I can't find documentation
192043412Snewton			 * to back this up, but when a process does a generic
192143412Snewton			 * "getmsg()" call it seems that the command field is
192243412Snewton			 * zero and the length of the data area is zero.  I
192343412Snewton			 * think processes expect getmsg() to fill in dat.len
192443412Snewton			 * after reading at most dat.maxlen octets from the
192543412Snewton			 * stream.  Since we're using sockets I can let
192643412Snewton			 * read() look after it and frob return values
192743412Snewton			 * appropriately (or inappropriately :-)
192843412Snewton			 *   -- newton@atdot.dotat.org        XXX
192943412Snewton			 */
1930107849Salfred			ra.fd = uap->fd;
1931107849Salfred			ra.buf = dat.buf;
1932107849Salfred			ra.nbyte = dat.maxlen;
1933225617Skmacy			if ((error = sys_read(td, &ra)) != 0) {
1934160794Sjhb				mtx_unlock(&Giant);
193543412Snewton			        return error;
193643412Snewton			}
193743412Snewton			dat.len = *retval;
193843412Snewton			*retval = 0;
193943412Snewton			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
194043412Snewton			break;
194143412Snewton		}
1942160794Sjhb		mtx_unlock(&Giant);
194343412Snewton		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
194443412Snewton		return EINVAL;
194543412Snewton	}
194643412Snewton
1947107849Salfred	if (uap->ctl) {
1948144014Sdas		if (ctl.len > sizeof(sc))
1949144014Sdas			ctl.len = sizeof(sc);
195043412Snewton		if (ctl.len != -1)
1951160765Sjhb			error = copyout(&sc, ctl.buf, ctl.len);
195243412Snewton
1953160765Sjhb		if (error == 0)
1954160765Sjhb			error = copyout(&ctl, uap->ctl, sizeof(ctl));
195543412Snewton	}
195643412Snewton
1957107849Salfred	if (uap->dat) {
1958160765Sjhb		if (error == 0)
1959160765Sjhb			error = copyout(&dat, uap->dat, sizeof(dat));
196043412Snewton	}
196143412Snewton
1962107849Salfred	if (uap->flags) { /* XXX: Need translation */
1963160765Sjhb		if (error == 0)
1964160765Sjhb			error = copyout(&fl, uap->flags, sizeof(fl));
196543412Snewton	}
196643412Snewton
1967160765Sjhb	if (error) {
1968160765Sjhb		if (afp) {
1969160765Sjhb			fdclose(td->td_proc->p_fd, afp, st->s_afd, td);
1970160765Sjhb			fdrop(afp, td);
1971160765Sjhb			st->s_afd = -1;
1972160765Sjhb		}
1973160794Sjhb		mtx_unlock(&Giant);
1974160765Sjhb		return (error);
1975160765Sjhb	}
1976160794Sjhb	mtx_unlock(&Giant);
1977160765Sjhb	if (afp)
1978160765Sjhb		fdrop(afp, td);
1979160765Sjhb
198043412Snewton	*retval = 0;
198143412Snewton
198243412Snewton#ifdef DEBUG_SVR4
1983107849Salfred	show_msg("<getmsg", uap->fd, uap->ctl,
1984107849Salfred		 uap->dat, fl);
198543412Snewton#endif /* DEBUG_SVR4 */
198643412Snewton	return error;
198743412Snewton}
198843412Snewton
198983366Sjulianint svr4_sys_send(td, uap)
199083366Sjulian	struct thread *td;
199143412Snewton	struct svr4_sys_send_args *uap;
199243412Snewton{
1993183040Sed	struct sendto_args sta;
1994183040Sed
1995183040Sed	sta.s = uap->s;
1996183040Sed	sta.buf = uap->buf;
1997183040Sed	sta.len = uap->len;
1998183040Sed	sta.flags = uap->flags;
1999183040Sed	sta.to = NULL;
2000183040Sed	sta.tolen = 0;
2001183040Sed
2002225617Skmacy	return (sys_sendto(td, &sta));
200343412Snewton}
200443412Snewton
200583366Sjulianint svr4_sys_recv(td, uap)
200683366Sjulian	struct thread *td;
200743412Snewton	struct svr4_sys_recv_args *uap;
200843412Snewton{
2009183040Sed	struct recvfrom_args rfa;
2010183040Sed
2011183040Sed	rfa.s = uap->s;
2012183040Sed	rfa.buf = uap->buf;
2013183040Sed	rfa.len = uap->len;
2014183040Sed	rfa.flags = uap->flags;
2015183040Sed	rfa.from = NULL;
2016183040Sed	rfa.fromlenaddr = NULL;
2017183040Sed
2018225617Skmacy	return (sys_recvfrom(td, &rfa));
201943412Snewton}
202043412Snewton
202143412Snewton/*
202243412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into
202343412Snewton * sendto().  Let's leave it here for now...
202443412Snewton */
202543412Snewtonint
202683366Sjuliansvr4_sys_sendto(td, uap)
202783366Sjulian        struct thread *td;
202843412Snewton        struct svr4_sys_sendto_args *uap;
202943412Snewton{
203043412Snewton        struct sendto_args sa;
203143412Snewton
2032107849Salfred	sa.s = uap->s;
2033107849Salfred	sa.buf = uap->buf;
2034107849Salfred	sa.len = uap->len;
2035107849Salfred	sa.flags = uap->flags;
2036107849Salfred	sa.to = (caddr_t)uap->to;
2037107849Salfred	sa.tolen = uap->tolen;
203843412Snewton
203943412Snewton	DPRINTF(("calling sendto()\n"));
2040225617Skmacy	return sys_sendto(td, &sa);
204143412Snewton}
204243412Snewton
2043