svr4_stream.c revision 51418
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 51418 1999-09-19 17:00:25Z green $
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 = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, p)) != 0)
1259		return error;
1260
1261	if (nread != 0)
1262		*retval = 1;
1263	else
1264		*retval = 0;
1265
1266	return copyout(&nread, dat, sizeof(nread));
1267}
1268
1269static int
1270i_fdinsert(fp, p, retval, fd, cmd, dat)
1271	struct file *fp;
1272	struct proc *p;
1273	register_t *retval;
1274	int fd;
1275	u_long cmd;
1276	caddr_t dat;
1277{
1278	/*
1279	 * Major hack again here. We assume that we are using this to
1280	 * implement accept(2). If that is the case, we have already
1281	 * called accept, and we have stored the file descriptor in
1282	 * afd. We find the file descriptor that the code wants to use
1283	 * in fd insert, and then we dup2() our accepted file descriptor
1284	 * to it.
1285	 */
1286	int error;
1287	struct svr4_strm *st = svr4_stream_get(fp);
1288	struct svr4_strfdinsert fdi;
1289	struct dup2_args d2p;
1290	struct close_args clp;
1291
1292	if (st == NULL) {
1293		DPRINTF(("fdinsert: bad file type\n"));
1294		return EINVAL;
1295	}
1296
1297	if (st->s_afd == -1) {
1298		DPRINTF(("fdinsert: accept fd not found\n"));
1299		return ENOENT;
1300	}
1301
1302	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1303		DPRINTF(("fdinsert: copyin failed %d\n", error));
1304		return error;
1305	}
1306
1307	SCARG(&d2p, from) = st->s_afd;
1308	SCARG(&d2p, to) = fdi.fd;
1309
1310	if ((error = dup2(p, &d2p)) != 0) {
1311		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1312		    st->s_afd, fdi.fd, error));
1313		return error;
1314	}
1315
1316	SCARG(&clp, fd) = st->s_afd;
1317
1318	if ((error = close(p, &clp)) != 0) {
1319		DPRINTF(("fdinsert: close(%d) failed %d\n",
1320		    st->s_afd, error));
1321		return error;
1322	}
1323
1324	st->s_afd = -1;
1325
1326	*retval = 0;
1327	return 0;
1328}
1329
1330
1331static int
1332_i_bind_rsvd(fp, p, retval, fd, cmd, dat)
1333	struct file *fp;
1334	struct proc *p;
1335	register_t *retval;
1336	int fd;
1337	u_long cmd;
1338	caddr_t dat;
1339{
1340	struct mkfifo_args ap;
1341
1342	/*
1343	 * This is a supposed to be a kernel and library only ioctl.
1344	 * It gets called before ti_bind, when we have a unix
1345	 * socket, to physically create the socket transport and
1346	 * ``reserve'' it. I don't know how this get reserved inside
1347	 * the kernel, but we are going to create it nevertheless.
1348	 */
1349	SCARG(&ap, path) = dat;
1350	SCARG(&ap, mode) = S_IFIFO;
1351
1352	return mkfifo(p, &ap);
1353}
1354
1355static int
1356_i_rele_rsvd(fp, p, retval, fd, cmd, dat)
1357	struct file *fp;
1358	struct proc *p;
1359	register_t *retval;
1360	int fd;
1361	u_long cmd;
1362	caddr_t dat;
1363{
1364	struct unlink_args ap;
1365
1366	/*
1367	 * This is a supposed to be a kernel and library only ioctl.
1368	 * I guess it is supposed to release the socket.
1369	 */
1370	SCARG(&ap, path) = dat;
1371
1372	return unlink(p, &ap);
1373}
1374
1375static int
1376i_str(fp, p, retval, fd, cmd, dat)
1377	struct file *fp;
1378	struct proc *p;
1379	register_t *retval;
1380	int fd;
1381	u_long cmd;
1382	caddr_t dat;
1383{
1384	int			 error;
1385	struct svr4_strioctl	 ioc;
1386
1387	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1388		return error;
1389
1390#ifdef DEBUG_SVR4
1391	if ((error = show_ioc(">", &ioc)) != 0)
1392		return error;
1393#endif /* DEBUG_SVR4 */
1394
1395	switch (ioc.cmd & 0xff00) {
1396	case SVR4_SIMOD:
1397		if ((error = sockmod(fp, fd, &ioc, p)) != 0)
1398			return error;
1399		break;
1400
1401	case SVR4_TIMOD:
1402		if ((error = timod(fp, fd, &ioc, p)) != 0)
1403			return error;
1404		break;
1405
1406	default:
1407		DPRINTF(("Unimplemented module %c %ld\n",
1408			 (char) (cmd >> 8), cmd & 0xff));
1409		return 0;
1410	}
1411
1412#ifdef DEBUG_SVR4
1413	if ((error = show_ioc("<", &ioc)) != 0)
1414		return error;
1415#endif /* DEBUG_SVR4 */
1416	return copyout(&ioc, dat, sizeof(ioc));
1417}
1418
1419static int
1420i_setsig(fp, p, retval, fd, cmd, dat)
1421	struct file *fp;
1422	struct proc *p;
1423	register_t *retval;
1424	int fd;
1425	u_long cmd;
1426	caddr_t dat;
1427{
1428	/*
1429	 * This is the best we can do for now; we cannot generate
1430	 * signals only for specific events so the signal mask gets
1431	 * ignored; we save it just to pass it to a possible I_GETSIG...
1432	 *
1433	 * We alse have to fix the O_ASYNC fcntl bit, so the
1434	 * process will get SIGPOLLs.
1435	 */
1436	struct fcntl_args fa;
1437	int error;
1438	register_t oflags, flags;
1439	struct svr4_strm *st = svr4_stream_get(fp);
1440
1441	if (st == NULL) {
1442		DPRINTF(("i_setsig: bad file descriptor\n"));
1443		return EINVAL;
1444	}
1445	/* get old status flags */
1446	SCARG(&fa, fd) = fd;
1447	SCARG(&fa, cmd) = F_GETFL;
1448	if ((error = fcntl(p, &fa)) != 0)
1449		return error;
1450
1451	oflags = p->p_retval[0];
1452
1453	/* update the flags */
1454	if (dat != NULL) {
1455		int mask;
1456
1457		flags = oflags | O_ASYNC;
1458		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
1459			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
1460			  return error;
1461		}
1462		if (mask & SVR4_S_ALLMASK) {
1463			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
1464			  return EINVAL;
1465		}
1466		st->s_eventmask = mask;
1467	}
1468	else {
1469		flags = oflags & ~O_ASYNC;
1470		st->s_eventmask = 0;
1471	}
1472
1473	/* set the new flags, if changed */
1474	if (flags != oflags) {
1475		SCARG(&fa, cmd) = F_SETFL;
1476		SCARG(&fa, arg) = (long) flags;
1477		if ((error = fcntl(p, &fa)) != 0)
1478			  return error;
1479		flags = p->p_retval[0];
1480	}
1481
1482	/* set up SIGIO receiver if needed */
1483	if (dat != NULL) {
1484		SCARG(&fa, cmd) = F_SETOWN;
1485		SCARG(&fa, arg) = (long) p->p_pid;
1486		return fcntl(p, &fa);
1487	}
1488	return 0;
1489}
1490
1491static int
1492i_getsig(fp, p, retval, fd, cmd, dat)
1493	struct file *fp;
1494	struct proc *p;
1495	register_t *retval;
1496	int fd;
1497	u_long cmd;
1498	caddr_t dat;
1499{
1500	int error;
1501
1502	if (dat != NULL) {
1503		struct svr4_strm *st = svr4_stream_get(fp);
1504
1505		if (st == NULL) {
1506			DPRINTF(("i_getsig: bad file descriptor\n"));
1507			return EINVAL;
1508		}
1509		if ((error = copyout(&st->s_eventmask, dat,
1510				     sizeof(st->s_eventmask))) != 0) {
1511			DPRINTF(("i_getsig: bad eventmask pointer\n"));
1512			return error;
1513		}
1514	}
1515	return 0;
1516}
1517
1518int
1519svr4_stream_ioctl(fp, p, retval, fd, cmd, dat)
1520	struct file *fp;
1521	struct proc *p;
1522	register_t *retval;
1523	int fd;
1524	u_long cmd;
1525	caddr_t dat;
1526{
1527	*retval = 0;
1528
1529	/*
1530	 * All the following stuff assumes "sockmod" is pushed...
1531	 */
1532	switch (cmd) {
1533	case SVR4_I_NREAD:
1534		DPRINTF(("I_NREAD\n"));
1535		return i_nread(fp, p, retval, fd, cmd, dat);
1536
1537	case SVR4_I_PUSH:
1538		DPRINTF(("I_PUSH %x\n", dat));
1539#if defined(DEBUG_SVR4)
1540		show_strbuf(dat);
1541#endif
1542		return 0;
1543
1544	case SVR4_I_POP:
1545		DPRINTF(("I_POP\n"));
1546		return 0;
1547
1548	case SVR4_I_LOOK:
1549		DPRINTF(("I_LOOK\n"));
1550		return 0;
1551
1552	case SVR4_I_FLUSH:
1553		DPRINTF(("I_FLUSH\n"));
1554		return 0;
1555
1556	case SVR4_I_SRDOPT:
1557		DPRINTF(("I_SRDOPT\n"));
1558		return 0;
1559
1560	case SVR4_I_GRDOPT:
1561		DPRINTF(("I_GRDOPT\n"));
1562		return 0;
1563
1564	case SVR4_I_STR:
1565		DPRINTF(("I_STR\n"));
1566		return i_str(fp, p, retval, fd, cmd, dat);
1567
1568	case SVR4_I_SETSIG:
1569		DPRINTF(("I_SETSIG\n"));
1570		return i_setsig(fp, p, retval, fd, cmd, dat);
1571
1572	case SVR4_I_GETSIG:
1573	        DPRINTF(("I_GETSIG\n"));
1574		return i_getsig(fp, p, retval, fd, cmd, dat);
1575
1576	case SVR4_I_FIND:
1577		DPRINTF(("I_FIND\n"));
1578		/*
1579		 * Here we are not pushing modules really, we just
1580		 * pretend all are present
1581		 */
1582		*retval = 0;
1583		return 0;
1584
1585	case SVR4_I_LINK:
1586		DPRINTF(("I_LINK\n"));
1587		return 0;
1588
1589	case SVR4_I_UNLINK:
1590		DPRINTF(("I_UNLINK\n"));
1591		return 0;
1592
1593	case SVR4_I_ERECVFD:
1594		DPRINTF(("I_ERECVFD\n"));
1595		return 0;
1596
1597	case SVR4_I_PEEK:
1598		DPRINTF(("I_PEEK\n"));
1599		return 0;
1600
1601	case SVR4_I_FDINSERT:
1602		DPRINTF(("I_FDINSERT\n"));
1603		return i_fdinsert(fp, p, retval, fd, cmd, dat);
1604
1605	case SVR4_I_SENDFD:
1606		DPRINTF(("I_SENDFD\n"));
1607		return 0;
1608
1609	case SVR4_I_RECVFD:
1610		DPRINTF(("I_RECVFD\n"));
1611		return 0;
1612
1613	case SVR4_I_SWROPT:
1614		DPRINTF(("I_SWROPT\n"));
1615		return 0;
1616
1617	case SVR4_I_GWROPT:
1618		DPRINTF(("I_GWROPT\n"));
1619		return 0;
1620
1621	case SVR4_I_LIST:
1622		DPRINTF(("I_LIST\n"));
1623		return 0;
1624
1625	case SVR4_I_PLINK:
1626		DPRINTF(("I_PLINK\n"));
1627		return 0;
1628
1629	case SVR4_I_PUNLINK:
1630		DPRINTF(("I_PUNLINK\n"));
1631		return 0;
1632
1633	case SVR4_I_SETEV:
1634		DPRINTF(("I_SETEV\n"));
1635		return 0;
1636
1637	case SVR4_I_GETEV:
1638		DPRINTF(("I_GETEV\n"));
1639		return 0;
1640
1641	case SVR4_I_STREV:
1642		DPRINTF(("I_STREV\n"));
1643		return 0;
1644
1645	case SVR4_I_UNSTREV:
1646		DPRINTF(("I_UNSTREV\n"));
1647		return 0;
1648
1649	case SVR4_I_FLUSHBAND:
1650		DPRINTF(("I_FLUSHBAND\n"));
1651		return 0;
1652
1653	case SVR4_I_CKBAND:
1654		DPRINTF(("I_CKBAND\n"));
1655		return 0;
1656
1657	case SVR4_I_GETBAND:
1658		DPRINTF(("I_GETBANK\n"));
1659		return 0;
1660
1661	case SVR4_I_ATMARK:
1662		DPRINTF(("I_ATMARK\n"));
1663		return 0;
1664
1665	case SVR4_I_SETCLTIME:
1666		DPRINTF(("I_SETCLTIME\n"));
1667		return 0;
1668
1669	case SVR4_I_GETCLTIME:
1670		DPRINTF(("I_GETCLTIME\n"));
1671		return 0;
1672
1673	case SVR4_I_CANPUT:
1674		DPRINTF(("I_CANPUT\n"));
1675		return 0;
1676
1677	case SVR4__I_BIND_RSVD:
1678		DPRINTF(("_I_BIND_RSVD\n"));
1679		return _i_bind_rsvd(fp, p, retval, fd, cmd, dat);
1680
1681	case SVR4__I_RELE_RSVD:
1682		DPRINTF(("_I_RELE_RSVD\n"));
1683		return _i_rele_rsvd(fp, p, retval, fd, cmd, dat);
1684
1685	default:
1686		DPRINTF(("unimpl cmd = %lx\n", cmd));
1687		break;
1688	}
1689
1690	return 0;
1691}
1692
1693
1694
1695int
1696svr4_sys_putmsg(p, uap)
1697	register struct proc *p;
1698	struct svr4_sys_putmsg_args *uap;
1699{
1700	struct filedesc	*fdp = p->p_fd;
1701	struct file	*fp;
1702	struct svr4_strbuf dat, ctl;
1703	struct svr4_strmcmd sc;
1704	struct sockaddr_in sain;
1705	struct sockaddr_un saun;
1706	void *skp, *sup;
1707	int sasize, *retval;
1708	struct svr4_strm *st;
1709	int error;
1710	caddr_t sg;
1711
1712	retval = p->p_retval;
1713	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1714	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) {
1715#ifdef DEBUG_SVR4
1716	        uprintf("putmsg: bad fp\n");
1717#endif
1718		return EBADF;
1719	}
1720
1721#ifdef DEBUG_SVR4
1722	show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
1723		 SCARG(uap, dat), SCARG(uap, flags));
1724#endif /* DEBUG_SVR4 */
1725
1726	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1727	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) {
1728#ifdef DEBUG_SVR4
1729	        uprintf("putmsg: bad fp(2)\n");
1730#endif
1731		return EBADF;
1732	}
1733
1734	if (SCARG(uap, ctl) != NULL) {
1735	  if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
1736#ifdef DEBUG_SVR4
1737	    uprintf("putmsg: copyin(): %d\n", error);
1738#endif
1739	    return error;
1740	  }
1741	}
1742	else
1743		ctl.len = -1;
1744
1745	if (SCARG(uap, dat) != NULL) {
1746	  if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
1747#ifdef DEBUG_SVR4
1748	    uprintf("putmsg: copyin(): %d (2)\n", error);
1749#endif
1750	    return error;
1751	  }
1752	}
1753	else
1754		dat.len = -1;
1755
1756	/*
1757	 * Only for sockets for now.
1758	 */
1759	if ((st = svr4_stream_get(fp)) == NULL) {
1760		DPRINTF(("putmsg: bad file type\n"));
1761		return EINVAL;
1762	}
1763
1764	if (ctl.len > sizeof(sc)) {
1765		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
1766			 sizeof(struct svr4_strmcmd)));
1767		return EINVAL;
1768	}
1769
1770	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1771		return error;
1772
1773	switch (st->s_family) {
1774	case AF_INET:
1775	        if (sc.len != sizeof(sain)) {
1776		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
1777			        struct write_args wa;
1778
1779				/* Solaris seems to use sc.cmd = 3 to
1780				 * send "expedited" data.  telnet uses
1781				 * this for options processing, sending EOF,
1782				 * etc.  I'm sure other things use it too.
1783				 * I don't have any documentation
1784				 * on it, so I'm making a guess that this
1785				 * is how it works. newton@atdot.dotat.org XXX
1786				 */
1787				DPRINTF(("sending expedited data (???)\n"));
1788				SCARG(&wa, fd) = SCARG(uap, fd);
1789				SCARG(&wa, buf) = dat.buf;
1790				SCARG(&wa, nbyte) = dat.len;
1791				return write(p, &wa);
1792			}
1793	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1794	                return EINVAL;
1795	        }
1796	        netaddr_to_sockaddr_in(&sain, &sc);
1797	        skp = &sain;
1798	        sasize = sizeof(sain);
1799	        error = sain.sin_family != st->s_family;
1800		break;
1801
1802	case AF_LOCAL:
1803		if (ctl.len == 8) {
1804			/* We are doing an accept; succeed */
1805			DPRINTF(("putmsg: Do nothing\n"));
1806			*retval = 0;
1807			return 0;
1808		}
1809		else {
1810			/* Maybe we've been given a device/inode pair */
1811			udev_t *dev = SVR4_ADDROF(&sc);
1812			ino_t *ino = (ino_t *) &dev[1];
1813			skp = svr4_find_socket(p, fp, *dev, *ino);
1814			if (skp == NULL) {
1815				skp = &saun;
1816				/* I guess we have it by name */
1817				netaddr_to_sockaddr_un(skp, &sc);
1818			}
1819			sasize = sizeof(saun);
1820		}
1821		break;
1822
1823	default:
1824		DPRINTF(("putmsg: Unsupported address family %d\n",
1825			 st->s_family));
1826		return ENOSYS;
1827	}
1828
1829	sg = stackgap_init();
1830	sup = stackgap_alloc(&sg, sasize);
1831
1832	if ((error = copyout(skp, sup, sasize)) != 0)
1833		return error;
1834
1835	switch (st->s_cmd = sc.cmd) {
1836	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
1837		{
1838			struct connect_args co;
1839
1840			SCARG(&co, s) = SCARG(uap, fd);
1841			SCARG(&co, name) = (void *) sup;
1842			SCARG(&co, namelen) = (int) sasize;
1843
1844			return connect(p, &co);
1845		}
1846
1847	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
1848		{
1849			struct msghdr msg;
1850			struct iovec aiov;
1851
1852			msg.msg_name = (caddr_t) sup;
1853			msg.msg_namelen = sasize;
1854			msg.msg_iov = &aiov;
1855			msg.msg_iovlen = 1;
1856			msg.msg_control = 0;
1857			msg.msg_flags = 0;
1858			aiov.iov_base = dat.buf;
1859			aiov.iov_len = dat.len;
1860#if 0
1861			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
1862					      uio, 0, 0, 0, uio->uio_procp);
1863#endif
1864			error = svr4_sendit(p, SCARG(uap, fd), &msg,
1865				       SCARG(uap, flags));
1866			DPRINTF(("sendto_request error: %d\n", error));
1867			*retval = 0;
1868			return error;
1869		}
1870
1871	default:
1872		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1873		return ENOSYS;
1874	}
1875}
1876
1877int
1878svr4_sys_getmsg(p, uap)
1879	register struct proc *p;
1880	struct svr4_sys_getmsg_args *uap;
1881{
1882	struct filedesc	*fdp = p->p_fd;
1883	struct file	*fp;
1884	struct getpeername_args ga;
1885	struct accept_args aa;
1886	struct svr4_strbuf dat, ctl;
1887	struct svr4_strmcmd sc;
1888	int error, *retval;
1889	struct msghdr msg;
1890	struct iovec aiov;
1891	struct sockaddr_in sain;
1892	struct sockaddr_un saun;
1893	void *skp, *sup;
1894	int sasize;
1895	struct svr4_strm *st;
1896	int *flen;
1897	int fl;
1898	caddr_t sg;
1899
1900	retval = p->p_retval;
1901	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1902	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1903		return EBADF;
1904
1905	memset(&sc, 0, sizeof(sc));
1906
1907#ifdef DEBUG_SVR4
1908	show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1909		 SCARG(uap, dat), 0);
1910#endif /* DEBUG_SVR4 */
1911
1912	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1913	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1914		return EBADF;
1915
1916	if (SCARG(uap, ctl) != NULL) {
1917		if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
1918			return error;
1919	}
1920	else {
1921		ctl.len = -1;
1922		ctl.maxlen = 0;
1923	}
1924
1925	if (SCARG(uap, dat) != NULL) {
1926	    	if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
1927			return error;
1928	}
1929	else {
1930		dat.len = -1;
1931		dat.maxlen = 0;
1932	}
1933
1934	/*
1935	 * Only for sockets for now.
1936	 */
1937	if ((st = svr4_stream_get(fp)) == NULL) {
1938		DPRINTF(("getmsg: bad file type\n"));
1939		return EINVAL;
1940	}
1941
1942	if (ctl.maxlen == -1 || dat.maxlen == -1) {
1943		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1944		return ENOSYS;
1945	}
1946
1947	switch (st->s_family) {
1948	case AF_INET:
1949		skp = &sain;
1950		sasize = sizeof(sain);
1951		break;
1952
1953	case AF_LOCAL:
1954		skp = &saun;
1955		sasize = sizeof(saun);
1956		break;
1957
1958	default:
1959		DPRINTF(("getmsg: Unsupported address family %d\n",
1960			 st->s_family));
1961		return ENOSYS;
1962	}
1963
1964	sg = stackgap_init();
1965	sup = stackgap_alloc(&sg, sasize);
1966	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
1967
1968	fl = sasize;
1969	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
1970		return error;
1971
1972	switch (st->s_cmd) {
1973	case SVR4_TI_CONNECT_REQUEST:
1974		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
1975		/*
1976		 * We do the connect in one step, so the putmsg should
1977		 * have gotten the error.
1978		 */
1979		sc.cmd = SVR4_TI_OK_REPLY;
1980		sc.len = 0;
1981
1982		ctl.len = 8;
1983		dat.len = -1;
1984		fl = 1;
1985		st->s_cmd = sc.cmd;
1986		break;
1987
1988	case SVR4_TI_OK_REPLY:
1989		DPRINTF(("getmsg: TI_OK_REPLY\n"));
1990		/*
1991		 * We are immediately after a connect reply, so we send
1992		 * a connect verification.
1993		 */
1994
1995		SCARG(&ga, fdes) = SCARG(uap, fd);
1996		SCARG(&ga, asa) = (void *) sup;
1997		SCARG(&ga, alen) = flen;
1998
1999		if ((error = getpeername(p, &ga)) != 0) {
2000			DPRINTF(("getmsg: getpeername failed %d\n", error));
2001			return error;
2002		}
2003
2004		if ((error = copyin(sup, skp, sasize)) != 0)
2005			return error;
2006
2007		sc.cmd = SVR4_TI_CONNECT_REPLY;
2008		sc.pad[0] = 0x4;
2009		sc.offs = 0x18;
2010		sc.pad[1] = 0x14;
2011		sc.pad[2] = 0x04000402;
2012
2013		switch (st->s_family) {
2014		case AF_INET:
2015			sc.len = sasize;
2016			sockaddr_to_netaddr_in(&sc, &sain);
2017			break;
2018
2019		case AF_LOCAL:
2020			sc.len = sasize + 4;
2021			sockaddr_to_netaddr_un(&sc, &saun);
2022			break;
2023
2024		default:
2025			return ENOSYS;
2026		}
2027
2028		ctl.len = 40;
2029		dat.len = -1;
2030		fl = 0;
2031		st->s_cmd = sc.cmd;
2032		break;
2033
2034	case SVR4_TI__ACCEPT_OK:
2035		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
2036		/*
2037		 * We do the connect in one step, so the putmsg should
2038		 * have gotten the error.
2039		 */
2040		sc.cmd = SVR4_TI_OK_REPLY;
2041		sc.len = 1;
2042
2043		ctl.len = 8;
2044		dat.len = -1;
2045		fl = 1;
2046		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
2047		break;
2048
2049	case SVR4_TI__ACCEPT_WAIT:
2050		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
2051		/*
2052		 * We are after a listen, so we try to accept...
2053		 */
2054		SCARG(&aa, s) = SCARG(uap, fd);
2055		SCARG(&aa, name) = (void *) sup;
2056		SCARG(&aa, anamelen) = flen;
2057
2058		if ((error = accept(p, &aa)) != 0) {
2059			DPRINTF(("getmsg: accept failed %d\n", error));
2060			return error;
2061		}
2062
2063		st->s_afd = *retval;
2064
2065		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
2066
2067		if ((error = copyin(sup, skp, sasize)) != 0)
2068			return error;
2069
2070		sc.cmd = SVR4_TI_ACCEPT_REPLY;
2071		sc.offs = 0x18;
2072		sc.pad[0] = 0x0;
2073
2074		switch (st->s_family) {
2075		case AF_INET:
2076			sc.pad[1] = 0x28;
2077			sockaddr_to_netaddr_in(&sc, &sain);
2078			ctl.len = 40;
2079			sc.len = sasize;
2080			break;
2081
2082		case AF_LOCAL:
2083			sc.pad[1] = 0x00010000;
2084			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
2085			sc.pad[3] = 0x00010000;
2086			ctl.len = 134;
2087			sc.len = sasize + 4;
2088			break;
2089
2090		default:
2091			return ENOSYS;
2092		}
2093
2094		dat.len = -1;
2095		fl = 0;
2096		st->s_cmd = SVR4_TI__ACCEPT_OK;
2097		break;
2098
2099	case SVR4_TI_SENDTO_REQUEST:
2100		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
2101		if (ctl.maxlen > 36 && ctl.len < 36)
2102		    ctl.len = 36;
2103
2104		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
2105			return error;
2106
2107		switch (st->s_family) {
2108		case AF_INET:
2109			sockaddr_to_netaddr_in(&sc, &sain);
2110			break;
2111
2112		case AF_LOCAL:
2113			sockaddr_to_netaddr_un(&sc, &saun);
2114			break;
2115
2116		default:
2117			return ENOSYS;
2118		}
2119
2120		msg.msg_name = (caddr_t) sup;
2121		msg.msg_namelen = sasize;
2122		msg.msg_iov = &aiov;
2123		msg.msg_iovlen = 1;
2124		msg.msg_control = 0;
2125		aiov.iov_base = dat.buf;
2126		aiov.iov_len = dat.maxlen;
2127		msg.msg_flags = 0;
2128
2129		error = svr4_recvit(p, SCARG(uap, fd), &msg, (caddr_t) flen);
2130
2131		if (error) {
2132			DPRINTF(("getmsg: recvit failed %d\n", error));
2133			return error;
2134		}
2135
2136		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
2137			return error;
2138
2139		sc.cmd = SVR4_TI_RECVFROM_IND;
2140
2141		switch (st->s_family) {
2142		case AF_INET:
2143			sc.len = sasize;
2144			sockaddr_to_netaddr_in(&sc, &sain);
2145			break;
2146
2147		case AF_LOCAL:
2148			sc.len = sasize + 4;
2149			sockaddr_to_netaddr_un(&sc, &saun);
2150			break;
2151
2152		default:
2153			return ENOSYS;
2154		}
2155
2156		dat.len = *retval;
2157		fl = 0;
2158		st->s_cmd = sc.cmd;
2159		break;
2160
2161	default:
2162		st->s_cmd = sc.cmd;
2163		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
2164		        struct read_args ra;
2165
2166			/* More wierdness:  Again, I can't find documentation
2167			 * to back this up, but when a process does a generic
2168			 * "getmsg()" call it seems that the command field is
2169			 * zero and the length of the data area is zero.  I
2170			 * think processes expect getmsg() to fill in dat.len
2171			 * after reading at most dat.maxlen octets from the
2172			 * stream.  Since we're using sockets I can let
2173			 * read() look after it and frob return values
2174			 * appropriately (or inappropriately :-)
2175			 *   -- newton@atdot.dotat.org        XXX
2176			 */
2177			SCARG(&ra, fd) = SCARG(uap, fd);
2178			SCARG(&ra, buf) = dat.buf;
2179			SCARG(&ra, nbyte) = dat.maxlen;
2180			if ((error = read(p, &ra)) != 0) {
2181			        return error;
2182			}
2183			dat.len = *retval;
2184			*retval = 0;
2185			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
2186			break;
2187		}
2188		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
2189		return EINVAL;
2190	}
2191
2192	if (SCARG(uap, ctl)) {
2193		if (ctl.len != -1)
2194			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
2195				return error;
2196
2197		if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
2198			return error;
2199	}
2200
2201	if (SCARG(uap, dat)) {
2202		if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
2203			return error;
2204	}
2205
2206	if (SCARG(uap, flags)) { /* XXX: Need translation */
2207		if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
2208			return error;
2209	}
2210
2211	*retval = 0;
2212
2213#ifdef DEBUG_SVR4
2214	show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
2215		 SCARG(uap, dat), fl);
2216#endif /* DEBUG_SVR4 */
2217	return error;
2218}
2219
2220int svr4_sys_send(p, uap)
2221	struct proc *p;
2222	struct svr4_sys_send_args *uap;
2223{
2224	struct osend_args osa;
2225	SCARG(&osa, s) = SCARG(uap, s);
2226	SCARG(&osa, buf) = SCARG(uap, buf);
2227	SCARG(&osa, len) = SCARG(uap, len);
2228	SCARG(&osa, flags) = SCARG(uap, flags);
2229	return osend(p, &osa);
2230}
2231
2232int svr4_sys_recv(p, uap)
2233	struct proc *p;
2234	struct svr4_sys_recv_args *uap;
2235{
2236	struct orecv_args ora;
2237	SCARG(&ora, s) = SCARG(uap, s);
2238	SCARG(&ora, buf) = SCARG(uap, buf);
2239	SCARG(&ora, len) = SCARG(uap, len);
2240	SCARG(&ora, flags) = SCARG(uap, flags);
2241	return orecv(p, &ora);
2242}
2243
2244/*
2245 * XXX This isn't necessary, but it's handy for inserting debug code into
2246 * sendto().  Let's leave it here for now...
2247 */
2248int
2249svr4_sys_sendto(p, uap)
2250        struct proc *p;
2251        struct svr4_sys_sendto_args *uap;
2252{
2253        struct sendto_args sa;
2254
2255	SCARG(&sa, s) = SCARG(uap, s);
2256	SCARG(&sa, buf) = SCARG(uap, buf);
2257	SCARG(&sa, len) = SCARG(uap, len);
2258	SCARG(&sa, flags) = SCARG(uap, flags);
2259	SCARG(&sa, to) = SCARG(uap, to);
2260	SCARG(&sa, tolen) = SCARG(uap, tolen);
2261
2262	DPRINTF(("calling sendto()\n"));
2263	return sendto(p, &sa);
2264}
2265
2266