svr4_stream.c revision 139743
1/*-
2 * Copyright (c) 1998 Mark Newton.  All rights reserved.
3 * Copyright (c) 1994, 1996 Christos Zoulas.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Christos Zoulas.
16 * 4. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*
32 * Pretend that we have streams...
33 * Yes, this is gross.
34 *
35 * ToDo: The state machine for getmsg needs re-thinking
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_stream.c 139743 2005-01-05 22:34:37Z imp $");
40
41#define COMPAT_43 1
42
43#include "opt_mac.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/fcntl.h>
48#include <sys/filedesc.h>
49#include <sys/filio.h>
50#include <sys/lock.h>
51#include <sys/malloc.h>
52#include <sys/file.h> 		/* Must come after sys/malloc.h */
53#include <sys/mac.h>
54#include <sys/mbuf.h>
55#include <sys/mutex.h>
56#include <sys/proc.h>
57#include <sys/protosw.h>
58#include <sys/signal.h>
59#include <sys/signalvar.h>
60#include <sys/socket.h>
61#include <sys/socketvar.h>
62#include <sys/stat.h>
63#include <sys/syscallsubr.h>
64#include <sys/sysproto.h>
65#include <sys/uio.h>
66#include <sys/ktrace.h>		/* Must come after sys/uio.h */
67#include <sys/un.h>
68
69#include <netinet/in.h>
70
71#include <compat/svr4/svr4.h>
72#include <compat/svr4/svr4_types.h>
73#include <compat/svr4/svr4_util.h>
74#include <compat/svr4/svr4_signal.h>
75#include <compat/svr4/svr4_proto.h>
76#include <compat/svr4/svr4_stropts.h>
77#include <compat/svr4/svr4_timod.h>
78#include <compat/svr4/svr4_sockmod.h>
79#include <compat/svr4/svr4_ioctl.h>
80#include <compat/svr4/svr4_socket.h>
81
82/* Utils */
83static int clean_pipe(struct thread *, const char *);
84static void getparm(struct file *, struct svr4_si_sockparms *);
85static int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
86			       struct file *);
87static int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
88			       struct file *);
89
90/* Address Conversions */
91static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
92					const struct sockaddr_in *);
93static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
94					const struct sockaddr_un *);
95static void netaddr_to_sockaddr_in(struct sockaddr_in *,
96					const struct svr4_strmcmd *);
97static void netaddr_to_sockaddr_un(struct sockaddr_un *,
98					const struct svr4_strmcmd *);
99
100/* stream ioctls */
101static int i_nread(struct file *, struct thread *, register_t *, int,
102			u_long, caddr_t);
103static int i_fdinsert(struct file *, struct thread *, register_t *, int,
104			   u_long, caddr_t);
105static int i_str(struct file *, struct thread *, register_t *, int,
106			u_long, caddr_t);
107static int i_setsig(struct file *, struct thread *, register_t *, int,
108			u_long, caddr_t);
109static int i_getsig(struct file *, struct thread *, register_t *, int,
110			u_long, caddr_t);
111static int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
112			     u_long, caddr_t);
113static int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
114			     u_long, caddr_t);
115
116/* i_str sockmod calls */
117static int sockmod(struct file *, int, struct svr4_strioctl *,
118			      struct thread *);
119static int si_listen(struct file *, int, struct svr4_strioctl *,
120			      struct thread *);
121static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
122			      struct thread *);
123static int si_sockparams(struct file *, int, struct svr4_strioctl *,
124			      struct thread *);
125static int si_shutdown	(struct file *, int, struct svr4_strioctl *,
126			      struct thread *);
127static int si_getudata(struct file *, int, struct svr4_strioctl *,
128			      struct thread *);
129
130/* i_str timod calls */
131static int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
132static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
133			      struct thread *);
134static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
135
136/* infrastructure */
137static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
138
139static int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
140			    caddr_t namelenp);
141
142/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
143 * it isn't part of a "public" interface;  We're supposed to use
144 * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
145 * that matter.  Solution:  Suck sendit()/recvit() into here where we
146 * can do what we like.
147 *
148 * I hate code duplication.
149 *
150 * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
151 */
152static int
153svr4_sendit(td, s, mp, flags)
154	register struct thread *td;
155	int s;
156	register struct msghdr *mp;
157	int flags;
158{
159	struct uio auio;
160	register struct iovec *iov;
161	register int i;
162	struct mbuf *control;
163	struct sockaddr *to;
164	int len, error;
165	struct socket *so;
166#ifdef KTRACE
167	struct uio *ktruio = NULL;
168#endif
169
170	if ((error = fgetsock(td, s, &so, NULL)) != 0)
171		return (error);
172
173#ifdef MAC
174	SOCK_LOCK(so);
175	error = mac_check_socket_send(td->td_ucred, so);
176	SOCK_UNLOCK(so);
177	if (error)
178		goto done1;
179#endif
180
181	auio.uio_iov = mp->msg_iov;
182	auio.uio_iovcnt = mp->msg_iovlen;
183	auio.uio_segflg = UIO_USERSPACE;
184	auio.uio_rw = UIO_WRITE;
185	auio.uio_td = td;
186	auio.uio_offset = 0;			/* XXX */
187	auio.uio_resid = 0;
188	iov = mp->msg_iov;
189	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
190		if ((auio.uio_resid += iov->iov_len) < 0) {
191			error = EINVAL;
192			goto done1;
193		}
194	}
195	if (mp->msg_name) {
196		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
197		if (error)
198			goto done1;
199	} else {
200		to = 0;
201	}
202	if (mp->msg_control) {
203		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
204			error = EINVAL;
205			goto bad;
206		}
207		error = sockargs(&control, mp->msg_control,
208		    mp->msg_controllen, MT_CONTROL);
209		if (error)
210			goto bad;
211	} else {
212		control = 0;
213	}
214#ifdef KTRACE
215	if (KTRPOINT(td, KTR_GENIO))
216		ktruio = cloneuio(&auio);
217#endif
218	len = auio.uio_resid;
219	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
220						     flags, td);
221	if (error) {
222		if (auio.uio_resid != len && (error == ERESTART ||
223		    error == EINTR || error == EWOULDBLOCK))
224			error = 0;
225		if (error == EPIPE) {
226			PROC_LOCK(td->td_proc);
227			psignal(td->td_proc, SIGPIPE);
228			PROC_UNLOCK(td->td_proc);
229		}
230	}
231	if (error == 0)
232		td->td_retval[0] = len - auio.uio_resid;
233#ifdef KTRACE
234	if (ktruio != NULL) {
235		ktruio->uio_resid = td->td_retval[0];
236		ktrgenio(s, UIO_WRITE, ktruio, error);
237	}
238#endif
239bad:
240	if (to)
241		FREE(to, M_SONAME);
242done1:
243	fputsock(so);
244	return (error);
245}
246
247static int
248svr4_recvit(td, s, mp, namelenp)
249	register struct thread *td;
250	int s;
251	register struct msghdr *mp;
252	caddr_t namelenp;
253{
254	struct uio auio;
255	register struct iovec *iov;
256	register int i;
257	int len, error;
258	struct mbuf *m, *control = 0;
259	caddr_t ctlbuf;
260	struct socket *so;
261	struct sockaddr *fromsa = 0;
262#ifdef KTRACE
263	struct uio *ktruio = NULL;
264#endif
265
266	if ((error = fgetsock(td, s, &so, NULL)) != 0)
267		return (error);
268
269#ifdef MAC
270	SOCK_LOCK(so);
271	error = mac_check_socket_receive(td->td_ucred, so);
272	SOCK_UNLOCK(so);
273	if (error)
274		goto done1;
275#endif
276
277	auio.uio_iov = mp->msg_iov;
278	auio.uio_iovcnt = mp->msg_iovlen;
279	auio.uio_segflg = UIO_USERSPACE;
280	auio.uio_rw = UIO_READ;
281	auio.uio_td = td;
282	auio.uio_offset = 0;			/* XXX */
283	auio.uio_resid = 0;
284	iov = mp->msg_iov;
285	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
286		if ((auio.uio_resid += iov->iov_len) < 0) {
287			error = EINVAL;
288			goto done1;
289		}
290	}
291#ifdef KTRACE
292	if (KTRPOINT(td, KTR_GENIO))
293		ktruio = cloneuio(&auio);
294#endif
295	len = auio.uio_resid;
296	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
297	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
298	    &mp->msg_flags);
299	if (error) {
300		if (auio.uio_resid != len && (error == ERESTART ||
301		    error == EINTR || error == EWOULDBLOCK))
302			error = 0;
303	}
304#ifdef KTRACE
305	if (ktruio != NULL) {
306		ktruio->uio_resid = len - auio.uio_resid;
307		ktrgenio(s, UIO_READ, ktruio, error);
308	}
309#endif
310	if (error)
311		goto out;
312	td->td_retval[0] = len - auio.uio_resid;
313	if (mp->msg_name) {
314		len = mp->msg_namelen;
315		if (len <= 0 || fromsa == 0)
316			len = 0;
317		else {
318			/* save sa_len before it is destroyed by MSG_COMPAT */
319			len = MIN(len, fromsa->sa_len);
320			error = copyout(fromsa,
321			    (caddr_t)mp->msg_name, (unsigned)len);
322			if (error)
323				goto out;
324		}
325		mp->msg_namelen = len;
326		if (namelenp &&
327		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
328			goto out;
329		}
330	}
331	if (mp->msg_control) {
332		len = mp->msg_controllen;
333		m = control;
334		mp->msg_controllen = 0;
335		ctlbuf = (caddr_t) mp->msg_control;
336
337		while (m && len > 0) {
338			unsigned int tocopy;
339
340			if (len >= m->m_len)
341				tocopy = m->m_len;
342			else {
343				mp->msg_flags |= MSG_CTRUNC;
344				tocopy = len;
345			}
346
347			if ((error = copyout((caddr_t)mtod(m, caddr_t),
348					ctlbuf, tocopy)) != 0)
349				goto out;
350
351			ctlbuf += tocopy;
352			len -= tocopy;
353			m = m->m_next;
354		}
355		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
356	}
357out:
358	if (fromsa)
359		FREE(fromsa, M_SONAME);
360	if (control)
361		m_freem(control);
362done1:
363	fputsock(so);
364	return (error);
365}
366
367#ifdef DEBUG_SVR4
368static void bufprint(u_char *, size_t);
369static int show_ioc(const char *, struct svr4_strioctl *);
370static int show_strbuf(struct svr4_strbuf *);
371static void show_msg(const char *, int, struct svr4_strbuf *,
372			  struct svr4_strbuf *, int);
373
374static void
375bufprint(buf, len)
376	u_char *buf;
377	size_t len;
378{
379	size_t i;
380
381	uprintf("\n\t");
382	for (i = 0; i < len; i++) {
383		uprintf("%x ", buf[i]);
384		if (i && (i % 16) == 0)
385			uprintf("\n\t");
386	}
387}
388
389static int
390show_ioc(str, ioc)
391	const char		*str;
392	struct svr4_strioctl	*ioc;
393{
394	u_char *ptr = NULL;
395	int len;
396	int error;
397
398	len = ioc->len;
399	if (len > 1024)
400		len = 1024;
401
402	if (len > 0) {
403		ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
404		if ((error = copyin(ioc->buf, ptr, len)) != 0) {
405			free((char *) ptr, M_TEMP);
406			return error;
407		}
408	}
409
410	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
411	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
412
413	if (ptr != NULL)
414		bufprint(ptr, len);
415
416	uprintf("}\n");
417
418	if (ptr != NULL)
419		free((char *) ptr, M_TEMP);
420	return 0;
421}
422
423
424static int
425show_strbuf(str)
426	struct svr4_strbuf *str;
427{
428	int error;
429	u_char *ptr = NULL;
430	int maxlen = str->maxlen;
431	int len = str->len;
432
433	if (maxlen > 8192)
434		maxlen = 8192;
435
436	if (maxlen < 0)
437		maxlen = 0;
438
439	if (len >= maxlen)
440		len = maxlen;
441
442	if (len > 0) {
443	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
444
445	    if ((error = copyin(str->buf, ptr, len)) != 0) {
446		    free((char *) ptr, M_TEMP);
447		    return error;
448	    }
449	}
450
451	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
452
453	if (ptr)
454		bufprint(ptr, len);
455
456	uprintf("]}");
457
458	if (ptr)
459		free((char *) ptr, M_TEMP);
460
461	return 0;
462}
463
464
465static void
466show_msg(str, fd, ctl, dat, flags)
467	const char		*str;
468	int			 fd;
469	struct svr4_strbuf	*ctl;
470	struct svr4_strbuf	*dat;
471	int			 flags;
472{
473	struct svr4_strbuf	buf;
474	int error;
475
476	uprintf("%s(%d", str, fd);
477	if (ctl != NULL) {
478		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
479			return;
480		show_strbuf(&buf);
481	}
482	else
483		uprintf(", NULL");
484
485	if (dat != NULL) {
486		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
487			return;
488		show_strbuf(&buf);
489	}
490	else
491		uprintf(", NULL");
492
493	uprintf(", %x);\n", flags);
494}
495
496#endif /* DEBUG_SVR4 */
497
498/*
499 * We are faced with an interesting situation. On svr4 unix sockets
500 * are really pipes. But we really have sockets, and we might as
501 * well use them. At the point where svr4 calls TI_BIND, it has
502 * already created a named pipe for the socket using mknod(2).
503 * We need to create a socket with the same name when we bind,
504 * so we need to remove the pipe before, otherwise we'll get address
505 * already in use. So we *carefully* remove the pipe, to avoid
506 * using this as a random file removal tool. We use system calls
507 * to avoid code duplication.
508 */
509static int
510clean_pipe(td, path)
511	struct thread *td;
512	const char *path;
513{
514	struct lstat_args la;
515	struct unlink_args ua;
516	struct stat st;
517	int error;
518	caddr_t sg = stackgap_init();
519	size_t l = strlen(path) + 1;
520	void *tpath;
521
522	if ((tpath = stackgap_alloc(&sg, l)) == NULL)
523		return ENAMETOOLONG;
524	la.ub = stackgap_alloc(&sg, sizeof(struct stat));
525
526	if ((error = copyout(path, tpath, l)) != 0)
527		return error;
528
529	la.path = tpath;
530
531	if ((error = lstat(td, &la)) != 0)
532		return 0;
533
534	if ((error = copyin(la.ub, &st, sizeof(st))) != 0)
535		return 0;
536
537	/*
538	 * Make sure we are dealing with a mode 0 named pipe.
539	 */
540	if ((st.st_mode & S_IFMT) != S_IFIFO)
541		return 0;
542
543	if ((st.st_mode & ALLPERMS) != 0)
544		return 0;
545
546	ua.path = la.path;
547
548	if ((error = unlink(td, &ua)) != 0) {
549		DPRINTF(("clean_pipe: unlink failed %d\n", error));
550		return error;
551	}
552
553	return 0;
554}
555
556
557static void
558sockaddr_to_netaddr_in(sc, sain)
559	struct svr4_strmcmd *sc;
560	const struct sockaddr_in *sain;
561{
562	struct svr4_netaddr_in *na;
563	na = SVR4_ADDROF(sc);
564
565	na->family = sain->sin_family;
566	na->port = sain->sin_port;
567	na->addr = sain->sin_addr.s_addr;
568	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
569		 na->addr));
570}
571
572
573static void
574sockaddr_to_netaddr_un(sc, saun)
575	struct svr4_strmcmd *sc;
576	const struct sockaddr_un *saun;
577{
578	struct svr4_netaddr_un *na;
579	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
580	    sizeof(*sc);
581	const char *src;
582
583	na = SVR4_ADDROF(sc);
584	na->family = saun->sun_family;
585	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
586		if (dst == edst)
587			break;
588	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
589}
590
591
592static void
593netaddr_to_sockaddr_in(sain, sc)
594	struct sockaddr_in *sain;
595	const struct svr4_strmcmd *sc;
596{
597	const struct svr4_netaddr_in *na;
598
599
600	na = SVR4_C_ADDROF(sc);
601	memset(sain, 0, sizeof(*sain));
602	sain->sin_len = sizeof(*sain);
603	sain->sin_family = na->family;
604	sain->sin_port = na->port;
605	sain->sin_addr.s_addr = na->addr;
606	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
607		 sain->sin_port, sain->sin_addr.s_addr));
608}
609
610
611static void
612netaddr_to_sockaddr_un(saun, sc)
613	struct sockaddr_un *saun;
614	const struct svr4_strmcmd *sc;
615{
616	const struct svr4_netaddr_un *na;
617	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
618	const char *src;
619
620	na = SVR4_C_ADDROF(sc);
621	memset(saun, 0, sizeof(*saun));
622	saun->sun_family = na->family;
623	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
624		if (dst == edst)
625			break;
626	saun->sun_len = dst - saun->sun_path;
627	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
628		 saun->sun_path));
629}
630
631
632static void
633getparm(fp, pa)
634	struct file *fp;
635	struct svr4_si_sockparms *pa;
636{
637	struct svr4_strm *st;
638	struct socket *so;
639
640	st = svr4_stream_get(fp);
641	if (st == NULL)
642		return;
643
644	so = fp->f_data;
645
646	pa->family = st->s_family;
647
648	switch (so->so_type) {
649	case SOCK_DGRAM:
650		pa->type = SVR4_T_CLTS;
651		pa->protocol = IPPROTO_UDP;
652		DPRINTF(("getparm(dgram)\n"));
653		return;
654
655	case SOCK_STREAM:
656	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
657		pa->protocol = IPPROTO_IP;
658		DPRINTF(("getparm(stream)\n"));
659		return;
660
661	case SOCK_RAW:
662		pa->type = SVR4_T_CLTS;
663		pa->protocol = IPPROTO_RAW;
664		DPRINTF(("getparm(raw)\n"));
665		return;
666
667	default:
668		pa->type = 0;
669		pa->protocol = 0;
670		DPRINTF(("getparm(type %d?)\n", so->so_type));
671		return;
672	}
673}
674
675
676static int
677si_ogetudata(fp, fd, ioc, td)
678	struct file		*fp;
679	int 			 fd;
680	struct svr4_strioctl	*ioc;
681	struct thread		*td;
682{
683	int error;
684	struct svr4_si_oudata ud;
685	struct svr4_si_sockparms pa;
686
687	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
688		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
689			 sizeof(ud), ioc->len));
690		return EINVAL;
691	}
692
693	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
694		return error;
695
696	getparm(fp, &pa);
697
698	switch (pa.family) {
699	case AF_INET:
700	    ud.tidusize = 16384;
701	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
702	    if (pa.type == SVR4_SOCK_STREAM)
703		    ud.etsdusize = 1;
704	    else
705		    ud.etsdusize = 0;
706	    break;
707
708	case AF_LOCAL:
709	    ud.tidusize = 65536;
710	    ud.addrsize = 128;
711	    ud.etsdusize = 128;
712	    break;
713
714	default:
715	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
716		     pa.family));
717	    return ENOSYS;
718	}
719
720	/* I have no idea what these should be! */
721	ud.optsize = 128;
722	ud.tsdusize = 128;
723
724	ud.servtype = pa.type;
725
726	/* XXX: Fixme */
727	ud.so_state = 0;
728	ud.so_options = 0;
729	return copyout(&ud, ioc->buf, ioc->len);
730}
731
732
733static int
734si_sockparams(fp, fd, ioc, td)
735	struct file		*fp;
736	int 			 fd;
737	struct svr4_strioctl	*ioc;
738	struct thread		*td;
739{
740	struct svr4_si_sockparms pa;
741
742	getparm(fp, &pa);
743	return copyout(&pa, ioc->buf, sizeof(pa));
744}
745
746
747static int
748si_listen(fp, fd, ioc, td)
749	struct file		*fp;
750	int 			 fd;
751	struct svr4_strioctl	*ioc;
752	struct thread		*td;
753{
754	int error;
755	struct svr4_strm *st = svr4_stream_get(fp);
756	struct svr4_strmcmd lst;
757	struct listen_args la;
758
759	if (st == NULL)
760		return EINVAL;
761
762	if (ioc->len < 0 || ioc->len > sizeof(lst))
763		return EINVAL;
764
765	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
766		return error;
767
768	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
769		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
770		return EINVAL;
771	}
772
773	/*
774	 * We are making assumptions again...
775	 */
776	la.s = fd;
777	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
778	la.backlog = 5;
779
780	if ((error = listen(td, &la)) != 0) {
781		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
782		return error;
783	}
784
785	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
786	lst.cmd = SVR4_TI_BIND_REPLY;
787
788	switch (st->s_family) {
789	case AF_INET:
790		/* XXX: Fill the length here */
791		break;
792
793	case AF_LOCAL:
794		lst.len = 140;
795		lst.pad[28] = 0x00000000;	/* magic again */
796		lst.pad[29] = 0x00000800;	/* magic again */
797		lst.pad[30] = 0x80001400;	/* magic again */
798		break;
799
800	default:
801		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
802		    st->s_family));
803		return ENOSYS;
804	}
805
806
807	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
808		return error;
809
810	return 0;
811}
812
813
814static int
815si_getudata(fp, fd, ioc, td)
816	struct file		*fp;
817	int 			 fd;
818	struct svr4_strioctl	*ioc;
819	struct thread		*td;
820{
821	int error;
822	struct svr4_si_udata ud;
823
824	if (sizeof(ud) != ioc->len) {
825		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
826			 sizeof(ud), ioc->len));
827		return EINVAL;
828	}
829
830	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
831		return error;
832
833	getparm(fp, &ud.sockparms);
834
835	switch (ud.sockparms.family) {
836	case AF_INET:
837	    DPRINTF(("getudata_inet\n"));
838	    ud.tidusize = 16384;
839	    ud.tsdusize = 16384;
840	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
841	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
842		    ud.etsdusize = 1;
843	    else
844		    ud.etsdusize = 0;
845	    ud.optsize = 0;
846	    break;
847
848	case AF_LOCAL:
849	    DPRINTF(("getudata_local\n"));
850	    ud.tidusize = 65536;
851	    ud.tsdusize = 128;
852	    ud.addrsize = 128;
853	    ud.etsdusize = 128;
854	    ud.optsize = 128;
855	    break;
856
857	default:
858	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
859		     ud.sockparms.family));
860	    return ENOSYS;
861	}
862
863
864	ud.servtype = ud.sockparms.type;
865	DPRINTF(("ud.servtype = %d\n", ud.servtype));
866	/* XXX: Fixme */
867	ud.so_state = 0;
868	ud.so_options = 0;
869	return copyout(&ud, ioc->buf, sizeof(ud));
870}
871
872
873static int
874si_shutdown(fp, fd, ioc, td)
875	struct file		*fp;
876	int 			 fd;
877	struct svr4_strioctl	*ioc;
878	struct thread		*td;
879{
880	int error;
881	struct shutdown_args ap;
882
883	if (ioc->len != sizeof(ap.how)) {
884		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
885			 sizeof(ap.how), ioc->len));
886		return EINVAL;
887	}
888
889	if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0)
890		return error;
891
892	ap.s = fd;
893
894	return shutdown(td, &ap);
895}
896
897
898static int
899sockmod(fp, fd, ioc, td)
900	struct file		*fp;
901	int			 fd;
902	struct svr4_strioctl	*ioc;
903	struct thread		*td;
904{
905	switch (ioc->cmd) {
906	case SVR4_SI_OGETUDATA:
907		DPRINTF(("SI_OGETUDATA\n"));
908		return si_ogetudata(fp, fd, ioc, td);
909
910	case SVR4_SI_SHUTDOWN:
911		DPRINTF(("SI_SHUTDOWN\n"));
912		return si_shutdown(fp, fd, ioc, td);
913
914	case SVR4_SI_LISTEN:
915		DPRINTF(("SI_LISTEN\n"));
916		return si_listen(fp, fd, ioc, td);
917
918	case SVR4_SI_SETMYNAME:
919		DPRINTF(("SI_SETMYNAME\n"));
920		return 0;
921
922	case SVR4_SI_SETPEERNAME:
923		DPRINTF(("SI_SETPEERNAME\n"));
924		return 0;
925
926	case SVR4_SI_GETINTRANSIT:
927		DPRINTF(("SI_GETINTRANSIT\n"));
928		return 0;
929
930	case SVR4_SI_TCL_LINK:
931		DPRINTF(("SI_TCL_LINK\n"));
932		return 0;
933
934	case SVR4_SI_TCL_UNLINK:
935		DPRINTF(("SI_TCL_UNLINK\n"));
936		return 0;
937
938	case SVR4_SI_SOCKPARAMS:
939		DPRINTF(("SI_SOCKPARAMS\n"));
940		return si_sockparams(fp, fd, ioc, td);
941
942	case SVR4_SI_GETUDATA:
943		DPRINTF(("SI_GETUDATA\n"));
944		return si_getudata(fp, fd, ioc, td);
945
946	default:
947		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
948		return 0;
949
950	}
951}
952
953
954static int
955ti_getinfo(fp, fd, ioc, td)
956	struct file		*fp;
957	int 			 fd;
958	struct svr4_strioctl	*ioc;
959	struct thread		*td;
960{
961	int error;
962	struct svr4_infocmd info;
963
964	memset(&info, 0, sizeof(info));
965
966	if (ioc->len < 0 || ioc->len > sizeof(info))
967		return EINVAL;
968
969	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
970		return error;
971
972	if (info.cmd != SVR4_TI_INFO_REQUEST)
973		return EINVAL;
974
975	info.cmd = SVR4_TI_INFO_REPLY;
976	info.tsdu = 0;
977	info.etsdu = 1;
978	info.cdata = -2;
979	info.ddata = -2;
980	info.addr = 16;
981	info.opt = -1;
982	info.tidu = 16384;
983	info.serv = 2;
984	info.current = 0;
985	info.provider = 2;
986
987	ioc->len = sizeof(info);
988	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
989		return error;
990
991	return 0;
992}
993
994
995static int
996ti_bind(fp, fd, ioc, td)
997	struct file		*fp;
998	int 			 fd;
999	struct svr4_strioctl	*ioc;
1000	struct thread		*td;
1001{
1002	int error;
1003	struct svr4_strm *st = svr4_stream_get(fp);
1004	struct sockaddr_in sain;
1005	struct sockaddr_un saun;
1006	caddr_t sg;
1007	void *skp, *sup = NULL;
1008	int sasize;
1009	struct svr4_strmcmd bnd;
1010	struct bind_args ba;
1011
1012	if (st == NULL) {
1013		DPRINTF(("ti_bind: bad file descriptor\n"));
1014		return EINVAL;
1015	}
1016
1017	if (ioc->len < 0 || ioc->len > sizeof(bnd))
1018		return EINVAL;
1019
1020	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
1021		return error;
1022
1023	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
1024		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
1025		return EINVAL;
1026	}
1027
1028	switch (st->s_family) {
1029	case AF_INET:
1030		skp = &sain;
1031		sasize = sizeof(sain);
1032
1033		if (bnd.offs == 0)
1034			goto reply;
1035
1036		netaddr_to_sockaddr_in(&sain, &bnd);
1037
1038		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
1039			 sain.sin_family, sain.sin_port,
1040			 sain.sin_addr.s_addr));
1041		break;
1042
1043	case AF_LOCAL:
1044		skp = &saun;
1045		sasize = sizeof(saun);
1046		if (bnd.offs == 0)
1047			goto reply;
1048
1049		netaddr_to_sockaddr_un(&saun, &bnd);
1050
1051		if (saun.sun_path[0] == '\0')
1052			goto reply;
1053
1054		DPRINTF(("TI_BIND: fam %d, path %s\n",
1055			 saun.sun_family, saun.sun_path));
1056
1057		if ((error = clean_pipe(td, saun.sun_path)) != 0)
1058			return error;
1059
1060		bnd.pad[28] = 0x00001000;	/* magic again */
1061		break;
1062
1063	default:
1064		DPRINTF(("TI_BIND: Unsupported address family %d\n",
1065			 st->s_family));
1066		return ENOSYS;
1067	}
1068
1069	sg = stackgap_init();
1070	sup = stackgap_alloc(&sg, sasize);
1071
1072	if ((error = copyout(skp, sup, sasize)) != 0)
1073		return error;
1074
1075	ba.s = fd;
1076	DPRINTF(("TI_BIND: fileno %d\n", fd));
1077	ba.name = (void *) sup;
1078	ba.namelen = sasize;
1079
1080	if ((error = bind(td, &ba)) != 0) {
1081		DPRINTF(("TI_BIND: bind failed %d\n", error));
1082		return error;
1083	}
1084
1085reply:
1086	if (sup == NULL) {
1087		memset(&bnd, 0, sizeof(bnd));
1088		bnd.len = sasize + 4;
1089		bnd.offs = 0x10;	/* XXX */
1090	}
1091
1092	bnd.cmd = SVR4_TI_BIND_REPLY;
1093
1094	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
1095		return error;
1096
1097	return 0;
1098}
1099
1100
1101static int
1102timod(fp, fd, ioc, td)
1103	struct file		*fp;
1104	int			 fd;
1105	struct svr4_strioctl	*ioc;
1106	struct thread		*td;
1107{
1108	switch (ioc->cmd) {
1109	case SVR4_TI_GETINFO:
1110		DPRINTF(("TI_GETINFO\n"));
1111		return ti_getinfo(fp, fd, ioc, td);
1112
1113	case SVR4_TI_OPTMGMT:
1114		DPRINTF(("TI_OPTMGMT\n"));
1115		return 0;
1116
1117	case SVR4_TI_BIND:
1118		DPRINTF(("TI_BIND\n"));
1119		return ti_bind(fp, fd, ioc, td);
1120
1121	case SVR4_TI_UNBIND:
1122		DPRINTF(("TI_UNBIND\n"));
1123		return 0;
1124
1125	default:
1126		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
1127		return 0;
1128	}
1129}
1130
1131
1132int
1133svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
1134	struct file *fp;
1135	struct thread *td;
1136	register_t *retval;
1137	int fd;
1138	u_long cmd;
1139	caddr_t dat;
1140{
1141	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
1142	struct svr4_strm *st = svr4_stream_get(fp);
1143	int error;
1144	void *skp, *sup;
1145	struct sockaddr_in sain;
1146	struct sockaddr_un saun;
1147	struct svr4_strmcmd sc;
1148	int sasize, oldsasize;
1149	caddr_t sg;
1150	int *lenp;
1151
1152	DPRINTF(("svr4_stream_ti_ioctl\n"));
1153
1154	if (st == NULL)
1155		return EINVAL;
1156
1157	sc.offs = 0x10;
1158
1159	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
1160		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
1161		return error;
1162	}
1163
1164	switch (st->s_family) {
1165	case AF_INET:
1166		skp = &sain;
1167		sasize = sizeof(sain);
1168		break;
1169
1170	case AF_LOCAL:
1171		skp = &saun;
1172		sasize = sizeof(saun);
1173		break;
1174
1175	default:
1176		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
1177			 st->s_family));
1178		return ENOSYS;
1179	}
1180
1181	sg = stackgap_init();
1182	sup = stackgap_alloc(&sg, sasize);
1183	lenp = stackgap_alloc(&sg, sizeof(*lenp));
1184
1185	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
1186		DPRINTF(("ti_ioctl: error copying out lenp\n"));
1187		return error;
1188	}
1189
1190	switch (cmd) {
1191	case SVR4_TI_GETMYNAME:
1192		DPRINTF(("TI_GETMYNAME\n"));
1193		{
1194			struct getsockname_args ap;
1195			ap.fdes = fd;
1196			ap.asa = sup;
1197			ap.alen = lenp;
1198			if ((error = getsockname(td, &ap)) != 0) {
1199				DPRINTF(("ti_ioctl: getsockname error\n"));
1200				return error;
1201			}
1202		}
1203		break;
1204
1205	case SVR4_TI_GETPEERNAME:
1206		DPRINTF(("TI_GETPEERNAME\n"));
1207		{
1208			struct getpeername_args ap;
1209			ap.fdes = fd;
1210			ap.asa = sup;
1211			ap.alen = lenp;
1212			if ((error = getpeername(td, &ap)) != 0) {
1213				DPRINTF(("ti_ioctl: getpeername error\n"));
1214				return error;
1215			}
1216		}
1217		break;
1218
1219	case SVR4_TI_SETMYNAME:
1220		DPRINTF(("TI_SETMYNAME\n"));
1221		return 0;
1222
1223	case SVR4_TI_SETPEERNAME:
1224		DPRINTF(("TI_SETPEERNAME\n"));
1225		return 0;
1226	default:
1227		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
1228		return ENOSYS;
1229	}
1230
1231	if ((error = copyin(sup, skp, sasize)) != 0) {
1232		DPRINTF(("ti_ioctl: error copying in socket data\n"));
1233		return error;
1234	}
1235
1236	oldsasize = sasize;
1237
1238	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
1239		DPRINTF(("ti_ioctl: error copying in socket size\n"));
1240		return error;
1241	}
1242
1243	if (sasize < 0 || sasize > oldsasize)
1244		return EINVAL;
1245
1246	switch (st->s_family) {
1247	case AF_INET:
1248		sockaddr_to_netaddr_in(&sc, &sain);
1249		skb.len = sasize;
1250		break;
1251
1252	case AF_LOCAL:
1253		sockaddr_to_netaddr_un(&sc, &saun);
1254		skb.len = sasize + 4;
1255		break;
1256
1257	default:
1258		return ENOSYS;
1259	}
1260
1261
1262	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
1263		DPRINTF(("ti_ioctl: error copying out socket data\n"));
1264		return error;
1265	}
1266
1267
1268	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
1269		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
1270		return error;
1271	}
1272
1273	return error;
1274}
1275
1276
1277
1278
1279static int
1280i_nread(fp, td, retval, fd, cmd, dat)
1281	struct file *fp;
1282	struct thread *td;
1283	register_t *retval;
1284	int fd;
1285	u_long cmd;
1286	caddr_t dat;
1287{
1288	int error;
1289	int nread = 0;
1290
1291	/*
1292	 * We are supposed to return the message length in nread, and the
1293	 * number of messages in retval. We don't have the notion of number
1294	 * of stream messages, so we just find out if we have any bytes waiting
1295	 * for us, and if we do, then we assume that we have at least one
1296	 * message waiting for us.
1297	 */
1298	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred,
1299	    td)) != 0)
1300		return error;
1301
1302	if (nread != 0)
1303		*retval = 1;
1304	else
1305		*retval = 0;
1306
1307	return copyout(&nread, dat, sizeof(nread));
1308}
1309
1310static int
1311i_fdinsert(fp, td, retval, fd, cmd, dat)
1312	struct file *fp;
1313	struct thread *td;
1314	register_t *retval;
1315	int fd;
1316	u_long cmd;
1317	caddr_t dat;
1318{
1319	/*
1320	 * Major hack again here. We assume that we are using this to
1321	 * implement accept(2). If that is the case, we have already
1322	 * called accept, and we have stored the file descriptor in
1323	 * afd. We find the file descriptor that the code wants to use
1324	 * in fd insert, and then we dup2() our accepted file descriptor
1325	 * to it.
1326	 */
1327	int error;
1328	struct svr4_strm *st = svr4_stream_get(fp);
1329	struct svr4_strfdinsert fdi;
1330	struct dup2_args d2p;
1331	struct close_args clp;
1332
1333	if (st == NULL) {
1334		DPRINTF(("fdinsert: bad file type\n"));
1335		return EINVAL;
1336	}
1337
1338	if (st->s_afd == -1) {
1339		DPRINTF(("fdinsert: accept fd not found\n"));
1340		return ENOENT;
1341	}
1342
1343	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1344		DPRINTF(("fdinsert: copyin failed %d\n", error));
1345		return error;
1346	}
1347
1348	d2p.from = st->s_afd;
1349	d2p.to = fdi.fd;
1350
1351	if ((error = dup2(td, &d2p)) != 0) {
1352		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1353		    st->s_afd, fdi.fd, error));
1354		return error;
1355	}
1356
1357	clp.fd = st->s_afd;
1358
1359	if ((error = close(td, &clp)) != 0) {
1360		DPRINTF(("fdinsert: close(%d) failed %d\n",
1361		    st->s_afd, error));
1362		return error;
1363	}
1364
1365	st->s_afd = -1;
1366
1367	*retval = 0;
1368	return 0;
1369}
1370
1371
1372static int
1373_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
1374	struct file *fp;
1375	struct thread *td;
1376	register_t *retval;
1377	int fd;
1378	u_long cmd;
1379	caddr_t dat;
1380{
1381	struct mkfifo_args ap;
1382
1383	/*
1384	 * This is a supposed to be a kernel and library only ioctl.
1385	 * It gets called before ti_bind, when we have a unix
1386	 * socket, to physically create the socket transport and
1387	 * ``reserve'' it. I don't know how this get reserved inside
1388	 * the kernel, but we are going to create it nevertheless.
1389	 */
1390	ap.path = dat;
1391	ap.mode = S_IFIFO;
1392
1393	return mkfifo(td, &ap);
1394}
1395
1396static int
1397_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
1398	struct file *fp;
1399	struct thread *td;
1400	register_t *retval;
1401	int fd;
1402	u_long cmd;
1403	caddr_t dat;
1404{
1405	struct unlink_args ap;
1406
1407	/*
1408	 * This is a supposed to be a kernel and library only ioctl.
1409	 * I guess it is supposed to release the socket.
1410	 */
1411	ap.path = dat;
1412
1413	return unlink(td, &ap);
1414}
1415
1416static int
1417i_str(fp, td, retval, fd, cmd, dat)
1418	struct file *fp;
1419	struct thread *td;
1420	register_t *retval;
1421	int fd;
1422	u_long cmd;
1423	caddr_t dat;
1424{
1425	int			 error;
1426	struct svr4_strioctl	 ioc;
1427
1428	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1429		return error;
1430
1431#ifdef DEBUG_SVR4
1432	if ((error = show_ioc(">", &ioc)) != 0)
1433		return error;
1434#endif /* DEBUG_SVR4 */
1435
1436	switch (ioc.cmd & 0xff00) {
1437	case SVR4_SIMOD:
1438		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
1439			return error;
1440		break;
1441
1442	case SVR4_TIMOD:
1443		if ((error = timod(fp, fd, &ioc, td)) != 0)
1444			return error;
1445		break;
1446
1447	default:
1448		DPRINTF(("Unimplemented module %c %ld\n",
1449			 (char) (cmd >> 8), cmd & 0xff));
1450		return 0;
1451	}
1452
1453#ifdef DEBUG_SVR4
1454	if ((error = show_ioc("<", &ioc)) != 0)
1455		return error;
1456#endif /* DEBUG_SVR4 */
1457	return copyout(&ioc, dat, sizeof(ioc));
1458}
1459
1460static int
1461i_setsig(fp, td, retval, fd, cmd, dat)
1462	struct file *fp;
1463	struct thread *td;
1464	register_t *retval;
1465	int fd;
1466	u_long cmd;
1467	caddr_t dat;
1468{
1469	/*
1470	 * This is the best we can do for now; we cannot generate
1471	 * signals only for specific events so the signal mask gets
1472	 * ignored; we save it just to pass it to a possible I_GETSIG...
1473	 *
1474	 * We alse have to fix the O_ASYNC fcntl bit, so the
1475	 * process will get SIGPOLLs.
1476	 */
1477	int error;
1478	register_t oflags, flags;
1479	struct svr4_strm *st = svr4_stream_get(fp);
1480
1481	if (st == NULL) {
1482		DPRINTF(("i_setsig: bad file descriptor\n"));
1483		return EINVAL;
1484	}
1485	/* get old status flags */
1486	error = kern_fcntl(td, fd, F_GETFL, 0);
1487	if (error)
1488		return (error);
1489
1490	oflags = td->td_retval[0];
1491
1492	/* update the flags */
1493	if (dat != NULL) {
1494		int mask;
1495
1496		flags = oflags | O_ASYNC;
1497		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
1498			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
1499			  return error;
1500		}
1501		if (mask & SVR4_S_ALLMASK) {
1502			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
1503			  return EINVAL;
1504		}
1505		st->s_eventmask = mask;
1506	}
1507	else {
1508		flags = oflags & ~O_ASYNC;
1509		st->s_eventmask = 0;
1510	}
1511
1512	/* set the new flags, if changed */
1513	if (flags != oflags) {
1514		error = kern_fcntl(td, fd, F_SETFL, flags);
1515		if (error)
1516			return (error);
1517		flags = td->td_retval[0];
1518	}
1519
1520	/* set up SIGIO receiver if needed */
1521	if (dat != NULL)
1522		return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid));
1523	return 0;
1524}
1525
1526static int
1527i_getsig(fp, td, retval, fd, cmd, dat)
1528	struct file *fp;
1529	struct thread *td;
1530	register_t *retval;
1531	int fd;
1532	u_long cmd;
1533	caddr_t dat;
1534{
1535	int error;
1536
1537	if (dat != NULL) {
1538		struct svr4_strm *st = svr4_stream_get(fp);
1539
1540		if (st == NULL) {
1541			DPRINTF(("i_getsig: bad file descriptor\n"));
1542			return EINVAL;
1543		}
1544		if ((error = copyout(&st->s_eventmask, dat,
1545				     sizeof(st->s_eventmask))) != 0) {
1546			DPRINTF(("i_getsig: bad eventmask pointer\n"));
1547			return error;
1548		}
1549	}
1550	return 0;
1551}
1552
1553int
1554svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
1555	struct file *fp;
1556	struct thread *td;
1557	register_t *retval;
1558	int fd;
1559	u_long cmd;
1560	caddr_t dat;
1561{
1562	*retval = 0;
1563
1564	/*
1565	 * All the following stuff assumes "sockmod" is pushed...
1566	 */
1567	switch (cmd) {
1568	case SVR4_I_NREAD:
1569		DPRINTF(("I_NREAD\n"));
1570		return i_nread(fp, td, retval, fd, cmd, dat);
1571
1572	case SVR4_I_PUSH:
1573		DPRINTF(("I_PUSH %p\n", dat));
1574#if defined(DEBUG_SVR4)
1575		show_strbuf((struct svr4_strbuf *)dat);
1576#endif
1577		return 0;
1578
1579	case SVR4_I_POP:
1580		DPRINTF(("I_POP\n"));
1581		return 0;
1582
1583	case SVR4_I_LOOK:
1584		DPRINTF(("I_LOOK\n"));
1585		return 0;
1586
1587	case SVR4_I_FLUSH:
1588		DPRINTF(("I_FLUSH\n"));
1589		return 0;
1590
1591	case SVR4_I_SRDOPT:
1592		DPRINTF(("I_SRDOPT\n"));
1593		return 0;
1594
1595	case SVR4_I_GRDOPT:
1596		DPRINTF(("I_GRDOPT\n"));
1597		return 0;
1598
1599	case SVR4_I_STR:
1600		DPRINTF(("I_STR\n"));
1601		return i_str(fp, td, retval, fd, cmd, dat);
1602
1603	case SVR4_I_SETSIG:
1604		DPRINTF(("I_SETSIG\n"));
1605		return i_setsig(fp, td, retval, fd, cmd, dat);
1606
1607	case SVR4_I_GETSIG:
1608	        DPRINTF(("I_GETSIG\n"));
1609		return i_getsig(fp, td, retval, fd, cmd, dat);
1610
1611	case SVR4_I_FIND:
1612		DPRINTF(("I_FIND\n"));
1613		/*
1614		 * Here we are not pushing modules really, we just
1615		 * pretend all are present
1616		 */
1617		*retval = 0;
1618		return 0;
1619
1620	case SVR4_I_LINK:
1621		DPRINTF(("I_LINK\n"));
1622		return 0;
1623
1624	case SVR4_I_UNLINK:
1625		DPRINTF(("I_UNLINK\n"));
1626		return 0;
1627
1628	case SVR4_I_ERECVFD:
1629		DPRINTF(("I_ERECVFD\n"));
1630		return 0;
1631
1632	case SVR4_I_PEEK:
1633		DPRINTF(("I_PEEK\n"));
1634		return 0;
1635
1636	case SVR4_I_FDINSERT:
1637		DPRINTF(("I_FDINSERT\n"));
1638		return i_fdinsert(fp, td, retval, fd, cmd, dat);
1639
1640	case SVR4_I_SENDFD:
1641		DPRINTF(("I_SENDFD\n"));
1642		return 0;
1643
1644	case SVR4_I_RECVFD:
1645		DPRINTF(("I_RECVFD\n"));
1646		return 0;
1647
1648	case SVR4_I_SWROPT:
1649		DPRINTF(("I_SWROPT\n"));
1650		return 0;
1651
1652	case SVR4_I_GWROPT:
1653		DPRINTF(("I_GWROPT\n"));
1654		return 0;
1655
1656	case SVR4_I_LIST:
1657		DPRINTF(("I_LIST\n"));
1658		return 0;
1659
1660	case SVR4_I_PLINK:
1661		DPRINTF(("I_PLINK\n"));
1662		return 0;
1663
1664	case SVR4_I_PUNLINK:
1665		DPRINTF(("I_PUNLINK\n"));
1666		return 0;
1667
1668	case SVR4_I_SETEV:
1669		DPRINTF(("I_SETEV\n"));
1670		return 0;
1671
1672	case SVR4_I_GETEV:
1673		DPRINTF(("I_GETEV\n"));
1674		return 0;
1675
1676	case SVR4_I_STREV:
1677		DPRINTF(("I_STREV\n"));
1678		return 0;
1679
1680	case SVR4_I_UNSTREV:
1681		DPRINTF(("I_UNSTREV\n"));
1682		return 0;
1683
1684	case SVR4_I_FLUSHBAND:
1685		DPRINTF(("I_FLUSHBAND\n"));
1686		return 0;
1687
1688	case SVR4_I_CKBAND:
1689		DPRINTF(("I_CKBAND\n"));
1690		return 0;
1691
1692	case SVR4_I_GETBAND:
1693		DPRINTF(("I_GETBANK\n"));
1694		return 0;
1695
1696	case SVR4_I_ATMARK:
1697		DPRINTF(("I_ATMARK\n"));
1698		return 0;
1699
1700	case SVR4_I_SETCLTIME:
1701		DPRINTF(("I_SETCLTIME\n"));
1702		return 0;
1703
1704	case SVR4_I_GETCLTIME:
1705		DPRINTF(("I_GETCLTIME\n"));
1706		return 0;
1707
1708	case SVR4_I_CANPUT:
1709		DPRINTF(("I_CANPUT\n"));
1710		return 0;
1711
1712	case SVR4__I_BIND_RSVD:
1713		DPRINTF(("_I_BIND_RSVD\n"));
1714		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
1715
1716	case SVR4__I_RELE_RSVD:
1717		DPRINTF(("_I_RELE_RSVD\n"));
1718		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
1719
1720	default:
1721		DPRINTF(("unimpl cmd = %lx\n", cmd));
1722		break;
1723	}
1724
1725	return 0;
1726}
1727
1728
1729
1730int
1731svr4_sys_putmsg(td, uap)
1732	register struct thread *td;
1733	struct svr4_sys_putmsg_args *uap;
1734{
1735	struct file     *fp;
1736	int error;
1737
1738	if ((error = fget(td, uap->fd, &fp)) != 0) {
1739#ifdef DEBUG_SVR4
1740	        uprintf("putmsg: bad fp\n");
1741#endif
1742		return EBADF;
1743	}
1744	error = svr4_do_putmsg(td, uap, fp);
1745	fdrop(fp, td);
1746	return (error);
1747}
1748
1749static int
1750svr4_do_putmsg(td, uap, fp)
1751	struct thread *td;
1752	struct svr4_sys_putmsg_args *uap;
1753	struct file	*fp;
1754{
1755	struct svr4_strbuf dat, ctl;
1756	struct svr4_strmcmd sc;
1757	struct sockaddr_in sain;
1758	struct sockaddr_un saun;
1759	void *skp, *sup;
1760	int sasize, *retval;
1761	struct svr4_strm *st;
1762	int error;
1763	caddr_t sg;
1764
1765	retval = td->td_retval;
1766
1767#ifdef DEBUG_SVR4
1768	show_msg(">putmsg", uap->fd, uap->ctl,
1769		 uap->dat, uap->flags);
1770#endif /* DEBUG_SVR4 */
1771
1772	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1773
1774	if (uap->ctl != NULL) {
1775	  if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) {
1776#ifdef DEBUG_SVR4
1777	    uprintf("putmsg: copyin(): %d\n", error);
1778#endif
1779	    return error;
1780	  }
1781	}
1782	else
1783		ctl.len = -1;
1784
1785	if (uap->dat != NULL) {
1786	  if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) {
1787#ifdef DEBUG_SVR4
1788	    uprintf("putmsg: copyin(): %d (2)\n", error);
1789#endif
1790	    return error;
1791	  }
1792	}
1793	else
1794		dat.len = -1;
1795
1796	/*
1797	 * Only for sockets for now.
1798	 */
1799	if ((st = svr4_stream_get(fp)) == NULL) {
1800		DPRINTF(("putmsg: bad file type\n"));
1801		return EINVAL;
1802	}
1803
1804	if (ctl.len < 0 || ctl.len > sizeof(sc)) {
1805		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
1806			 sizeof(struct svr4_strmcmd)));
1807		return EINVAL;
1808	}
1809
1810	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1811		return error;
1812
1813	switch (st->s_family) {
1814	case AF_INET:
1815	        if (sc.len != sizeof(sain)) {
1816		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
1817			        struct write_args wa;
1818
1819				/* Solaris seems to use sc.cmd = 3 to
1820				 * send "expedited" data.  telnet uses
1821				 * this for options processing, sending EOF,
1822				 * etc.  I'm sure other things use it too.
1823				 * I don't have any documentation
1824				 * on it, so I'm making a guess that this
1825				 * is how it works. newton@atdot.dotat.org XXX
1826				 */
1827				DPRINTF(("sending expedited data ??\n"));
1828				wa.fd = uap->fd;
1829				wa.buf = dat.buf;
1830				wa.nbyte = dat.len;
1831				return write(td, &wa);
1832			}
1833	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1834	                return EINVAL;
1835	        }
1836	        netaddr_to_sockaddr_in(&sain, &sc);
1837	        skp = &sain;
1838	        sasize = sizeof(sain);
1839	        error = sain.sin_family != st->s_family;
1840		break;
1841
1842	case AF_LOCAL:
1843		if (ctl.len == 8) {
1844			/* We are doing an accept; succeed */
1845			DPRINTF(("putmsg: Do nothing\n"));
1846			*retval = 0;
1847			return 0;
1848		}
1849		else {
1850			/* Maybe we've been given a device/inode pair */
1851			dev_t *dev = SVR4_ADDROF(&sc);
1852			ino_t *ino = (ino_t *) &dev[1];
1853			skp = svr4_find_socket(td, fp, *dev, *ino);
1854			if (skp == NULL) {
1855				skp = &saun;
1856				/* I guess we have it by name */
1857				netaddr_to_sockaddr_un(skp, &sc);
1858			}
1859			sasize = sizeof(saun);
1860		}
1861		break;
1862
1863	default:
1864		DPRINTF(("putmsg: Unsupported address family %d\n",
1865			 st->s_family));
1866		return ENOSYS;
1867	}
1868
1869	sg = stackgap_init();
1870	sup = stackgap_alloc(&sg, sasize);
1871
1872	if ((error = copyout(skp, sup, sasize)) != 0)
1873		return error;
1874
1875	switch (st->s_cmd = sc.cmd) {
1876	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
1877		{
1878			struct connect_args co;
1879
1880			co.s = uap->fd;
1881			co.name = (void *) sup;
1882			co.namelen = (int) sasize;
1883
1884			return connect(td, &co);
1885		}
1886
1887	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
1888		{
1889			struct msghdr msg;
1890			struct iovec aiov;
1891
1892			msg.msg_name = (caddr_t) sup;
1893			msg.msg_namelen = sasize;
1894			msg.msg_iov = &aiov;
1895			msg.msg_iovlen = 1;
1896			msg.msg_control = 0;
1897			msg.msg_flags = 0;
1898			aiov.iov_base = dat.buf;
1899			aiov.iov_len = dat.len;
1900#if 0
1901			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
1902					      uio, 0, 0, 0, uio->uio_td);
1903#endif
1904			error = svr4_sendit(td, uap->fd, &msg,
1905				       uap->flags);
1906			DPRINTF(("sendto_request error: %d\n", error));
1907			*retval = 0;
1908			return error;
1909		}
1910
1911	default:
1912		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1913		return ENOSYS;
1914	}
1915}
1916
1917int
1918svr4_sys_getmsg(td, uap)
1919	struct thread *td;
1920	struct svr4_sys_getmsg_args *uap;
1921{
1922	struct file     *fp;
1923	int error;
1924
1925	if ((error = fget(td, uap->fd, &fp)) != 0) {
1926#ifdef DEBUG_SVR4
1927	        uprintf("getmsg: bad fp\n");
1928#endif
1929		return EBADF;
1930	}
1931	error = svr4_do_getmsg(td, uap, fp);
1932	fdrop(fp, td);
1933	return (error);
1934}
1935
1936int
1937svr4_do_getmsg(td, uap, fp)
1938	register struct thread *td;
1939	struct svr4_sys_getmsg_args *uap;
1940	struct file *fp;
1941{
1942	struct getpeername_args ga;
1943	struct accept_args aa;
1944	struct svr4_strbuf dat, ctl;
1945	struct svr4_strmcmd sc;
1946	int error, *retval;
1947	struct msghdr msg;
1948	struct iovec aiov;
1949	struct sockaddr_in sain;
1950	struct sockaddr_un saun;
1951	void *skp, *sup;
1952	int sasize;
1953	struct svr4_strm *st;
1954	int *flen;
1955	int fl;
1956	caddr_t sg;
1957
1958	retval = td->td_retval;
1959
1960	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1961
1962	memset(&sc, 0, sizeof(sc));
1963
1964#ifdef DEBUG_SVR4
1965	show_msg(">getmsg", uap->fd, uap->ctl,
1966		 uap->dat, 0);
1967#endif /* DEBUG_SVR4 */
1968
1969	if (uap->ctl != NULL) {
1970		if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
1971			return error;
1972		if (ctl.len < 0)
1973			return EINVAL;
1974	}
1975	else {
1976		ctl.len = -1;
1977		ctl.maxlen = 0;
1978	}
1979
1980	if (uap->dat != NULL) {
1981	    	if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0)
1982			return error;
1983	}
1984	else {
1985		dat.len = -1;
1986		dat.maxlen = 0;
1987	}
1988
1989	/*
1990	 * Only for sockets for now.
1991	 */
1992	if ((st = svr4_stream_get(fp)) == NULL) {
1993		DPRINTF(("getmsg: bad file type\n"));
1994		return EINVAL;
1995	}
1996
1997	if (ctl.maxlen == -1 || dat.maxlen == -1) {
1998		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1999		return ENOSYS;
2000	}
2001
2002	switch (st->s_family) {
2003	case AF_INET:
2004		skp = &sain;
2005		sasize = sizeof(sain);
2006		break;
2007
2008	case AF_LOCAL:
2009		skp = &saun;
2010		sasize = sizeof(saun);
2011		break;
2012
2013	default:
2014		DPRINTF(("getmsg: Unsupported address family %d\n",
2015			 st->s_family));
2016		return ENOSYS;
2017	}
2018
2019	sg = stackgap_init();
2020	sup = stackgap_alloc(&sg, sasize);
2021	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
2022
2023	fl = sasize;
2024	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
2025		return error;
2026
2027	switch (st->s_cmd) {
2028	case SVR4_TI_CONNECT_REQUEST:
2029		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
2030		/*
2031		 * We do the connect in one step, so the putmsg should
2032		 * have gotten the error.
2033		 */
2034		sc.cmd = SVR4_TI_OK_REPLY;
2035		sc.len = 0;
2036
2037		ctl.len = 8;
2038		dat.len = -1;
2039		fl = 1;
2040		st->s_cmd = sc.cmd;
2041		break;
2042
2043	case SVR4_TI_OK_REPLY:
2044		DPRINTF(("getmsg: TI_OK_REPLY\n"));
2045		/*
2046		 * We are immediately after a connect reply, so we send
2047		 * a connect verification.
2048		 */
2049
2050		ga.fdes = uap->fd;
2051		ga.asa = (void *) sup;
2052		ga.alen = flen;
2053
2054		if ((error = getpeername(td, &ga)) != 0) {
2055			DPRINTF(("getmsg: getpeername failed %d\n", error));
2056			return error;
2057		}
2058
2059		if ((error = copyin(sup, skp, sasize)) != 0)
2060			return error;
2061
2062		sc.cmd = SVR4_TI_CONNECT_REPLY;
2063		sc.pad[0] = 0x4;
2064		sc.offs = 0x18;
2065		sc.pad[1] = 0x14;
2066		sc.pad[2] = 0x04000402;
2067
2068		switch (st->s_family) {
2069		case AF_INET:
2070			sc.len = sasize;
2071			sockaddr_to_netaddr_in(&sc, &sain);
2072			break;
2073
2074		case AF_LOCAL:
2075			sc.len = sasize + 4;
2076			sockaddr_to_netaddr_un(&sc, &saun);
2077			break;
2078
2079		default:
2080			return ENOSYS;
2081		}
2082
2083		ctl.len = 40;
2084		dat.len = -1;
2085		fl = 0;
2086		st->s_cmd = sc.cmd;
2087		break;
2088
2089	case SVR4_TI__ACCEPT_OK:
2090		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
2091		/*
2092		 * We do the connect in one step, so the putmsg should
2093		 * have gotten the error.
2094		 */
2095		sc.cmd = SVR4_TI_OK_REPLY;
2096		sc.len = 1;
2097
2098		ctl.len = 8;
2099		dat.len = -1;
2100		fl = 1;
2101		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
2102		break;
2103
2104	case SVR4_TI__ACCEPT_WAIT:
2105		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
2106		/*
2107		 * We are after a listen, so we try to accept...
2108		 */
2109		aa.s = uap->fd;
2110		aa.name = (void *) sup;
2111		aa.anamelen = flen;
2112
2113		if ((error = accept(td, &aa)) != 0) {
2114			DPRINTF(("getmsg: accept failed %d\n", error));
2115			return error;
2116		}
2117
2118		st->s_afd = *retval;
2119
2120		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
2121
2122		if ((error = copyin(sup, skp, sasize)) != 0)
2123			return error;
2124
2125		sc.cmd = SVR4_TI_ACCEPT_REPLY;
2126		sc.offs = 0x18;
2127		sc.pad[0] = 0x0;
2128
2129		switch (st->s_family) {
2130		case AF_INET:
2131			sc.pad[1] = 0x28;
2132			sockaddr_to_netaddr_in(&sc, &sain);
2133			ctl.len = 40;
2134			sc.len = sasize;
2135			break;
2136
2137		case AF_LOCAL:
2138			sc.pad[1] = 0x00010000;
2139			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
2140			sc.pad[3] = 0x00010000;
2141			ctl.len = 134;
2142			sc.len = sasize + 4;
2143			break;
2144
2145		default:
2146			return ENOSYS;
2147		}
2148
2149		dat.len = -1;
2150		fl = 0;
2151		st->s_cmd = SVR4_TI__ACCEPT_OK;
2152		break;
2153
2154	case SVR4_TI_SENDTO_REQUEST:
2155		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
2156		if (ctl.maxlen > 36 && ctl.len < 36)
2157		    ctl.len = 36;
2158
2159		if (ctl.len > sizeof(sc))
2160			ctl.len = sizeof(sc);
2161
2162		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
2163			return error;
2164
2165		switch (st->s_family) {
2166		case AF_INET:
2167			sockaddr_to_netaddr_in(&sc, &sain);
2168			break;
2169
2170		case AF_LOCAL:
2171			sockaddr_to_netaddr_un(&sc, &saun);
2172			break;
2173
2174		default:
2175			return ENOSYS;
2176		}
2177
2178		msg.msg_name = (caddr_t) sup;
2179		msg.msg_namelen = sasize;
2180		msg.msg_iov = &aiov;
2181		msg.msg_iovlen = 1;
2182		msg.msg_control = 0;
2183		aiov.iov_base = dat.buf;
2184		aiov.iov_len = dat.maxlen;
2185		msg.msg_flags = 0;
2186
2187		error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen);
2188
2189		if (error) {
2190			DPRINTF(("getmsg: recvit failed %d\n", error));
2191			return error;
2192		}
2193
2194		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
2195			return error;
2196
2197		sc.cmd = SVR4_TI_RECVFROM_IND;
2198
2199		switch (st->s_family) {
2200		case AF_INET:
2201			sc.len = sasize;
2202			sockaddr_to_netaddr_in(&sc, &sain);
2203			break;
2204
2205		case AF_LOCAL:
2206			sc.len = sasize + 4;
2207			sockaddr_to_netaddr_un(&sc, &saun);
2208			break;
2209
2210		default:
2211			return ENOSYS;
2212		}
2213
2214		dat.len = *retval;
2215		fl = 0;
2216		st->s_cmd = sc.cmd;
2217		break;
2218
2219	default:
2220		st->s_cmd = sc.cmd;
2221		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
2222		        struct read_args ra;
2223
2224			/* More weirdness:  Again, I can't find documentation
2225			 * to back this up, but when a process does a generic
2226			 * "getmsg()" call it seems that the command field is
2227			 * zero and the length of the data area is zero.  I
2228			 * think processes expect getmsg() to fill in dat.len
2229			 * after reading at most dat.maxlen octets from the
2230			 * stream.  Since we're using sockets I can let
2231			 * read() look after it and frob return values
2232			 * appropriately (or inappropriately :-)
2233			 *   -- newton@atdot.dotat.org        XXX
2234			 */
2235			ra.fd = uap->fd;
2236			ra.buf = dat.buf;
2237			ra.nbyte = dat.maxlen;
2238			if ((error = read(td, &ra)) != 0) {
2239			        return error;
2240			}
2241			dat.len = *retval;
2242			*retval = 0;
2243			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
2244			break;
2245		}
2246		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
2247		return EINVAL;
2248	}
2249
2250	if (uap->ctl) {
2251		if (ctl.len != -1)
2252			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
2253				return error;
2254
2255		if ((error = copyout(&ctl, uap->ctl, sizeof(ctl))) != 0)
2256			return error;
2257	}
2258
2259	if (uap->dat) {
2260		if ((error = copyout(&dat, uap->dat, sizeof(dat))) != 0)
2261			return error;
2262	}
2263
2264	if (uap->flags) { /* XXX: Need translation */
2265		if ((error = copyout(&fl, uap->flags, sizeof(fl))) != 0)
2266			return error;
2267	}
2268
2269	*retval = 0;
2270
2271#ifdef DEBUG_SVR4
2272	show_msg("<getmsg", uap->fd, uap->ctl,
2273		 uap->dat, fl);
2274#endif /* DEBUG_SVR4 */
2275	return error;
2276}
2277
2278int svr4_sys_send(td, uap)
2279	struct thread *td;
2280	struct svr4_sys_send_args *uap;
2281{
2282	struct osend_args osa;
2283	osa.s = uap->s;
2284	osa.buf = uap->buf;
2285	osa.len = uap->len;
2286	osa.flags = uap->flags;
2287	return osend(td, &osa);
2288}
2289
2290int svr4_sys_recv(td, uap)
2291	struct thread *td;
2292	struct svr4_sys_recv_args *uap;
2293{
2294	struct orecv_args ora;
2295	ora.s = uap->s;
2296	ora.buf = uap->buf;
2297	ora.len = uap->len;
2298	ora.flags = uap->flags;
2299	return orecv(td, &ora);
2300}
2301
2302/*
2303 * XXX This isn't necessary, but it's handy for inserting debug code into
2304 * sendto().  Let's leave it here for now...
2305 */
2306int
2307svr4_sys_sendto(td, uap)
2308        struct thread *td;
2309        struct svr4_sys_sendto_args *uap;
2310{
2311        struct sendto_args sa;
2312
2313	sa.s = uap->s;
2314	sa.buf = uap->buf;
2315	sa.len = uap->len;
2316	sa.flags = uap->flags;
2317	sa.to = (caddr_t)uap->to;
2318	sa.tolen = uap->tolen;
2319
2320	DPRINTF(("calling sendto()\n"));
2321	return sendto(td, &sa);
2322}
2323
2324