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