svr4_stream.c revision 103872
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 103872 2002-09-23 20:58:59Z 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/fcntl.h>
45#include <sys/filedesc.h>
46#include <sys/filio.h>
47#include <sys/lock.h>
48#include <sys/malloc.h>
49#include <sys/file.h> 		/* Must come after sys/malloc.h */
50#include <sys/mbuf.h>
51#include <sys/mutex.h>
52#include <sys/proc.h>
53#include <sys/protosw.h>
54#include <sys/signal.h>
55#include <sys/signalvar.h>
56#include <sys/socket.h>
57#include <sys/socketvar.h>
58#include <sys/stat.h>
59#include <sys/sysproto.h>
60#include <sys/uio.h>
61#include <sys/ktrace.h>		/* Must come after sys/uio.h */
62#include <sys/un.h>
63
64#include <netinet/in.h>
65
66#include <compat/svr4/svr4.h>
67#include <compat/svr4/svr4_types.h>
68#include <compat/svr4/svr4_util.h>
69#include <compat/svr4/svr4_signal.h>
70#include <compat/svr4/svr4_proto.h>
71#include <compat/svr4/svr4_stropts.h>
72#include <compat/svr4/svr4_timod.h>
73#include <compat/svr4/svr4_sockmod.h>
74#include <compat/svr4/svr4_ioctl.h>
75#include <compat/svr4/svr4_socket.h>
76
77/* Utils */
78static int clean_pipe(struct thread *, const char *);
79static void getparm(struct file *, struct svr4_si_sockparms *);
80static int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
81			       struct file *);
82static int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
83			       struct file *);
84
85/* Address Conversions */
86static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
87					const struct sockaddr_in *);
88static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
89					const struct sockaddr_un *);
90static void netaddr_to_sockaddr_in(struct sockaddr_in *,
91					const struct svr4_strmcmd *);
92static void netaddr_to_sockaddr_un(struct sockaddr_un *,
93					const struct svr4_strmcmd *);
94
95/* stream ioctls */
96static int i_nread(struct file *, struct thread *, register_t *, int,
97			u_long, caddr_t);
98static int i_fdinsert(struct file *, struct thread *, register_t *, int,
99			   u_long, caddr_t);
100static int i_str(struct file *, struct thread *, register_t *, int,
101			u_long, caddr_t);
102static int i_setsig(struct file *, struct thread *, register_t *, int,
103			u_long, caddr_t);
104static int i_getsig(struct file *, struct thread *, register_t *, int,
105			u_long, caddr_t);
106static int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
107			     u_long, caddr_t);
108static int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
109			     u_long, caddr_t);
110
111/* i_str sockmod calls */
112static int sockmod(struct file *, int, struct svr4_strioctl *,
113			      struct thread *);
114static int si_listen(struct file *, int, struct svr4_strioctl *,
115			      struct thread *);
116static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
117			      struct thread *);
118static int si_sockparams(struct file *, int, struct svr4_strioctl *,
119			      struct thread *);
120static int si_shutdown	(struct file *, int, struct svr4_strioctl *,
121			      struct thread *);
122static int si_getudata(struct file *, int, struct svr4_strioctl *,
123			      struct thread *);
124
125/* i_str timod calls */
126static int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
127static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
128			      struct thread *);
129static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
130
131/* infrastructure */
132static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
133
134static int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
135			    caddr_t namelenp);
136
137/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
138 * it isn't part of a "public" interface;  We're supposed to use
139 * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
140 * that matter.  Solution:  Suck sendit()/recvit() into here where we
141 * can do what we like.
142 *
143 * I hate code duplication.
144 *
145 * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
146 */
147static int
148svr4_sendit(td, s, mp, flags)
149	register struct thread *td;
150	int s;
151	register struct msghdr *mp;
152	int flags;
153{
154	struct uio auio;
155	register struct iovec *iov;
156	register int i;
157	struct mbuf *control;
158	struct sockaddr *to;
159	int len, error;
160	struct socket *so;
161#ifdef KTRACE
162	struct iovec *ktriov = NULL;
163	struct uio ktruio;
164#endif
165
166	if ((error = fgetsock(td, s, &so, NULL)) != 0)
167		return (error);
168	auio.uio_iov = mp->msg_iov;
169	auio.uio_iovcnt = mp->msg_iovlen;
170	auio.uio_segflg = UIO_USERSPACE;
171	auio.uio_rw = UIO_WRITE;
172	auio.uio_td = td;
173	auio.uio_offset = 0;			/* XXX */
174	auio.uio_resid = 0;
175	iov = mp->msg_iov;
176	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
177		if ((auio.uio_resid += iov->iov_len) < 0) {
178			error = EINVAL;
179			goto done1;
180		}
181	}
182	if (mp->msg_name) {
183		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
184		if (error)
185			goto done1;
186	} else {
187		to = 0;
188	}
189	if (mp->msg_control) {
190		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
191			error = EINVAL;
192			goto bad;
193		}
194		error = sockargs(&control, mp->msg_control,
195		    mp->msg_controllen, MT_CONTROL);
196		if (error)
197			goto bad;
198	} else {
199		control = 0;
200	}
201#ifdef KTRACE
202	if (KTRPOINT(td, KTR_GENIO)) {
203		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
204
205		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
206		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
207		ktruio = auio;
208	}
209#endif
210	len = auio.uio_resid;
211	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
212						     flags, td);
213	if (error) {
214		if (auio.uio_resid != len && (error == ERESTART ||
215		    error == EINTR || error == EWOULDBLOCK))
216			error = 0;
217		if (error == EPIPE) {
218			PROC_LOCK(td->td_proc);
219			psignal(td->td_proc, SIGPIPE);
220			PROC_UNLOCK(td->td_proc);
221		}
222	}
223	if (error == 0)
224		td->td_retval[0] = len - auio.uio_resid;
225#ifdef KTRACE
226	if (ktriov != NULL) {
227		if (error == 0) {
228			ktruio.uio_iov = ktriov;
229			ktruio.uio_resid = td->td_retval[0];
230			ktrgenio(s, UIO_WRITE, &ktruio, error);
231		}
232		FREE(ktriov, M_TEMP);
233	}
234#endif
235bad:
236	if (to)
237		FREE(to, M_SONAME);
238done1:
239	fputsock(so);
240	return (error);
241}
242
243static int
244svr4_recvit(td, s, mp, namelenp)
245	register struct thread *td;
246	int s;
247	register struct msghdr *mp;
248	caddr_t namelenp;
249{
250	struct uio auio;
251	register struct iovec *iov;
252	register int i;
253	int len, error;
254	struct mbuf *m, *control = 0;
255	caddr_t ctlbuf;
256	struct socket *so;
257	struct sockaddr *fromsa = 0;
258#ifdef KTRACE
259	struct iovec *ktriov = NULL;
260	struct uio ktruio;
261#endif
262
263	if ((error = fgetsock(td, s, &so, NULL)) != 0)
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_td = td;
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			error = EINVAL;
276			goto done1;
277		}
278	}
279#ifdef KTRACE
280	if (KTRPOINT(td, 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	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
290	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
291	    &mp->msg_flags);
292	if (error) {
293		if (auio.uio_resid != len && (error == ERESTART ||
294		    error == EINTR || error == EWOULDBLOCK))
295			error = 0;
296	}
297#ifdef KTRACE
298	if (ktriov != NULL) {
299		if (error == 0) {
300			ktruio.uio_iov = ktriov;
301			ktruio.uio_resid = len - auio.uio_resid;
302			ktrgenio(s, UIO_READ, &ktruio, error);
303		}
304		FREE(ktriov, M_TEMP);
305	}
306#endif
307	if (error)
308		goto out;
309	td->td_retval[0] = len - auio.uio_resid;
310	if (mp->msg_name) {
311		len = mp->msg_namelen;
312		if (len <= 0 || fromsa == 0)
313			len = 0;
314		else {
315#ifndef MIN
316#define MIN(a,b) ((a)>(b)?(b):(a))
317#endif
318			/* save sa_len before it is destroyed by MSG_COMPAT */
319			len = MIN(len, fromsa->sa_len);
320			error = copyout(fromsa,
321			    (caddr_t)mp->msg_name, (unsigned)len);
322			if (error)
323				goto out;
324		}
325		mp->msg_namelen = len;
326		if (namelenp &&
327		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
328			goto out;
329		}
330	}
331	if (mp->msg_control) {
332		len = mp->msg_controllen;
333		m = control;
334		mp->msg_controllen = 0;
335		ctlbuf = (caddr_t) mp->msg_control;
336
337		while (m && len > 0) {
338			unsigned int tocopy;
339
340			if (len >= m->m_len)
341				tocopy = m->m_len;
342			else {
343				mp->msg_flags |= MSG_CTRUNC;
344				tocopy = len;
345			}
346
347			if ((error = copyout((caddr_t)mtod(m, caddr_t),
348					ctlbuf, tocopy)) != 0)
349				goto out;
350
351			ctlbuf += tocopy;
352			len -= tocopy;
353			m = m->m_next;
354		}
355		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
356	}
357out:
358	if (fromsa)
359		FREE(fromsa, M_SONAME);
360	if (control)
361		m_freem(control);
362done1:
363	fputsock(so);
364	return (error);
365}
366
367#ifdef DEBUG_SVR4
368static void bufprint(u_char *, size_t);
369static int show_ioc(const char *, struct svr4_strioctl *);
370static int show_strbuf(struct svr4_strbuf *);
371static void show_msg(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(td, path)
498	struct thread *td;
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(td, &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(td, &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;
624	struct socket *so;
625
626	st = svr4_stream_get(fp);
627	if (st == NULL)
628		return;
629
630	so = (struct socket *) fp->f_data;
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, td)
664	struct file		*fp;
665	int 			 fd;
666	struct svr4_strioctl	*ioc;
667	struct thread		*td;
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, td)
721	struct file		*fp;
722	int 			 fd;
723	struct svr4_strioctl	*ioc;
724	struct thread		*td;
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, td)
735	struct file		*fp;
736	int 			 fd;
737	struct svr4_strioctl	*ioc;
738	struct thread		*td;
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(td, &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, td)
799	struct file		*fp;
800	int 			 fd;
801	struct svr4_strioctl	*ioc;
802	struct thread		*td;
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, td)
858	struct file		*fp;
859	int 			 fd;
860	struct svr4_strioctl	*ioc;
861	struct thread		*td;
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(td, &ap);
878}
879
880
881static int
882sockmod(fp, fd, ioc, td)
883	struct file		*fp;
884	int			 fd;
885	struct svr4_strioctl	*ioc;
886	struct thread		*td;
887{
888	switch (ioc->cmd) {
889	case SVR4_SI_OGETUDATA:
890		DPRINTF(("SI_OGETUDATA\n"));
891		return si_ogetudata(fp, fd, ioc, td);
892
893	case SVR4_SI_SHUTDOWN:
894		DPRINTF(("SI_SHUTDOWN\n"));
895		return si_shutdown(fp, fd, ioc, td);
896
897	case SVR4_SI_LISTEN:
898		DPRINTF(("SI_LISTEN\n"));
899		return si_listen(fp, fd, ioc, td);
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, td);
924
925	case SVR4_SI_GETUDATA:
926		DPRINTF(("SI_GETUDATA\n"));
927		return si_getudata(fp, fd, ioc, td);
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, td)
939	struct file		*fp;
940	int 			 fd;
941	struct svr4_strioctl	*ioc;
942	struct thread		*td;
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, td)
977	struct file		*fp;
978	int 			 fd;
979	struct svr4_strioctl	*ioc;
980	struct thread		*td;
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(td, 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(td, &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, td)
1080	struct file		*fp;
1081	int			 fd;
1082	struct svr4_strioctl	*ioc;
1083	struct thread		*td;
1084{
1085	switch (ioc->cmd) {
1086	case SVR4_TI_GETINFO:
1087		DPRINTF(("TI_GETINFO\n"));
1088		return ti_getinfo(fp, fd, ioc, td);
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, td);
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, td, retval, fd, cmd, dat)
1111	struct file *fp;
1112	struct thread *td;
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(td, &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(td, &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, td, retval, fd, cmd, dat)
1253	struct file *fp;
1254	struct thread *td;
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, td->td_ucred,
1271	    td)) != 0)
1272		return error;
1273
1274	if (nread != 0)
1275		*retval = 1;
1276	else
1277		*retval = 0;
1278
1279	return copyout(&nread, dat, sizeof(nread));
1280}
1281
1282static int
1283i_fdinsert(fp, td, retval, fd, cmd, dat)
1284	struct file *fp;
1285	struct thread *td;
1286	register_t *retval;
1287	int fd;
1288	u_long cmd;
1289	caddr_t dat;
1290{
1291	/*
1292	 * Major hack again here. We assume that we are using this to
1293	 * implement accept(2). If that is the case, we have already
1294	 * called accept, and we have stored the file descriptor in
1295	 * afd. We find the file descriptor that the code wants to use
1296	 * in fd insert, and then we dup2() our accepted file descriptor
1297	 * to it.
1298	 */
1299	int error;
1300	struct svr4_strm *st = svr4_stream_get(fp);
1301	struct svr4_strfdinsert fdi;
1302	struct dup2_args d2p;
1303	struct close_args clp;
1304
1305	if (st == NULL) {
1306		DPRINTF(("fdinsert: bad file type\n"));
1307		return EINVAL;
1308	}
1309
1310	if (st->s_afd == -1) {
1311		DPRINTF(("fdinsert: accept fd not found\n"));
1312		return ENOENT;
1313	}
1314
1315	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1316		DPRINTF(("fdinsert: copyin failed %d\n", error));
1317		return error;
1318	}
1319
1320	SCARG(&d2p, from) = st->s_afd;
1321	SCARG(&d2p, to) = fdi.fd;
1322
1323	if ((error = dup2(td, &d2p)) != 0) {
1324		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1325		    st->s_afd, fdi.fd, error));
1326		return error;
1327	}
1328
1329	SCARG(&clp, fd) = st->s_afd;
1330
1331	if ((error = close(td, &clp)) != 0) {
1332		DPRINTF(("fdinsert: close(%d) failed %d\n",
1333		    st->s_afd, error));
1334		return error;
1335	}
1336
1337	st->s_afd = -1;
1338
1339	*retval = 0;
1340	return 0;
1341}
1342
1343
1344static int
1345_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
1346	struct file *fp;
1347	struct thread *td;
1348	register_t *retval;
1349	int fd;
1350	u_long cmd;
1351	caddr_t dat;
1352{
1353	struct mkfifo_args ap;
1354
1355	/*
1356	 * This is a supposed to be a kernel and library only ioctl.
1357	 * It gets called before ti_bind, when we have a unix
1358	 * socket, to physically create the socket transport and
1359	 * ``reserve'' it. I don't know how this get reserved inside
1360	 * the kernel, but we are going to create it nevertheless.
1361	 */
1362	SCARG(&ap, path) = dat;
1363	SCARG(&ap, mode) = S_IFIFO;
1364
1365	return mkfifo(td, &ap);
1366}
1367
1368static int
1369_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
1370	struct file *fp;
1371	struct thread *td;
1372	register_t *retval;
1373	int fd;
1374	u_long cmd;
1375	caddr_t dat;
1376{
1377	struct unlink_args ap;
1378
1379	/*
1380	 * This is a supposed to be a kernel and library only ioctl.
1381	 * I guess it is supposed to release the socket.
1382	 */
1383	SCARG(&ap, path) = dat;
1384
1385	return unlink(td, &ap);
1386}
1387
1388static int
1389i_str(fp, td, retval, fd, cmd, dat)
1390	struct file *fp;
1391	struct thread *td;
1392	register_t *retval;
1393	int fd;
1394	u_long cmd;
1395	caddr_t dat;
1396{
1397	int			 error;
1398	struct svr4_strioctl	 ioc;
1399
1400	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1401		return error;
1402
1403#ifdef DEBUG_SVR4
1404	if ((error = show_ioc(">", &ioc)) != 0)
1405		return error;
1406#endif /* DEBUG_SVR4 */
1407
1408	switch (ioc.cmd & 0xff00) {
1409	case SVR4_SIMOD:
1410		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
1411			return error;
1412		break;
1413
1414	case SVR4_TIMOD:
1415		if ((error = timod(fp, fd, &ioc, td)) != 0)
1416			return error;
1417		break;
1418
1419	default:
1420		DPRINTF(("Unimplemented module %c %ld\n",
1421			 (char) (cmd >> 8), cmd & 0xff));
1422		return 0;
1423	}
1424
1425#ifdef DEBUG_SVR4
1426	if ((error = show_ioc("<", &ioc)) != 0)
1427		return error;
1428#endif /* DEBUG_SVR4 */
1429	return copyout(&ioc, dat, sizeof(ioc));
1430}
1431
1432static int
1433i_setsig(fp, td, retval, fd, cmd, dat)
1434	struct file *fp;
1435	struct thread *td;
1436	register_t *retval;
1437	int fd;
1438	u_long cmd;
1439	caddr_t dat;
1440{
1441	/*
1442	 * This is the best we can do for now; we cannot generate
1443	 * signals only for specific events so the signal mask gets
1444	 * ignored; we save it just to pass it to a possible I_GETSIG...
1445	 *
1446	 * We alse have to fix the O_ASYNC fcntl bit, so the
1447	 * process will get SIGPOLLs.
1448	 */
1449	struct fcntl_args fa;
1450	int error;
1451	register_t oflags, flags;
1452	struct svr4_strm *st = svr4_stream_get(fp);
1453
1454	if (st == NULL) {
1455		DPRINTF(("i_setsig: bad file descriptor\n"));
1456		return EINVAL;
1457	}
1458	/* get old status flags */
1459	SCARG(&fa, fd) = fd;
1460	SCARG(&fa, cmd) = F_GETFL;
1461	if ((error = fcntl(td, &fa)) != 0)
1462		return error;
1463
1464	oflags = td->td_retval[0];
1465
1466	/* update the flags */
1467	if (dat != NULL) {
1468		int mask;
1469
1470		flags = oflags | O_ASYNC;
1471		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
1472			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
1473			  return error;
1474		}
1475		if (mask & SVR4_S_ALLMASK) {
1476			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
1477			  return EINVAL;
1478		}
1479		st->s_eventmask = mask;
1480	}
1481	else {
1482		flags = oflags & ~O_ASYNC;
1483		st->s_eventmask = 0;
1484	}
1485
1486	/* set the new flags, if changed */
1487	if (flags != oflags) {
1488		SCARG(&fa, cmd) = F_SETFL;
1489		SCARG(&fa, arg) = (long) flags;
1490		if ((error = fcntl(td, &fa)) != 0)
1491			  return error;
1492		flags = td->td_retval[0];
1493	}
1494
1495	/* set up SIGIO receiver if needed */
1496	if (dat != NULL) {
1497		SCARG(&fa, cmd) = F_SETOWN;
1498		SCARG(&fa, arg) = (long) td->td_proc->p_pid;
1499		return fcntl(td, &fa);
1500	}
1501	return 0;
1502}
1503
1504static int
1505i_getsig(fp, td, retval, fd, cmd, dat)
1506	struct file *fp;
1507	struct thread *td;
1508	register_t *retval;
1509	int fd;
1510	u_long cmd;
1511	caddr_t dat;
1512{
1513	int error;
1514
1515	if (dat != NULL) {
1516		struct svr4_strm *st = svr4_stream_get(fp);
1517
1518		if (st == NULL) {
1519			DPRINTF(("i_getsig: bad file descriptor\n"));
1520			return EINVAL;
1521		}
1522		if ((error = copyout(&st->s_eventmask, dat,
1523				     sizeof(st->s_eventmask))) != 0) {
1524			DPRINTF(("i_getsig: bad eventmask pointer\n"));
1525			return error;
1526		}
1527	}
1528	return 0;
1529}
1530
1531int
1532svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
1533	struct file *fp;
1534	struct thread *td;
1535	register_t *retval;
1536	int fd;
1537	u_long cmd;
1538	caddr_t dat;
1539{
1540	*retval = 0;
1541
1542	/*
1543	 * All the following stuff assumes "sockmod" is pushed...
1544	 */
1545	switch (cmd) {
1546	case SVR4_I_NREAD:
1547		DPRINTF(("I_NREAD\n"));
1548		return i_nread(fp, td, retval, fd, cmd, dat);
1549
1550	case SVR4_I_PUSH:
1551		DPRINTF(("I_PUSH %p\n", dat));
1552#if defined(DEBUG_SVR4)
1553		show_strbuf((struct svr4_strbuf *)dat);
1554#endif
1555		return 0;
1556
1557	case SVR4_I_POP:
1558		DPRINTF(("I_POP\n"));
1559		return 0;
1560
1561	case SVR4_I_LOOK:
1562		DPRINTF(("I_LOOK\n"));
1563		return 0;
1564
1565	case SVR4_I_FLUSH:
1566		DPRINTF(("I_FLUSH\n"));
1567		return 0;
1568
1569	case SVR4_I_SRDOPT:
1570		DPRINTF(("I_SRDOPT\n"));
1571		return 0;
1572
1573	case SVR4_I_GRDOPT:
1574		DPRINTF(("I_GRDOPT\n"));
1575		return 0;
1576
1577	case SVR4_I_STR:
1578		DPRINTF(("I_STR\n"));
1579		return i_str(fp, td, retval, fd, cmd, dat);
1580
1581	case SVR4_I_SETSIG:
1582		DPRINTF(("I_SETSIG\n"));
1583		return i_setsig(fp, td, retval, fd, cmd, dat);
1584
1585	case SVR4_I_GETSIG:
1586	        DPRINTF(("I_GETSIG\n"));
1587		return i_getsig(fp, td, retval, fd, cmd, dat);
1588
1589	case SVR4_I_FIND:
1590		DPRINTF(("I_FIND\n"));
1591		/*
1592		 * Here we are not pushing modules really, we just
1593		 * pretend all are present
1594		 */
1595		*retval = 0;
1596		return 0;
1597
1598	case SVR4_I_LINK:
1599		DPRINTF(("I_LINK\n"));
1600		return 0;
1601
1602	case SVR4_I_UNLINK:
1603		DPRINTF(("I_UNLINK\n"));
1604		return 0;
1605
1606	case SVR4_I_ERECVFD:
1607		DPRINTF(("I_ERECVFD\n"));
1608		return 0;
1609
1610	case SVR4_I_PEEK:
1611		DPRINTF(("I_PEEK\n"));
1612		return 0;
1613
1614	case SVR4_I_FDINSERT:
1615		DPRINTF(("I_FDINSERT\n"));
1616		return i_fdinsert(fp, td, retval, fd, cmd, dat);
1617
1618	case SVR4_I_SENDFD:
1619		DPRINTF(("I_SENDFD\n"));
1620		return 0;
1621
1622	case SVR4_I_RECVFD:
1623		DPRINTF(("I_RECVFD\n"));
1624		return 0;
1625
1626	case SVR4_I_SWROPT:
1627		DPRINTF(("I_SWROPT\n"));
1628		return 0;
1629
1630	case SVR4_I_GWROPT:
1631		DPRINTF(("I_GWROPT\n"));
1632		return 0;
1633
1634	case SVR4_I_LIST:
1635		DPRINTF(("I_LIST\n"));
1636		return 0;
1637
1638	case SVR4_I_PLINK:
1639		DPRINTF(("I_PLINK\n"));
1640		return 0;
1641
1642	case SVR4_I_PUNLINK:
1643		DPRINTF(("I_PUNLINK\n"));
1644		return 0;
1645
1646	case SVR4_I_SETEV:
1647		DPRINTF(("I_SETEV\n"));
1648		return 0;
1649
1650	case SVR4_I_GETEV:
1651		DPRINTF(("I_GETEV\n"));
1652		return 0;
1653
1654	case SVR4_I_STREV:
1655		DPRINTF(("I_STREV\n"));
1656		return 0;
1657
1658	case SVR4_I_UNSTREV:
1659		DPRINTF(("I_UNSTREV\n"));
1660		return 0;
1661
1662	case SVR4_I_FLUSHBAND:
1663		DPRINTF(("I_FLUSHBAND\n"));
1664		return 0;
1665
1666	case SVR4_I_CKBAND:
1667		DPRINTF(("I_CKBAND\n"));
1668		return 0;
1669
1670	case SVR4_I_GETBAND:
1671		DPRINTF(("I_GETBANK\n"));
1672		return 0;
1673
1674	case SVR4_I_ATMARK:
1675		DPRINTF(("I_ATMARK\n"));
1676		return 0;
1677
1678	case SVR4_I_SETCLTIME:
1679		DPRINTF(("I_SETCLTIME\n"));
1680		return 0;
1681
1682	case SVR4_I_GETCLTIME:
1683		DPRINTF(("I_GETCLTIME\n"));
1684		return 0;
1685
1686	case SVR4_I_CANPUT:
1687		DPRINTF(("I_CANPUT\n"));
1688		return 0;
1689
1690	case SVR4__I_BIND_RSVD:
1691		DPRINTF(("_I_BIND_RSVD\n"));
1692		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
1693
1694	case SVR4__I_RELE_RSVD:
1695		DPRINTF(("_I_RELE_RSVD\n"));
1696		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
1697
1698	default:
1699		DPRINTF(("unimpl cmd = %lx\n", cmd));
1700		break;
1701	}
1702
1703	return 0;
1704}
1705
1706
1707
1708int
1709svr4_sys_putmsg(td, uap)
1710	register struct thread *td;
1711	struct svr4_sys_putmsg_args *uap;
1712{
1713	struct file     *fp;
1714	int error;
1715
1716	if ((error = fget(td, uap->fd, &fp)) != 0) {
1717#ifdef DEBUG_SVR4
1718	        uprintf("putmsg: bad fp\n");
1719#endif
1720		return EBADF;
1721	}
1722	error = svr4_do_putmsg(td, uap, fp);
1723	fdrop(fp, td);
1724	return (error);
1725}
1726
1727static int
1728svr4_do_putmsg(td, uap, fp)
1729	struct thread *td;
1730	struct svr4_sys_putmsg_args *uap;
1731	struct file	*fp;
1732{
1733	struct svr4_strbuf dat, ctl;
1734	struct svr4_strmcmd sc;
1735	struct sockaddr_in sain;
1736	struct sockaddr_un saun;
1737	void *skp, *sup;
1738	int sasize, *retval;
1739	struct svr4_strm *st;
1740	int error;
1741	caddr_t sg;
1742
1743	retval = td->td_retval;
1744
1745#ifdef DEBUG_SVR4
1746	show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
1747		 SCARG(uap, dat), SCARG(uap, flags));
1748#endif /* DEBUG_SVR4 */
1749
1750	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1751
1752	if (SCARG(uap, ctl) != NULL) {
1753	  if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
1754#ifdef DEBUG_SVR4
1755	    uprintf("putmsg: copyin(): %d\n", error);
1756#endif
1757	    return error;
1758	  }
1759	}
1760	else
1761		ctl.len = -1;
1762
1763	if (SCARG(uap, dat) != NULL) {
1764	  if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
1765#ifdef DEBUG_SVR4
1766	    uprintf("putmsg: copyin(): %d (2)\n", error);
1767#endif
1768	    return error;
1769	  }
1770	}
1771	else
1772		dat.len = -1;
1773
1774	/*
1775	 * Only for sockets for now.
1776	 */
1777	if ((st = svr4_stream_get(fp)) == NULL) {
1778		DPRINTF(("putmsg: bad file type\n"));
1779		return EINVAL;
1780	}
1781
1782	if (ctl.len > sizeof(sc)) {
1783		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
1784			 sizeof(struct svr4_strmcmd)));
1785		return EINVAL;
1786	}
1787
1788	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1789		return error;
1790
1791	switch (st->s_family) {
1792	case AF_INET:
1793	        if (sc.len != sizeof(sain)) {
1794		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
1795			        struct write_args wa;
1796
1797				/* Solaris seems to use sc.cmd = 3 to
1798				 * send "expedited" data.  telnet uses
1799				 * this for options processing, sending EOF,
1800				 * etc.  I'm sure other things use it too.
1801				 * I don't have any documentation
1802				 * on it, so I'm making a guess that this
1803				 * is how it works. newton@atdot.dotat.org XXX
1804				 */
1805				DPRINTF(("sending expedited data ??\n"));
1806				SCARG(&wa, fd) = SCARG(uap, fd);
1807				SCARG(&wa, buf) = dat.buf;
1808				SCARG(&wa, nbyte) = dat.len;
1809				return write(td, &wa);
1810			}
1811	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1812	                return EINVAL;
1813	        }
1814	        netaddr_to_sockaddr_in(&sain, &sc);
1815	        skp = &sain;
1816	        sasize = sizeof(sain);
1817	        error = sain.sin_family != st->s_family;
1818		break;
1819
1820	case AF_LOCAL:
1821		if (ctl.len == 8) {
1822			/* We are doing an accept; succeed */
1823			DPRINTF(("putmsg: Do nothing\n"));
1824			*retval = 0;
1825			return 0;
1826		}
1827		else {
1828			/* Maybe we've been given a device/inode pair */
1829			udev_t *dev = SVR4_ADDROF(&sc);
1830			ino_t *ino = (ino_t *) &dev[1];
1831			skp = svr4_find_socket(td, fp, *dev, *ino);
1832			if (skp == NULL) {
1833				skp = &saun;
1834				/* I guess we have it by name */
1835				netaddr_to_sockaddr_un(skp, &sc);
1836			}
1837			sasize = sizeof(saun);
1838		}
1839		break;
1840
1841	default:
1842		DPRINTF(("putmsg: Unsupported address family %d\n",
1843			 st->s_family));
1844		return ENOSYS;
1845	}
1846
1847	sg = stackgap_init();
1848	sup = stackgap_alloc(&sg, sasize);
1849
1850	if ((error = copyout(skp, sup, sasize)) != 0)
1851		return error;
1852
1853	switch (st->s_cmd = sc.cmd) {
1854	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
1855		{
1856			struct connect_args co;
1857
1858			SCARG(&co, s) = SCARG(uap, fd);
1859			SCARG(&co, name) = (void *) sup;
1860			SCARG(&co, namelen) = (int) sasize;
1861
1862			return connect(td, &co);
1863		}
1864
1865	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
1866		{
1867			struct msghdr msg;
1868			struct iovec aiov;
1869
1870			msg.msg_name = (caddr_t) sup;
1871			msg.msg_namelen = sasize;
1872			msg.msg_iov = &aiov;
1873			msg.msg_iovlen = 1;
1874			msg.msg_control = 0;
1875			msg.msg_flags = 0;
1876			aiov.iov_base = dat.buf;
1877			aiov.iov_len = dat.len;
1878#if 0
1879			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
1880					      uio, 0, 0, 0, uio->uio_td);
1881#endif
1882			error = svr4_sendit(td, SCARG(uap, fd), &msg,
1883				       SCARG(uap, flags));
1884			DPRINTF(("sendto_request error: %d\n", error));
1885			*retval = 0;
1886			return error;
1887		}
1888
1889	default:
1890		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1891		return ENOSYS;
1892	}
1893}
1894
1895int
1896svr4_sys_getmsg(td, uap)
1897	struct thread *td;
1898	struct svr4_sys_getmsg_args *uap;
1899{
1900	struct file     *fp;
1901	int error;
1902
1903	if ((error = fget(td, uap->fd, &fp)) != 0) {
1904#ifdef DEBUG_SVR4
1905	        uprintf("getmsg: bad fp\n");
1906#endif
1907		return EBADF;
1908	}
1909	error = svr4_do_getmsg(td, uap, fp);
1910	fdrop(fp, td);
1911	return (error);
1912}
1913
1914int
1915svr4_do_getmsg(td, uap, fp)
1916	register struct thread *td;
1917	struct svr4_sys_getmsg_args *uap;
1918	struct file *fp;
1919{
1920	struct getpeername_args ga;
1921	struct accept_args aa;
1922	struct svr4_strbuf dat, ctl;
1923	struct svr4_strmcmd sc;
1924	int error, *retval;
1925	struct msghdr msg;
1926	struct iovec aiov;
1927	struct sockaddr_in sain;
1928	struct sockaddr_un saun;
1929	void *skp, *sup;
1930	int sasize;
1931	struct svr4_strm *st;
1932	int *flen;
1933	int fl;
1934	caddr_t sg;
1935
1936	retval = td->td_retval;
1937
1938	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1939
1940	memset(&sc, 0, sizeof(sc));
1941
1942#ifdef DEBUG_SVR4
1943	show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1944		 SCARG(uap, dat), 0);
1945#endif /* DEBUG_SVR4 */
1946
1947	if (SCARG(uap, ctl) != NULL) {
1948		if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
1949			return error;
1950	}
1951	else {
1952		ctl.len = -1;
1953		ctl.maxlen = 0;
1954	}
1955
1956	if (SCARG(uap, dat) != NULL) {
1957	    	if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
1958			return error;
1959	}
1960	else {
1961		dat.len = -1;
1962		dat.maxlen = 0;
1963	}
1964
1965	/*
1966	 * Only for sockets for now.
1967	 */
1968	if ((st = svr4_stream_get(fp)) == NULL) {
1969		DPRINTF(("getmsg: bad file type\n"));
1970		return EINVAL;
1971	}
1972
1973	if (ctl.maxlen == -1 || dat.maxlen == -1) {
1974		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1975		return ENOSYS;
1976	}
1977
1978	switch (st->s_family) {
1979	case AF_INET:
1980		skp = &sain;
1981		sasize = sizeof(sain);
1982		break;
1983
1984	case AF_LOCAL:
1985		skp = &saun;
1986		sasize = sizeof(saun);
1987		break;
1988
1989	default:
1990		DPRINTF(("getmsg: Unsupported address family %d\n",
1991			 st->s_family));
1992		return ENOSYS;
1993	}
1994
1995	sg = stackgap_init();
1996	sup = stackgap_alloc(&sg, sasize);
1997	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
1998
1999	fl = sasize;
2000	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
2001		return error;
2002
2003	switch (st->s_cmd) {
2004	case SVR4_TI_CONNECT_REQUEST:
2005		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
2006		/*
2007		 * We do the connect in one step, so the putmsg should
2008		 * have gotten the error.
2009		 */
2010		sc.cmd = SVR4_TI_OK_REPLY;
2011		sc.len = 0;
2012
2013		ctl.len = 8;
2014		dat.len = -1;
2015		fl = 1;
2016		st->s_cmd = sc.cmd;
2017		break;
2018
2019	case SVR4_TI_OK_REPLY:
2020		DPRINTF(("getmsg: TI_OK_REPLY\n"));
2021		/*
2022		 * We are immediately after a connect reply, so we send
2023		 * a connect verification.
2024		 */
2025
2026		SCARG(&ga, fdes) = SCARG(uap, fd);
2027		SCARG(&ga, asa) = (void *) sup;
2028		SCARG(&ga, alen) = flen;
2029
2030		if ((error = getpeername(td, &ga)) != 0) {
2031			DPRINTF(("getmsg: getpeername failed %d\n", error));
2032			return error;
2033		}
2034
2035		if ((error = copyin(sup, skp, sasize)) != 0)
2036			return error;
2037
2038		sc.cmd = SVR4_TI_CONNECT_REPLY;
2039		sc.pad[0] = 0x4;
2040		sc.offs = 0x18;
2041		sc.pad[1] = 0x14;
2042		sc.pad[2] = 0x04000402;
2043
2044		switch (st->s_family) {
2045		case AF_INET:
2046			sc.len = sasize;
2047			sockaddr_to_netaddr_in(&sc, &sain);
2048			break;
2049
2050		case AF_LOCAL:
2051			sc.len = sasize + 4;
2052			sockaddr_to_netaddr_un(&sc, &saun);
2053			break;
2054
2055		default:
2056			return ENOSYS;
2057		}
2058
2059		ctl.len = 40;
2060		dat.len = -1;
2061		fl = 0;
2062		st->s_cmd = sc.cmd;
2063		break;
2064
2065	case SVR4_TI__ACCEPT_OK:
2066		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
2067		/*
2068		 * We do the connect in one step, so the putmsg should
2069		 * have gotten the error.
2070		 */
2071		sc.cmd = SVR4_TI_OK_REPLY;
2072		sc.len = 1;
2073
2074		ctl.len = 8;
2075		dat.len = -1;
2076		fl = 1;
2077		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
2078		break;
2079
2080	case SVR4_TI__ACCEPT_WAIT:
2081		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
2082		/*
2083		 * We are after a listen, so we try to accept...
2084		 */
2085		SCARG(&aa, s) = SCARG(uap, fd);
2086		SCARG(&aa, name) = (void *) sup;
2087		SCARG(&aa, anamelen) = flen;
2088
2089		if ((error = accept(td, &aa)) != 0) {
2090			DPRINTF(("getmsg: accept failed %d\n", error));
2091			return error;
2092		}
2093
2094		st->s_afd = *retval;
2095
2096		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
2097
2098		if ((error = copyin(sup, skp, sasize)) != 0)
2099			return error;
2100
2101		sc.cmd = SVR4_TI_ACCEPT_REPLY;
2102		sc.offs = 0x18;
2103		sc.pad[0] = 0x0;
2104
2105		switch (st->s_family) {
2106		case AF_INET:
2107			sc.pad[1] = 0x28;
2108			sockaddr_to_netaddr_in(&sc, &sain);
2109			ctl.len = 40;
2110			sc.len = sasize;
2111			break;
2112
2113		case AF_LOCAL:
2114			sc.pad[1] = 0x00010000;
2115			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
2116			sc.pad[3] = 0x00010000;
2117			ctl.len = 134;
2118			sc.len = sasize + 4;
2119			break;
2120
2121		default:
2122			return ENOSYS;
2123		}
2124
2125		dat.len = -1;
2126		fl = 0;
2127		st->s_cmd = SVR4_TI__ACCEPT_OK;
2128		break;
2129
2130	case SVR4_TI_SENDTO_REQUEST:
2131		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
2132		if (ctl.maxlen > 36 && ctl.len < 36)
2133		    ctl.len = 36;
2134
2135		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
2136			return error;
2137
2138		switch (st->s_family) {
2139		case AF_INET:
2140			sockaddr_to_netaddr_in(&sc, &sain);
2141			break;
2142
2143		case AF_LOCAL:
2144			sockaddr_to_netaddr_un(&sc, &saun);
2145			break;
2146
2147		default:
2148			return ENOSYS;
2149		}
2150
2151		msg.msg_name = (caddr_t) sup;
2152		msg.msg_namelen = sasize;
2153		msg.msg_iov = &aiov;
2154		msg.msg_iovlen = 1;
2155		msg.msg_control = 0;
2156		aiov.iov_base = dat.buf;
2157		aiov.iov_len = dat.maxlen;
2158		msg.msg_flags = 0;
2159
2160		error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen);
2161
2162		if (error) {
2163			DPRINTF(("getmsg: recvit failed %d\n", error));
2164			return error;
2165		}
2166
2167		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
2168			return error;
2169
2170		sc.cmd = SVR4_TI_RECVFROM_IND;
2171
2172		switch (st->s_family) {
2173		case AF_INET:
2174			sc.len = sasize;
2175			sockaddr_to_netaddr_in(&sc, &sain);
2176			break;
2177
2178		case AF_LOCAL:
2179			sc.len = sasize + 4;
2180			sockaddr_to_netaddr_un(&sc, &saun);
2181			break;
2182
2183		default:
2184			return ENOSYS;
2185		}
2186
2187		dat.len = *retval;
2188		fl = 0;
2189		st->s_cmd = sc.cmd;
2190		break;
2191
2192	default:
2193		st->s_cmd = sc.cmd;
2194		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
2195		        struct read_args ra;
2196
2197			/* More weirdness:  Again, I can't find documentation
2198			 * to back this up, but when a process does a generic
2199			 * "getmsg()" call it seems that the command field is
2200			 * zero and the length of the data area is zero.  I
2201			 * think processes expect getmsg() to fill in dat.len
2202			 * after reading at most dat.maxlen octets from the
2203			 * stream.  Since we're using sockets I can let
2204			 * read() look after it and frob return values
2205			 * appropriately (or inappropriately :-)
2206			 *   -- newton@atdot.dotat.org        XXX
2207			 */
2208			SCARG(&ra, fd) = SCARG(uap, fd);
2209			SCARG(&ra, buf) = dat.buf;
2210			SCARG(&ra, nbyte) = dat.maxlen;
2211			if ((error = read(td, &ra)) != 0) {
2212			        return error;
2213			}
2214			dat.len = *retval;
2215			*retval = 0;
2216			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
2217			break;
2218		}
2219		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
2220		return EINVAL;
2221	}
2222
2223	if (SCARG(uap, ctl)) {
2224		if (ctl.len != -1)
2225			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
2226				return error;
2227
2228		if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
2229			return error;
2230	}
2231
2232	if (SCARG(uap, dat)) {
2233		if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
2234			return error;
2235	}
2236
2237	if (SCARG(uap, flags)) { /* XXX: Need translation */
2238		if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
2239			return error;
2240	}
2241
2242	*retval = 0;
2243
2244#ifdef DEBUG_SVR4
2245	show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
2246		 SCARG(uap, dat), fl);
2247#endif /* DEBUG_SVR4 */
2248	return error;
2249}
2250
2251int svr4_sys_send(td, uap)
2252	struct thread *td;
2253	struct svr4_sys_send_args *uap;
2254{
2255	struct sendto_args osa;
2256
2257	SCARG(&osa, s) = SCARG(uap, s);
2258	SCARG(&osa, buf) = SCARG(uap, buf);
2259	SCARG(&osa, len) = SCARG(uap, len);
2260	SCARG(&osa, flags) = SCARG(uap, flags);
2261	SCARG(&osa, to) = NULL;
2262	SCARG(&osa, tolen) = 0;
2263	return sendto(td, &osa);
2264}
2265
2266int svr4_sys_recv(td, uap)
2267	struct thread *td;
2268	struct svr4_sys_recv_args *uap;
2269{
2270	struct recvfrom_args ora;
2271
2272	SCARG(&ora, s) = SCARG(uap, s);
2273	SCARG(&ora, buf) = SCARG(uap, buf);
2274	SCARG(&ora, len) = SCARG(uap, len);
2275	SCARG(&ora, flags) = SCARG(uap, flags);
2276	SCARG(&ora, from) = NULL;
2277	SCARG(&ora, fromlen) = 0;
2278	return recvfrom(td, &ora);
2279}
2280
2281/*
2282 * XXX This isn't necessary, but it's handy for inserting debug code into
2283 * sendto().  Let's leave it here for now...
2284 */
2285int
2286svr4_sys_sendto(td, uap)
2287        struct thread *td;
2288        struct svr4_sys_sendto_args *uap;
2289{
2290        struct sendto_args sa;
2291
2292	SCARG(&sa, s) = SCARG(uap, s);
2293	SCARG(&sa, buf) = SCARG(uap, buf);
2294	SCARG(&sa, len) = SCARG(uap, len);
2295	SCARG(&sa, flags) = SCARG(uap, flags);
2296	SCARG(&sa, to) = (caddr_t)SCARG(uap, to);
2297	SCARG(&sa, tolen) = SCARG(uap, tolen);
2298
2299	DPRINTF(("calling sendto()\n"));
2300	return sendto(td, &sa);
2301}
2302
2303