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