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