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