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