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