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