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