svr4_stream.c revision 89536
1191665Sbms/*
2191665Sbms * Copyright (c) 1998 Mark Newton.  All rights reserved.
3191665Sbms * Copyright (c) 1994, 1996 Christos Zoulas.  All rights reserved.
4191665Sbms *
5191665Sbms * Redistribution and use in source and binary forms, with or without
6191665Sbms * modification, are permitted provided that the following conditions
7191665Sbms * are met:
8191665Sbms * 1. Redistributions of source code must retain the above copyright
9191665Sbms *    notice, this list of conditions and the following disclaimer.
10191665Sbms * 2. Redistributions in binary form must reproduce the above copyright
11191665Sbms *    notice, this list of conditions and the following disclaimer in the
12191665Sbms *    documentation and/or other materials provided with the distribution.
13191665Sbms * 3. All advertising materials mentioning features or use of this software
14191665Sbms *    must display the following acknowledgement:
15191665Sbms *	This product includes software developed by Christos Zoulas.
16191665Sbms * 4. The name of the author may not be used to endorse or promote products
17191665Sbms *    derived from this software without specific prior written permission.
18191665Sbms *
19191665Sbms * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20191665Sbms * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21191665Sbms * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22191665Sbms * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23191665Sbms * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24191665Sbms * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25191665Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26191665Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27191665Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28191665Sbms * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29191665Sbms *
30191665Sbms * $FreeBSD: head/sys/compat/svr4/svr4_stream.c 89536 2002-01-19 03:52:17Z alfred $
31191665Sbms */
32191672Sbms
33191665Sbms/*
34191665Sbms * Pretend that we have streams...
35191665Sbms * Yes, this is gross.
36191665Sbms *
37191665Sbms * ToDo: The state machine for getmsg needs re-thinking
38191665Sbms */
39191665Sbms
40191665Sbms#define COMPAT_43 1
41191665Sbms
42191665Sbms#include <sys/param.h>
43191665Sbms#include <sys/systm.h>
44191665Sbms#include <sys/fcntl.h>
45191665Sbms#include <sys/filedesc.h>
46191665Sbms#include <sys/filio.h>
47191665Sbms#include <sys/lock.h>
48191665Sbms#include <sys/malloc.h>
49191665Sbms#include <sys/file.h> 		/* Must come after sys/malloc.h */
50191665Sbms#include <sys/mbuf.h>
51191665Sbms#include <sys/mutex.h>
52191665Sbms#include <sys/proc.h>
53191665Sbms#include <sys/protosw.h>
54191665Sbms#include <sys/signal.h>
55257176Sglebius#include <sys/signalvar.h>
56191665Sbms#include <sys/socket.h>
57191665Sbms#include <sys/socketvar.h>
58191665Sbms#include <sys/stat.h>
59191665Sbms#include <sys/sysproto.h>
60191665Sbms#include <sys/uio.h>
61191665Sbms#include <sys/ktrace.h>		/* Must come after sys/uio.h */
62292015Smelifaro#include <sys/un.h>
63191665Sbms
64191665Sbms#include <netinet/in.h>
65191665Sbms
66191665Sbms#include <compat/svr4/svr4.h>
67191665Sbms#include <compat/svr4/svr4_types.h>
68191665Sbms#include <compat/svr4/svr4_util.h>
69191665Sbms#include <compat/svr4/svr4_signal.h>
70191665Sbms#include <compat/svr4/svr4_proto.h>
71195699Srwatson#include <compat/svr4/svr4_stropts.h>
72191665Sbms#include <compat/svr4/svr4_timod.h>
73191665Sbms#include <compat/svr4/svr4_sockmod.h>
74191665Sbms#include <compat/svr4/svr4_ioctl.h>
75191665Sbms#include <compat/svr4/svr4_socket.h>
76191665Sbms
77191665Sbms/* Utils */
78191665Sbmsstatic int clean_pipe __P((struct thread *, const char *));
79191665Sbmsstatic void getparm __P((struct file *, struct svr4_si_sockparms *));
80191665Sbmsstatic int svr4_do_putmsg __P((struct thread *, struct svr4_sys_putmsg_args *,
81191665Sbms			       struct file *));
82191665Sbmsstatic int svr4_do_getmsg __P((struct thread *, struct svr4_sys_getmsg_args *,
83191665Sbms			       struct file *));
84191665Sbms
85191665Sbms/* Address Conversions */
86191665Sbmsstatic void sockaddr_to_netaddr_in __P((struct svr4_strmcmd *,
87191665Sbms					const struct sockaddr_in *));
88191665Sbmsstatic void sockaddr_to_netaddr_un __P((struct svr4_strmcmd *,
89191665Sbms					const struct sockaddr_un *));
90191665Sbmsstatic void netaddr_to_sockaddr_in __P((struct sockaddr_in *,
91191665Sbms					const struct svr4_strmcmd *));
92191665Sbmsstatic void netaddr_to_sockaddr_un __P((struct sockaddr_un *,
93191665Sbms					const struct svr4_strmcmd *));
94191665Sbms
95191665Sbms/* stream ioctls */
96191665Sbmsstatic int i_nread __P((struct file *, struct thread *, register_t *, int,
97191665Sbms			u_long, caddr_t));
98191665Sbmsstatic int i_fdinsert __P((struct file *, struct thread *, register_t *, int,
99191665Sbms			   u_long, caddr_t));
100191665Sbmsstatic int i_str   __P((struct file *, struct thread *, register_t *, int,
101191665Sbms			u_long, caddr_t));
102191665Sbmsstatic int i_setsig   __P((struct file *, struct thread *, register_t *, int,
103191665Sbms			u_long, caddr_t));
104191665Sbmsstatic int i_getsig   __P((struct file *, struct thread *, register_t *, int,
105191665Sbms			u_long, caddr_t));
106191665Sbmsstatic int _i_bind_rsvd __P((struct file *, struct thread *, register_t *, int,
107191665Sbms			     u_long, caddr_t));
108191665Sbmsstatic int _i_rele_rsvd __P((struct file *, struct thread *, register_t *, int,
109191665Sbms			     u_long, caddr_t));
110191665Sbms
111191665Sbms/* i_str sockmod calls */
112191665Sbmsstatic int sockmod       __P((struct file *, int, struct svr4_strioctl *,
113191665Sbms			      struct thread *));
114191665Sbmsstatic int si_listen     __P((struct file *, int, struct svr4_strioctl *,
115191665Sbms			      struct thread *));
116191665Sbmsstatic int si_ogetudata  __P((struct file *, int, struct svr4_strioctl *,
117191665Sbms			      struct thread *));
118191665Sbmsstatic int si_sockparams __P((struct file *, int, struct svr4_strioctl *,
119191665Sbms			      struct thread *));
120191665Sbmsstatic int si_shutdown	 __P((struct file *, int, struct svr4_strioctl *,
121191665Sbms			      struct thread *));
122191665Sbmsstatic int si_getudata   __P((struct file *, int, struct svr4_strioctl *,
123191665Sbms			      struct thread *));
124191665Sbms
125191665Sbms/* i_str timod calls */
126191665Sbmsstatic int timod         __P((struct file *, int, struct svr4_strioctl *,
127191665Sbms		              struct thread *));
128191665Sbmsstatic int ti_getinfo    __P((struct file *, int, struct svr4_strioctl *,
129191665Sbms			      struct thread *));
130191665Sbmsstatic int ti_bind       __P((struct file *, int, struct svr4_strioctl *,
131191665Sbms			      struct thread *));
132191665Sbms
133191665Sbms/* infrastructure */
134191665Sbmsstatic int svr4_sendit __P((struct thread *td, int s, struct msghdr *mp,
135191665Sbms			    int flags));
136259840Sdim
137191665Sbmsstatic int svr4_recvit __P((struct thread *td, int s, struct msghdr *mp,
138259840Sdim			    caddr_t namelenp));
139191665Sbms
140191665Sbms/* <sigh>  Ok, so we shouldn't use sendit() in uipc_syscalls.c because
141191665Sbms * it isn't part of a "public" interface;  We're supposed to use
142191665Sbms * pru_sosend instead.  Same goes for recvit()/pru_soreceive() for
143191665Sbms * that matter.  Solution:  Suck sendit()/recvit() into here where we
144191665Sbms * can do what we like.
145191665Sbms *
146191665Sbms * I hate code duplication.
147191672Sbms *
148191672Sbms * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
149191672Sbms */
150191665Sbmsstatic int
151191665Sbmssvr4_sendit(td, s, mp, flags)
152191665Sbms	register struct thread *td;
153191665Sbms	int s;
154191665Sbms	register struct msghdr *mp;
155191665Sbms	int flags;
156191665Sbms{
157227309Sed	struct uio auio;
158227309Sed	register struct iovec *iov;
159191665Sbms	register int i;
160191665Sbms	struct mbuf *control;
161191665Sbms	struct sockaddr *to;
162267992Shselasky	int len, error;
163191665Sbms	struct socket *so;
164191665Sbms#ifdef KTRACE
165191665Sbms	struct iovec *ktriov = NULL;
166191665Sbms	struct uio ktruio;
167267992Shselasky#endif
168191665Sbms
169191665Sbms	if ((error = fgetsock(td, s, &so, NULL)) != 0)
170191665Sbms		return (error);
171191665Sbms	auio.uio_iov = mp->msg_iov;
172267992Shselasky	auio.uio_iovcnt = mp->msg_iovlen;
173191665Sbms	auio.uio_segflg = UIO_USERSPACE;
174191665Sbms	auio.uio_rw = UIO_WRITE;
175227309Sed	auio.uio_td = td;
176191665Sbms	auio.uio_offset = 0;			/* XXX */
177191665Sbms	auio.uio_resid = 0;
178191665Sbms	iov = mp->msg_iov;
179259840Sdim	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
180191665Sbms		if ((auio.uio_resid += iov->iov_len) < 0) {
181191665Sbms			error = EINVAL;
182191665Sbms			goto done1;
183191665Sbms		}
184191665Sbms	}
185191665Sbms	if (mp->msg_name) {
186191665Sbms		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
187191665Sbms		if (error)
188191665Sbms			goto done1;
189191665Sbms	} else {
190191665Sbms		to = 0;
191191665Sbms	}
192191665Sbms	if (mp->msg_control) {
193191665Sbms		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
194191665Sbms			error = EINVAL;
195191665Sbms			goto bad;
196191665Sbms		}
197191665Sbms		error = sockargs(&control, mp->msg_control,
198191665Sbms		    mp->msg_controllen, MT_CONTROL);
199191665Sbms		if (error)
200191665Sbms			goto bad;
201191665Sbms	} else {
202259840Sdim		control = 0;
203191665Sbms	}
204191665Sbms#ifdef KTRACE
205191665Sbms	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
206191665Sbms		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
207191665Sbms
208191665Sbms		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
209191665Sbms		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
210191665Sbms		ktruio = auio;
211191665Sbms	}
212191665Sbms#endif
213191665Sbms	len = auio.uio_resid;
214191665Sbms	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
215191665Sbms						     flags, td);
216191665Sbms	if (error) {
217191665Sbms		if (auio.uio_resid != len && (error == ERESTART ||
218191665Sbms		    error == EINTR || error == EWOULDBLOCK))
219191665Sbms			error = 0;
220191665Sbms		if (error == EPIPE) {
221191665Sbms			PROC_LOCK(td->td_proc);
222191665Sbms			psignal(td->td_proc, SIGPIPE);
223191665Sbms			PROC_UNLOCK(td->td_proc);
224191665Sbms		}
225191665Sbms	}
226191665Sbms	if (error == 0)
227191665Sbms		td->td_retval[0] = len - auio.uio_resid;
228191665Sbms#ifdef KTRACE
229191665Sbms	if (ktriov != NULL) {
230191665Sbms		if (error == 0) {
231191665Sbms			ktruio.uio_iov = ktriov;
232191665Sbms			ktruio.uio_resid = td->td_retval[0];
233191665Sbms			ktrgenio(td->td_proc->p_tracep, s, UIO_WRITE, &ktruio, error);
234191665Sbms		}
235191665Sbms		FREE(ktriov, M_TEMP);
236191665Sbms	}
237191665Sbms#endif
238191665Sbmsbad:
239191665Sbms	if (to)
240191665Sbms		FREE(to, M_SONAME);
241191665Sbmsdone1:
242191665Sbms	fputsock(so);
243191665Sbms	return (error);
244191665Sbms}
245191665Sbms
246191665Sbmsstatic int
247191665Sbmssvr4_recvit(td, s, mp, namelenp)
248191665Sbms	register struct thread *td;
249191665Sbms	int s;
250191665Sbms	register struct msghdr *mp;
251191665Sbms	caddr_t namelenp;
252191665Sbms{
253191665Sbms	struct uio auio;
254191665Sbms	register struct iovec *iov;
255191665Sbms	register int i;
256191665Sbms	int len, error;
257191665Sbms	struct mbuf *m, *control = 0;
258191665Sbms	caddr_t ctlbuf;
259191665Sbms	struct socket *so;
260191665Sbms	struct sockaddr *fromsa = 0;
261191665Sbms#ifdef KTRACE
262191665Sbms	struct iovec *ktriov = NULL;
263191665Sbms	struct uio ktruio;
264191665Sbms#endif
265191665Sbms
266191665Sbms	if ((error = fgetsock(td, s, &so, NULL)) != 0)
267191665Sbms		return (error);
268191665Sbms	auio.uio_iov = mp->msg_iov;
269191665Sbms	auio.uio_iovcnt = mp->msg_iovlen;
270191665Sbms	auio.uio_segflg = UIO_USERSPACE;
271191665Sbms	auio.uio_rw = UIO_READ;
272191665Sbms	auio.uio_td = td;
273191665Sbms	auio.uio_offset = 0;			/* XXX */
274191665Sbms	auio.uio_resid = 0;
275191665Sbms	iov = mp->msg_iov;
276191665Sbms	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
277191665Sbms		if ((auio.uio_resid += iov->iov_len) < 0) {
278191665Sbms			error = EINVAL;
279191665Sbms			goto done1;
280191665Sbms		}
281191665Sbms	}
282191665Sbms#ifdef KTRACE
283191665Sbms	if (KTRPOINT(td->td_proc, KTR_GENIO)) {
284191665Sbms		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
285191665Sbms
286191665Sbms		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
287191665Sbms		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
288191665Sbms		ktruio = auio;
289191665Sbms	}
290191665Sbms#endif
291191665Sbms	len = auio.uio_resid;
292191665Sbms	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
293191665Sbms	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
294191665Sbms	    &mp->msg_flags);
295191665Sbms	if (error) {
296191665Sbms		if (auio.uio_resid != len && (error == ERESTART ||
297191665Sbms		    error == EINTR || error == EWOULDBLOCK))
298191665Sbms			error = 0;
299191665Sbms	}
300191665Sbms#ifdef KTRACE
301191665Sbms	if (ktriov != NULL) {
302191665Sbms		if (error == 0) {
303191665Sbms			ktruio.uio_iov = ktriov;
304191665Sbms			ktruio.uio_resid = len - auio.uio_resid;
305191665Sbms			ktrgenio(td->td_proc->p_tracep, s, UIO_READ, &ktruio, error);
306191665Sbms		}
307191665Sbms		FREE(ktriov, M_TEMP);
308191665Sbms	}
309192923Sbms#endif
310192923Sbms	if (error)
311192923Sbms		goto out;
312192923Sbms	td->td_retval[0] = len - auio.uio_resid;
313191665Sbms	if (mp->msg_name) {
314191665Sbms		len = mp->msg_namelen;
315191665Sbms		if (len <= 0 || fromsa == 0)
316191665Sbms			len = 0;
317191665Sbms		else {
318191665Sbms#ifndef MIN
319191665Sbms#define MIN(a,b) ((a)>(b)?(b):(a))
320191665Sbms#endif
321191665Sbms			/* save sa_len before it is destroyed by MSG_COMPAT */
322191665Sbms			len = MIN(len, fromsa->sa_len);
323191665Sbms			error = copyout(fromsa,
324191665Sbms			    (caddr_t)mp->msg_name, (unsigned)len);
325191665Sbms			if (error)
326191665Sbms				goto out;
327191665Sbms		}
328191665Sbms		mp->msg_namelen = len;
329191665Sbms		if (namelenp &&
330191665Sbms		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
331191665Sbms			goto out;
332191665Sbms		}
333191665Sbms	}
334191665Sbms	if (mp->msg_control) {
335191665Sbms		len = mp->msg_controllen;
336192923Sbms		m = control;
337191665Sbms		mp->msg_controllen = 0;
338191665Sbms		ctlbuf = (caddr_t) mp->msg_control;
339191665Sbms
340191665Sbms		while (m && len > 0) {
341191665Sbms			unsigned int tocopy;
342191665Sbms
343191665Sbms			if (len >= m->m_len)
344191665Sbms				tocopy = m->m_len;
345191665Sbms			else {
346191665Sbms				mp->msg_flags |= MSG_CTRUNC;
347191665Sbms				tocopy = len;
348191665Sbms			}
349191665Sbms
350191665Sbms			if ((error = copyout((caddr_t)mtod(m, caddr_t),
351191665Sbms					ctlbuf, tocopy)) != 0)
352191665Sbms				goto out;
353191665Sbms
354191665Sbms			ctlbuf += tocopy;
355191665Sbms			len -= tocopy;
356191665Sbms			m = m->m_next;
357191665Sbms		}
358191665Sbms		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
359191665Sbms	}
360191665Sbmsout:
361191665Sbms	if (fromsa)
362191665Sbms		FREE(fromsa, M_SONAME);
363191665Sbms	if (control)
364191665Sbms		m_freem(control);
365191665Sbmsdone1:
366191665Sbms	fputsock(so);
367191665Sbms	return (error);
368191665Sbms}
369191665Sbms
370191665Sbms#ifdef DEBUG_SVR4
371191665Sbmsstatic void bufprint __P((u_char *, size_t));
372191665Sbmsstatic int show_ioc __P((const char *, struct svr4_strioctl *));
373191665Sbmsstatic int show_strbuf __P((struct svr4_strbuf *));
374191665Sbmsstatic void show_msg __P((const char *, int, struct svr4_strbuf *,
375191665Sbms			  struct svr4_strbuf *, int));
376191665Sbms
377191665Sbmsstatic void
378191665Sbmsbufprint(buf, len)
379191665Sbms	u_char *buf;
380191665Sbms	size_t len;
381191665Sbms{
382191665Sbms	size_t i;
383191665Sbms
384191665Sbms	uprintf("\n\t");
385191665Sbms	for (i = 0; i < len; i++) {
386191665Sbms		uprintf("%x ", buf[i]);
387191665Sbms		if (i && (i % 16) == 0)
388191665Sbms			uprintf("\n\t");
389191665Sbms	}
390191665Sbms}
391191665Sbms
392191665Sbmsstatic int
393191665Sbmsshow_ioc(str, ioc)
394191665Sbms	const char		*str;
395191665Sbms	struct svr4_strioctl	*ioc;
396191665Sbms{
397191665Sbms	u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK);
398191665Sbms	int error;
399191665Sbms
400191665Sbms	uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
401191665Sbms	    str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
402191665Sbms
403191665Sbms	if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) {
404191665Sbms		free((char *) ptr, M_TEMP);
405191665Sbms		return error;
406229621Sjhb	}
407191665Sbms
408191665Sbms	bufprint(ptr, ioc->len);
409191665Sbms
410191665Sbms	uprintf("}\n");
411191665Sbms
412191665Sbms	free((char *) ptr, M_TEMP);
413191665Sbms	return 0;
414191665Sbms}
415191665Sbms
416191665Sbms
417191665Sbmsstatic int
418191665Sbmsshow_strbuf(str)
419191665Sbms	struct svr4_strbuf *str;
420191665Sbms{
421191665Sbms	int error;
422191665Sbms	u_char *ptr = NULL;
423191665Sbms	int maxlen = str->maxlen;
424191665Sbms	int len = str->len;
425191665Sbms
426191665Sbms	if (maxlen < 0)
427191665Sbms		maxlen = 0;
428191665Sbms
429191665Sbms	if (len >= maxlen)
430229621Sjhb		len = maxlen;
431191665Sbms
432191665Sbms	if (len > 0) {
433191665Sbms	    ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
434229621Sjhb
435191665Sbms	    if ((error = copyin(str->buf, ptr, len)) != 0) {
436191665Sbms		    free((char *) ptr, M_TEMP);
437191665Sbms		    return error;
438191665Sbms	    }
439191665Sbms	}
440191665Sbms
441191665Sbms	uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
442191665Sbms
443191665Sbms	if (ptr)
444191665Sbms		bufprint(ptr, len);
445191665Sbms
446191665Sbms	uprintf("]}");
447191665Sbms
448191665Sbms	if (ptr)
449191665Sbms		free((char *) ptr, M_TEMP);
450191665Sbms
451191665Sbms	return 0;
452191665Sbms}
453191665Sbms
454191665Sbms
455191665Sbmsstatic void
456191665Sbmsshow_msg(str, fd, ctl, dat, flags)
457191665Sbms	const char		*str;
458191665Sbms	int			 fd;
459191665Sbms	struct svr4_strbuf	*ctl;
460191665Sbms	struct svr4_strbuf	*dat;
461229621Sjhb	int			 flags;
462191665Sbms{
463191665Sbms	struct svr4_strbuf	buf;
464191665Sbms	int error;
465191665Sbms
466191665Sbms	uprintf("%s(%d", str, fd);
467191665Sbms	if (ctl != NULL) {
468191665Sbms		if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
469191665Sbms			return;
470191665Sbms		show_strbuf(&buf);
471191665Sbms	}
472191665Sbms	else
473291045Scem		uprintf(", NULL");
474191665Sbms
475291045Scem	if (dat != NULL) {
476191665Sbms		if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
477191665Sbms			return;
478191665Sbms		show_strbuf(&buf);
479191665Sbms	}
480191665Sbms	else
481191665Sbms		uprintf(", NULL");
482191665Sbms
483278979Sglebius	uprintf(", %x);\n", flags);
484191665Sbms}
485191665Sbms
486191665Sbms#endif /* DEBUG_SVR4 */
487191665Sbms
488191665Sbms/*
489191665Sbms * We are faced with an interesting situation. On svr4 unix sockets
490191665Sbms * are really pipes. But we really have sockets, and we might as
491191665Sbms * well use them. At the point where svr4 calls TI_BIND, it has
492191665Sbms * already created a named pipe for the socket using mknod(2).
493229621Sjhb * We need to create a socket with the same name when we bind,
494191665Sbms * so we need to remove the pipe before, otherwise we'll get address
495191665Sbms * already in use. So we *carefully* remove the pipe, to avoid
496191665Sbms * using this as a random file removal tool. We use system calls
497191665Sbms * to avoid code duplication.
498191665Sbms */
499191665Sbmsstatic int
500191665Sbmsclean_pipe(td, path)
501191665Sbms	struct thread *td;
502191665Sbms	const char *path;
503191665Sbms{
504191665Sbms	struct lstat_args la;
505191665Sbms	struct unlink_args ua;
506191665Sbms	struct stat st;
507191665Sbms	int error;
508191665Sbms	caddr_t sg = stackgap_init();
509191665Sbms	size_t l = strlen(path) + 1;
510191665Sbms	void *tpath;
511191665Sbms
512191665Sbms	tpath = stackgap_alloc(&sg, l);
513191665Sbms	SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
514191665Sbms
515191665Sbms	if ((error = copyout(path, tpath, l)) != 0)
516191665Sbms		return error;
517191665Sbms
518191665Sbms	SCARG(&la, path) = tpath;
519191665Sbms
520191665Sbms	if ((error = lstat(td, &la)) != 0)
521191665Sbms		return 0;
522191665Sbms
523191665Sbms	if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
524191665Sbms		return 0;
525191665Sbms
526191665Sbms	/*
527191665Sbms	 * Make sure we are dealing with a mode 0 named pipe.
528191665Sbms	 */
529191665Sbms	if ((st.st_mode & S_IFMT) != S_IFIFO)
530191665Sbms		return 0;
531191665Sbms
532191665Sbms	if ((st.st_mode & ALLPERMS) != 0)
533191665Sbms		return 0;
534191665Sbms
535191665Sbms	SCARG(&ua, path) = SCARG(&la, path);
536191665Sbms
537191665Sbms	if ((error = unlink(td, &ua)) != 0) {
538191665Sbms		DPRINTF(("clean_pipe: unlink failed %d\n", error));
539191665Sbms		return error;
540191665Sbms	}
541191665Sbms
542191665Sbms	return 0;
543191665Sbms}
544191665Sbms
545191665Sbms
546191665Sbmsstatic void
547191665Sbmssockaddr_to_netaddr_in(sc, sain)
548191665Sbms	struct svr4_strmcmd *sc;
549191665Sbms	const struct sockaddr_in *sain;
550191665Sbms{
551191665Sbms	struct svr4_netaddr_in *na;
552191665Sbms	na = SVR4_ADDROF(sc);
553191665Sbms
554191665Sbms	na->family = sain->sin_family;
555191665Sbms	na->port = sain->sin_port;
556191665Sbms	na->addr = sain->sin_addr.s_addr;
557191665Sbms	DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
558191665Sbms		 na->addr));
559191665Sbms}
560191665Sbms
561191665Sbms
562191665Sbmsstatic void
563191665Sbmssockaddr_to_netaddr_un(sc, saun)
564191665Sbms	struct svr4_strmcmd *sc;
565191665Sbms	const struct sockaddr_un *saun;
566191665Sbms{
567191665Sbms	struct svr4_netaddr_un *na;
568191665Sbms	char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
569191665Sbms	    sizeof(*sc);
570191665Sbms	const char *src;
571191665Sbms
572191665Sbms	na = SVR4_ADDROF(sc);
573191665Sbms	na->family = saun->sun_family;
574191665Sbms	for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
575191665Sbms		if (dst == edst)
576191665Sbms			break;
577298995Spfg	DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
578191665Sbms}
579191665Sbms
580191665Sbms
581191665Sbmsstatic void
582191665Sbmsnetaddr_to_sockaddr_in(sain, sc)
583191665Sbms	struct sockaddr_in *sain;
584191665Sbms	const struct svr4_strmcmd *sc;
585191665Sbms{
586191665Sbms	const struct svr4_netaddr_in *na;
587191665Sbms
588191665Sbms
589191665Sbms	na = SVR4_C_ADDROF(sc);
590191665Sbms	memset(sain, 0, sizeof(*sain));
591191665Sbms	sain->sin_len = sizeof(*sain);
592191665Sbms	sain->sin_family = na->family;
593191665Sbms	sain->sin_port = na->port;
594191665Sbms	sain->sin_addr.s_addr = na->addr;
595191665Sbms	DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
596191665Sbms		 sain->sin_port, sain->sin_addr.s_addr));
597191665Sbms}
598191665Sbms
599191665Sbms
600191665Sbmsstatic void
601191665Sbmsnetaddr_to_sockaddr_un(saun, sc)
602191665Sbms	struct sockaddr_un *saun;
603191665Sbms	const struct svr4_strmcmd *sc;
604191665Sbms{
605191665Sbms	const struct svr4_netaddr_un *na;
606191665Sbms	char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
607191665Sbms	const char *src;
608191665Sbms
609191665Sbms	na = SVR4_C_ADDROF(sc);
610191665Sbms	memset(saun, 0, sizeof(*saun));
611191665Sbms	saun->sun_family = na->family;
612191665Sbms	for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
613191665Sbms		if (dst == edst)
614191665Sbms			break;
615191665Sbms	saun->sun_len = dst - saun->sun_path;
616191665Sbms	DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
617191665Sbms		 saun->sun_path));
618191665Sbms}
619191665Sbms
620191665Sbms
621191665Sbmsstatic void
622191665Sbmsgetparm(fp, pa)
623191665Sbms	struct file *fp;
624191665Sbms	struct svr4_si_sockparms *pa;
625191665Sbms{
626191665Sbms	struct svr4_strm *st;
627191665Sbms	struct socket *so;
628191665Sbms
629191665Sbms	st = svr4_stream_get(fp);
630191665Sbms	if (st == NULL)
631191665Sbms		return;
632191665Sbms
633191665Sbms	so = (struct socket *) fp->f_data;
634191665Sbms
635191665Sbms	pa->family = st->s_family;
636191665Sbms
637191665Sbms	switch (so->so_type) {
638191665Sbms	case SOCK_DGRAM:
639191665Sbms		pa->type = SVR4_T_CLTS;
640191665Sbms		pa->protocol = IPPROTO_UDP;
641191665Sbms		DPRINTF(("getparm(dgram)\n"));
642191665Sbms		return;
643191665Sbms
644191665Sbms	case SOCK_STREAM:
645191665Sbms	        pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
646191665Sbms		pa->protocol = IPPROTO_IP;
647191665Sbms		DPRINTF(("getparm(stream)\n"));
648191665Sbms		return;
649191665Sbms
650191665Sbms	case SOCK_RAW:
651191665Sbms		pa->type = SVR4_T_CLTS;
652191665Sbms		pa->protocol = IPPROTO_RAW;
653191665Sbms		DPRINTF(("getparm(raw)\n"));
654191665Sbms		return;
655191665Sbms
656191665Sbms	default:
657191665Sbms		pa->type = 0;
658191665Sbms		pa->protocol = 0;
659191665Sbms		DPRINTF(("getparm(type %d?)\n", so->so_type));
660191665Sbms		return;
661191665Sbms	}
662191665Sbms}
663191665Sbms
664191665Sbms
665191665Sbmsstatic int
666191665Sbmssi_ogetudata(fp, fd, ioc, td)
667191665Sbms	struct file		*fp;
668191665Sbms	int 			 fd;
669191665Sbms	struct svr4_strioctl	*ioc;
670191665Sbms	struct thread		*td;
671191665Sbms{
672191665Sbms	int error;
673191665Sbms	struct svr4_si_oudata ud;
674191665Sbms	struct svr4_si_sockparms pa;
675191665Sbms
676191665Sbms	if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
677191665Sbms		DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
678191665Sbms			 sizeof(ud), ioc->len));
679191665Sbms		return EINVAL;
680191665Sbms	}
681191665Sbms
682191665Sbms	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
683191665Sbms		return error;
684191665Sbms
685191665Sbms	getparm(fp, &pa);
686191665Sbms
687191665Sbms	switch (pa.family) {
688191665Sbms	case AF_INET:
689191665Sbms	    ud.tidusize = 16384;
690191665Sbms	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
691191665Sbms	    if (pa.type == SVR4_SOCK_STREAM)
692191665Sbms		    ud.etsdusize = 1;
693191665Sbms	    else
694191665Sbms		    ud.etsdusize = 0;
695191665Sbms	    break;
696191665Sbms
697191665Sbms	case AF_LOCAL:
698191665Sbms	    ud.tidusize = 65536;
699191665Sbms	    ud.addrsize = 128;
700191665Sbms	    ud.etsdusize = 128;
701191665Sbms	    break;
702191665Sbms
703191665Sbms	default:
704191665Sbms	    DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
705191665Sbms		     pa.family));
706191665Sbms	    return ENOSYS;
707191665Sbms	}
708191665Sbms
709191665Sbms	/* I have no idea what these should be! */
710191665Sbms	ud.optsize = 128;
711191665Sbms	ud.tsdusize = 128;
712191665Sbms
713191665Sbms	ud.servtype = pa.type;
714191665Sbms
715191665Sbms	/* XXX: Fixme */
716191665Sbms	ud.so_state = 0;
717191665Sbms	ud.so_options = 0;
718191665Sbms	return copyout(&ud, ioc->buf, ioc->len);
719191665Sbms}
720191665Sbms
721191665Sbms
722191665Sbmsstatic int
723191665Sbmssi_sockparams(fp, fd, ioc, td)
724191665Sbms	struct file		*fp;
725191665Sbms	int 			 fd;
726191665Sbms	struct svr4_strioctl	*ioc;
727191665Sbms	struct thread		*td;
728191665Sbms{
729191665Sbms	struct svr4_si_sockparms pa;
730191665Sbms
731191665Sbms	getparm(fp, &pa);
732191665Sbms	return copyout(&pa, ioc->buf, sizeof(pa));
733191665Sbms}
734191665Sbms
735191665Sbms
736191665Sbmsstatic int
737191665Sbmssi_listen(fp, fd, ioc, td)
738191665Sbms	struct file		*fp;
739191665Sbms	int 			 fd;
740191665Sbms	struct svr4_strioctl	*ioc;
741191665Sbms	struct thread		*td;
742191665Sbms{
743191665Sbms	int error;
744191665Sbms	struct svr4_strm *st = svr4_stream_get(fp);
745191665Sbms	struct svr4_strmcmd lst;
746191665Sbms	struct listen_args la;
747191665Sbms
748191665Sbms	if (st == NULL)
749191665Sbms		return EINVAL;
750191665Sbms
751191665Sbms	if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
752191665Sbms		return error;
753191665Sbms
754191665Sbms	if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
755191665Sbms		DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
756191665Sbms		return EINVAL;
757191665Sbms	}
758191665Sbms
759191665Sbms	/*
760191665Sbms	 * We are making assumptions again...
761191665Sbms	 */
762191665Sbms	SCARG(&la, s) = fd;
763191665Sbms	DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
764191665Sbms	SCARG(&la, backlog) = 5;
765191665Sbms
766191665Sbms	if ((error = listen(td, &la)) != 0) {
767191665Sbms		DPRINTF(("SI_LISTEN: listen failed %d\n", error));
768191665Sbms		return error;
769191665Sbms	}
770191665Sbms
771191665Sbms	st->s_cmd = SVR4_TI__ACCEPT_WAIT;
772191665Sbms	lst.cmd = SVR4_TI_BIND_REPLY;
773191665Sbms
774191665Sbms	switch (st->s_family) {
775191665Sbms	case AF_INET:
776191665Sbms		/* XXX: Fill the length here */
777191665Sbms		break;
778191665Sbms
779191665Sbms	case AF_LOCAL:
780191665Sbms		lst.len = 140;
781191665Sbms		lst.pad[28] = 0x00000000;	/* magic again */
782191665Sbms		lst.pad[29] = 0x00000800;	/* magic again */
783191665Sbms		lst.pad[30] = 0x80001400;	/* magic again */
784191665Sbms		break;
785191665Sbms
786191665Sbms	default:
787191665Sbms		DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
788191665Sbms		    st->s_family));
789191665Sbms		return ENOSYS;
790191665Sbms	}
791191665Sbms
792191665Sbms
793191665Sbms	if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
794191665Sbms		return error;
795191665Sbms
796191665Sbms	return 0;
797191665Sbms}
798191665Sbms
799191665Sbms
800191665Sbmsstatic int
801191665Sbmssi_getudata(fp, fd, ioc, td)
802191665Sbms	struct file		*fp;
803191665Sbms	int 			 fd;
804191665Sbms	struct svr4_strioctl	*ioc;
805191665Sbms	struct thread		*td;
806191665Sbms{
807191665Sbms	int error;
808191665Sbms	struct svr4_si_udata ud;
809191665Sbms
810191665Sbms	if (sizeof(ud) != ioc->len) {
811191665Sbms		DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
812191665Sbms			 sizeof(ud), ioc->len));
813191665Sbms		return EINVAL;
814191665Sbms	}
815191665Sbms
816191665Sbms	if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
817191665Sbms		return error;
818191665Sbms
819191665Sbms	getparm(fp, &ud.sockparms);
820191665Sbms
821191665Sbms	switch (ud.sockparms.family) {
822191665Sbms	case AF_INET:
823191665Sbms	    DPRINTF(("getudata_inet\n"));
824191665Sbms	    ud.tidusize = 16384;
825191665Sbms	    ud.tsdusize = 16384;
826191665Sbms	    ud.addrsize = sizeof(struct svr4_sockaddr_in);
827191665Sbms	    if (ud.sockparms.type == SVR4_SOCK_STREAM)
828191665Sbms		    ud.etsdusize = 1;
829191665Sbms	    else
830191665Sbms		    ud.etsdusize = 0;
831191665Sbms	    ud.optsize = 0;
832191665Sbms	    break;
833191665Sbms
834191665Sbms	case AF_LOCAL:
835191665Sbms	    DPRINTF(("getudata_local\n"));
836191665Sbms	    ud.tidusize = 65536;
837191665Sbms	    ud.tsdusize = 128;
838191665Sbms	    ud.addrsize = 128;
839191665Sbms	    ud.etsdusize = 128;
840191665Sbms	    ud.optsize = 128;
841191665Sbms	    break;
842191665Sbms
843191665Sbms	default:
844191665Sbms	    DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
845191665Sbms		     ud.sockparms.family));
846191665Sbms	    return ENOSYS;
847191665Sbms	}
848191665Sbms
849191665Sbms
850191665Sbms	ud.servtype = ud.sockparms.type;
851191665Sbms	DPRINTF(("ud.servtype = %d\n", ud.servtype));
852191665Sbms	/* XXX: Fixme */
853191665Sbms	ud.so_state = 0;
854191665Sbms	ud.so_options = 0;
855191665Sbms	return copyout(&ud, ioc->buf, sizeof(ud));
856191665Sbms}
857191665Sbms
858191665Sbms
859191665Sbmsstatic int
860191665Sbmssi_shutdown(fp, fd, ioc, td)
861191665Sbms	struct file		*fp;
862191665Sbms	int 			 fd;
863191665Sbms	struct svr4_strioctl	*ioc;
864191665Sbms	struct thread		*td;
865191665Sbms{
866191665Sbms	int error;
867191665Sbms	struct shutdown_args ap;
868191665Sbms
869191665Sbms	if (ioc->len != sizeof(SCARG(&ap, how))) {
870191665Sbms		DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
871191665Sbms			 sizeof(SCARG(&ap, how)), ioc->len));
872191665Sbms		return EINVAL;
873191665Sbms	}
874191665Sbms
875191665Sbms	if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
876191665Sbms		return error;
877191665Sbms
878191665Sbms	SCARG(&ap, s) = fd;
879191665Sbms
880191665Sbms	return shutdown(td, &ap);
881191665Sbms}
882191665Sbms
883191665Sbms
884191665Sbmsstatic int
885191665Sbmssockmod(fp, fd, ioc, td)
886191665Sbms	struct file		*fp;
887191665Sbms	int			 fd;
888191665Sbms	struct svr4_strioctl	*ioc;
889191665Sbms	struct thread		*td;
890191665Sbms{
891191665Sbms	switch (ioc->cmd) {
892191665Sbms	case SVR4_SI_OGETUDATA:
893191665Sbms		DPRINTF(("SI_OGETUDATA\n"));
894191665Sbms		return si_ogetudata(fp, fd, ioc, td);
895191665Sbms
896191665Sbms	case SVR4_SI_SHUTDOWN:
897191665Sbms		DPRINTF(("SI_SHUTDOWN\n"));
898191665Sbms		return si_shutdown(fp, fd, ioc, td);
899191665Sbms
900191665Sbms	case SVR4_SI_LISTEN:
901191665Sbms		DPRINTF(("SI_LISTEN\n"));
902191665Sbms		return si_listen(fp, fd, ioc, td);
903191665Sbms
904191665Sbms	case SVR4_SI_SETMYNAME:
905191665Sbms		DPRINTF(("SI_SETMYNAME\n"));
906191665Sbms		return 0;
907191665Sbms
908191665Sbms	case SVR4_SI_SETPEERNAME:
909191665Sbms		DPRINTF(("SI_SETPEERNAME\n"));
910191665Sbms		return 0;
911191665Sbms
912191665Sbms	case SVR4_SI_GETINTRANSIT:
913191665Sbms		DPRINTF(("SI_GETINTRANSIT\n"));
914191665Sbms		return 0;
915191665Sbms
916191665Sbms	case SVR4_SI_TCL_LINK:
917191665Sbms		DPRINTF(("SI_TCL_LINK\n"));
918191665Sbms		return 0;
919191665Sbms
920191665Sbms	case SVR4_SI_TCL_UNLINK:
921191665Sbms		DPRINTF(("SI_TCL_UNLINK\n"));
922191665Sbms		return 0;
923191665Sbms
924191665Sbms	case SVR4_SI_SOCKPARAMS:
925191665Sbms		DPRINTF(("SI_SOCKPARAMS\n"));
926191665Sbms		return si_sockparams(fp, fd, ioc, td);
927191665Sbms
928191665Sbms	case SVR4_SI_GETUDATA:
929191665Sbms		DPRINTF(("SI_GETUDATA\n"));
930191665Sbms		return si_getudata(fp, fd, ioc, td);
931191665Sbms
932191665Sbms	default:
933191665Sbms		DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
934191665Sbms		return 0;
935191665Sbms
936191665Sbms	}
937191665Sbms}
938191665Sbms
939191665Sbms
940191665Sbmsstatic int
941191665Sbmsti_getinfo(fp, fd, ioc, td)
942191665Sbms	struct file		*fp;
943191665Sbms	int 			 fd;
944191665Sbms	struct svr4_strioctl	*ioc;
945191665Sbms	struct thread		*td;
946191665Sbms{
947191665Sbms	int error;
948191665Sbms	struct svr4_infocmd info;
949191665Sbms
950191665Sbms	memset(&info, 0, sizeof(info));
951191665Sbms
952191665Sbms	if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
953191665Sbms		return error;
954191665Sbms
955191665Sbms	if (info.cmd != SVR4_TI_INFO_REQUEST)
956191665Sbms		return EINVAL;
957191665Sbms
958191665Sbms	info.cmd = SVR4_TI_INFO_REPLY;
959191665Sbms	info.tsdu = 0;
960191665Sbms	info.etsdu = 1;
961191665Sbms	info.cdata = -2;
962191665Sbms	info.ddata = -2;
963191665Sbms	info.addr = 16;
964191665Sbms	info.opt = -1;
965191665Sbms	info.tidu = 16384;
966191665Sbms	info.serv = 2;
967191665Sbms	info.current = 0;
968191665Sbms	info.provider = 2;
969191665Sbms
970191665Sbms	ioc->len = sizeof(info);
971191665Sbms	if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
972191665Sbms		return error;
973191665Sbms
974191665Sbms	return 0;
975191665Sbms}
976191665Sbms
977191665Sbms
978191665Sbmsstatic int
979191665Sbmsti_bind(fp, fd, ioc, td)
980191665Sbms	struct file		*fp;
981191665Sbms	int 			 fd;
982191665Sbms	struct svr4_strioctl	*ioc;
983191665Sbms	struct thread		*td;
984191665Sbms{
985191665Sbms	int error;
986191665Sbms	struct svr4_strm *st = svr4_stream_get(fp);
987191665Sbms	struct sockaddr_in sain;
988191665Sbms	struct sockaddr_un saun;
989191665Sbms	caddr_t sg;
990191665Sbms	void *skp, *sup = NULL;
991191665Sbms	int sasize;
992191665Sbms	struct svr4_strmcmd bnd;
993191665Sbms	struct bind_args ba;
994191665Sbms
995191665Sbms	if (st == NULL) {
996191665Sbms		DPRINTF(("ti_bind: bad file descriptor\n"));
997191665Sbms		return EINVAL;
998191665Sbms	}
999191665Sbms
1000191665Sbms	if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
1001191665Sbms		return error;
1002191665Sbms
1003191665Sbms	if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
1004191665Sbms		DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
1005191665Sbms		return EINVAL;
1006191665Sbms	}
1007191665Sbms
1008191665Sbms	switch (st->s_family) {
1009191665Sbms	case AF_INET:
1010191665Sbms		skp = &sain;
1011191665Sbms		sasize = sizeof(sain);
1012191665Sbms
1013191665Sbms		if (bnd.offs == 0)
1014191665Sbms			goto reply;
1015191665Sbms
1016191665Sbms		netaddr_to_sockaddr_in(&sain, &bnd);
1017191665Sbms
1018191665Sbms		DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
1019191665Sbms			 sain.sin_family, sain.sin_port,
1020191665Sbms			 sain.sin_addr.s_addr));
1021191665Sbms		break;
1022191665Sbms
1023191665Sbms	case AF_LOCAL:
1024191665Sbms		skp = &saun;
1025191665Sbms		sasize = sizeof(saun);
1026191665Sbms		if (bnd.offs == 0)
1027191665Sbms			goto reply;
1028191665Sbms
1029191665Sbms		netaddr_to_sockaddr_un(&saun, &bnd);
1030191665Sbms
1031191665Sbms		if (saun.sun_path[0] == '\0')
1032191665Sbms			goto reply;
1033191665Sbms
1034191665Sbms		DPRINTF(("TI_BIND: fam %d, path %s\n",
1035191665Sbms			 saun.sun_family, saun.sun_path));
1036191665Sbms
1037191665Sbms		if ((error = clean_pipe(td, saun.sun_path)) != 0)
1038191665Sbms			return error;
1039191665Sbms
1040191665Sbms		bnd.pad[28] = 0x00001000;	/* magic again */
1041191665Sbms		break;
1042191665Sbms
1043191665Sbms	default:
1044191665Sbms		DPRINTF(("TI_BIND: Unsupported address family %d\n",
1045191665Sbms			 st->s_family));
1046191665Sbms		return ENOSYS;
1047191665Sbms	}
1048191665Sbms
1049191665Sbms	sg = stackgap_init();
1050191665Sbms	sup = stackgap_alloc(&sg, sasize);
1051191665Sbms
1052191665Sbms	if ((error = copyout(skp, sup, sasize)) != 0)
1053191665Sbms		return error;
1054191665Sbms
1055191665Sbms	SCARG(&ba, s) = fd;
1056191665Sbms	DPRINTF(("TI_BIND: fileno %d\n", fd));
1057191665Sbms	SCARG(&ba, name) = (void *) sup;
1058191665Sbms	SCARG(&ba, namelen) = sasize;
1059191665Sbms
1060191665Sbms	if ((error = bind(td, &ba)) != 0) {
1061191665Sbms		DPRINTF(("TI_BIND: bind failed %d\n", error));
1062191665Sbms		return error;
1063191665Sbms	}
1064191665Sbms
1065191665Sbmsreply:
1066191665Sbms	if (sup == NULL) {
1067191665Sbms		memset(&bnd, 0, sizeof(bnd));
1068191665Sbms		bnd.len = sasize + 4;
1069191665Sbms		bnd.offs = 0x10;	/* XXX */
1070191665Sbms	}
1071191665Sbms
1072191665Sbms	bnd.cmd = SVR4_TI_BIND_REPLY;
1073191665Sbms
1074191665Sbms	if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
1075191665Sbms		return error;
1076191665Sbms
1077273857Sae	return 0;
1078278979Sglebius}
1079191665Sbms
1080191665Sbms
1081191665Sbmsstatic int
1082191665Sbmstimod(fp, fd, ioc, td)
1083191665Sbms	struct file		*fp;
1084191665Sbms	int			 fd;
1085191665Sbms	struct svr4_strioctl	*ioc;
1086191665Sbms	struct thread		*td;
1087191665Sbms{
1088191665Sbms	switch (ioc->cmd) {
1089191665Sbms	case SVR4_TI_GETINFO:
1090191665Sbms		DPRINTF(("TI_GETINFO\n"));
1091191665Sbms		return ti_getinfo(fp, fd, ioc, td);
1092191665Sbms
1093191665Sbms	case SVR4_TI_OPTMGMT:
1094191665Sbms		DPRINTF(("TI_OPTMGMT\n"));
1095191665Sbms		return 0;
1096191665Sbms
1097191665Sbms	case SVR4_TI_BIND:
1098191665Sbms		DPRINTF(("TI_BIND\n"));
1099191665Sbms		return ti_bind(fp, fd, ioc, td);
1100191665Sbms
1101191665Sbms	case SVR4_TI_UNBIND:
1102191665Sbms		DPRINTF(("TI_UNBIND\n"));
1103191665Sbms		return 0;
1104191665Sbms
1105191665Sbms	default:
1106191665Sbms		DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
1107191665Sbms		return 0;
1108191665Sbms	}
1109191665Sbms}
1110191665Sbms
1111191665Sbms
1112191665Sbmsint
1113191665Sbmssvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
1114191665Sbms	struct file *fp;
1115191665Sbms	struct thread *td;
1116191665Sbms	register_t *retval;
1117191665Sbms	int fd;
1118191665Sbms	u_long cmd;
1119191665Sbms	caddr_t dat;
1120191665Sbms{
1121191665Sbms	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
1122191665Sbms	struct svr4_strm *st = svr4_stream_get(fp);
1123191665Sbms	int error;
1124191665Sbms	void *skp, *sup;
1125191665Sbms	struct sockaddr_in sain;
1126191665Sbms	struct sockaddr_un saun;
1127191665Sbms	struct svr4_strmcmd sc;
1128191665Sbms	int sasize;
1129191665Sbms	caddr_t sg;
1130191665Sbms	int *lenp;
1131191665Sbms
1132191665Sbms	DPRINTF(("svr4_stream_ti_ioctl\n"));
1133191665Sbms
1134191665Sbms	if (st == NULL)
1135191665Sbms		return EINVAL;
1136191665Sbms
1137191665Sbms	sc.offs = 0x10;
1138191665Sbms
1139191665Sbms	if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
1140191665Sbms		DPRINTF(("ti_ioctl: error copying in strbuf\n"));
1141191665Sbms		return error;
1142191665Sbms	}
1143191665Sbms
1144191665Sbms	switch (st->s_family) {
1145191665Sbms	case AF_INET:
1146191665Sbms		skp = &sain;
1147191665Sbms		sasize = sizeof(sain);
1148191665Sbms		break;
1149191665Sbms
1150191665Sbms	case AF_LOCAL:
1151191665Sbms		skp = &saun;
1152191665Sbms		sasize = sizeof(saun);
1153191665Sbms		break;
1154191665Sbms
1155191665Sbms	default:
1156191665Sbms		DPRINTF(("ti_ioctl: Unsupported address family %d\n",
1157191665Sbms			 st->s_family));
1158191665Sbms		return ENOSYS;
1159191665Sbms	}
1160191665Sbms
1161191665Sbms	sg = stackgap_init();
1162191665Sbms	sup = stackgap_alloc(&sg, sasize);
1163191665Sbms	lenp = stackgap_alloc(&sg, sizeof(*lenp));
1164191665Sbms
1165191665Sbms	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
1166191665Sbms		DPRINTF(("ti_ioctl: error copying out lenp\n"));
1167191665Sbms		return error;
1168191665Sbms	}
1169191665Sbms
1170192923Sbms	switch (cmd) {
1171192923Sbms	case SVR4_TI_GETMYNAME:
1172192923Sbms		DPRINTF(("TI_GETMYNAME\n"));
1173192923Sbms		{
1174192923Sbms			struct getsockname_args ap;
1175192923Sbms			SCARG(&ap, fdes) = fd;
1176192923Sbms			SCARG(&ap, asa) = sup;
1177192923Sbms			SCARG(&ap, alen) = lenp;
1178192923Sbms			if ((error = getsockname(td, &ap)) != 0) {
1179192923Sbms				DPRINTF(("ti_ioctl: getsockname error\n"));
1180192923Sbms				return error;
1181192923Sbms			}
1182192923Sbms		}
1183192923Sbms		break;
1184191665Sbms
1185191665Sbms	case SVR4_TI_GETPEERNAME:
1186191665Sbms		DPRINTF(("TI_GETPEERNAME\n"));
1187260511Sae		{
1188191665Sbms			struct getpeername_args ap;
1189191665Sbms			SCARG(&ap, fdes) = fd;
1190191665Sbms			SCARG(&ap, asa) = sup;
1191191665Sbms			SCARG(&ap, alen) = lenp;
1192191665Sbms			if ((error = getpeername(td, &ap)) != 0) {
1193191665Sbms				DPRINTF(("ti_ioctl: getpeername error\n"));
1194191665Sbms				return error;
1195191665Sbms			}
1196191665Sbms		}
1197191665Sbms		break;
1198191665Sbms
1199191665Sbms	case SVR4_TI_SETMYNAME:
1200191665Sbms		DPRINTF(("TI_SETMYNAME\n"));
1201191665Sbms		return 0;
1202191665Sbms
1203191665Sbms	case SVR4_TI_SETPEERNAME:
1204191665Sbms		DPRINTF(("TI_SETPEERNAME\n"));
1205191665Sbms		return 0;
1206191665Sbms	default:
1207191665Sbms		DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
1208191665Sbms		return ENOSYS;
1209191665Sbms	}
1210191665Sbms
1211191665Sbms	if ((error = copyin(sup, skp, sasize)) != 0) {
1212191665Sbms		DPRINTF(("ti_ioctl: error copying in socket data\n"));
1213191665Sbms		return error;
1214191665Sbms	}
1215191665Sbms
1216191665Sbms	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
1217191665Sbms		DPRINTF(("ti_ioctl: error copying in socket size\n"));
1218191665Sbms		return error;
1219191665Sbms	}
1220191665Sbms
1221191665Sbms	switch (st->s_family) {
1222191665Sbms	case AF_INET:
1223191665Sbms		sockaddr_to_netaddr_in(&sc, &sain);
1224191665Sbms		skb.len = sasize;
1225191665Sbms		break;
1226191665Sbms
1227191665Sbms	case AF_LOCAL:
1228191665Sbms		sockaddr_to_netaddr_un(&sc, &saun);
1229191665Sbms		skb.len = sasize + 4;
1230191665Sbms		break;
1231191665Sbms
1232191665Sbms	default:
1233191665Sbms		return ENOSYS;
1234191665Sbms	}
1235191665Sbms
1236191665Sbms
1237191665Sbms	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
1238191665Sbms		DPRINTF(("ti_ioctl: error copying out socket data\n"));
1239191665Sbms		return error;
1240191665Sbms	}
1241191665Sbms
1242191665Sbms
1243191665Sbms	if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
1244191665Sbms		DPRINTF(("ti_ioctl: error copying out strbuf\n"));
1245191665Sbms		return error;
1246191665Sbms	}
1247191665Sbms
1248191665Sbms	return error;
1249191665Sbms}
1250191665Sbms
1251191665Sbms
1252191665Sbms
1253191665Sbms
1254191665Sbmsstatic int
1255191665Sbmsi_nread(fp, td, retval, fd, cmd, dat)
1256191665Sbms	struct file *fp;
1257191665Sbms	struct thread *td;
1258191665Sbms	register_t *retval;
1259191665Sbms	int fd;
1260191665Sbms	u_long cmd;
1261191665Sbms	caddr_t dat;
1262191665Sbms{
1263191665Sbms	int error;
1264191665Sbms	int nread = 0;
1265191665Sbms
1266191665Sbms	/*
1267191665Sbms	 * We are supposed to return the message length in nread, and the
1268191665Sbms	 * number of messages in retval. We don't have the notion of number
1269191665Sbms	 * of stream messages, so we just find out if we have any bytes waiting
1270191665Sbms	 * for us, and if we do, then we assume that we have at least one
1271191665Sbms	 * message waiting for us.
1272191665Sbms	 */
1273191665Sbms	if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0)
1274191665Sbms		return error;
1275191665Sbms
1276191665Sbms	if (nread != 0)
1277191665Sbms		*retval = 1;
1278260511Sae	else
1279191665Sbms		*retval = 0;
1280191665Sbms
1281191665Sbms	return copyout(&nread, dat, sizeof(nread));
1282191665Sbms}
1283191665Sbms
1284191665Sbmsstatic int
1285191665Sbmsi_fdinsert(fp, td, retval, fd, cmd, dat)
1286191665Sbms	struct file *fp;
1287191665Sbms	struct thread *td;
1288191665Sbms	register_t *retval;
1289191665Sbms	int fd;
1290191665Sbms	u_long cmd;
1291191665Sbms	caddr_t dat;
1292191665Sbms{
1293191665Sbms	/*
1294191665Sbms	 * Major hack again here. We assume that we are using this to
1295191665Sbms	 * implement accept(2). If that is the case, we have already
1296191665Sbms	 * called accept, and we have stored the file descriptor in
1297191665Sbms	 * afd. We find the file descriptor that the code wants to use
1298191665Sbms	 * in fd insert, and then we dup2() our accepted file descriptor
1299191665Sbms	 * to it.
1300191665Sbms	 */
1301191665Sbms	int error;
1302191665Sbms	struct svr4_strm *st = svr4_stream_get(fp);
1303191665Sbms	struct svr4_strfdinsert fdi;
1304191665Sbms	struct dup2_args d2p;
1305191665Sbms	struct close_args clp;
1306191665Sbms
1307191665Sbms	if (st == NULL) {
1308191665Sbms		DPRINTF(("fdinsert: bad file type\n"));
1309191665Sbms		return EINVAL;
1310191665Sbms	}
1311191665Sbms
1312191665Sbms	if (st->s_afd == -1) {
1313191665Sbms		DPRINTF(("fdinsert: accept fd not found\n"));
1314191665Sbms		return ENOENT;
1315191665Sbms	}
1316191665Sbms
1317191665Sbms	if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
1318191665Sbms		DPRINTF(("fdinsert: copyin failed %d\n", error));
1319191665Sbms		return error;
1320191665Sbms	}
1321191665Sbms
1322191665Sbms	SCARG(&d2p, from) = st->s_afd;
1323191665Sbms	SCARG(&d2p, to) = fdi.fd;
1324191665Sbms
1325191665Sbms	if ((error = dup2(td, &d2p)) != 0) {
1326191665Sbms		DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
1327191665Sbms		    st->s_afd, fdi.fd, error));
1328191665Sbms		return error;
1329191665Sbms	}
1330191665Sbms
1331191665Sbms	SCARG(&clp, fd) = st->s_afd;
1332191665Sbms
1333191665Sbms	if ((error = close(td, &clp)) != 0) {
1334191665Sbms		DPRINTF(("fdinsert: close(%d) failed %d\n",
1335191665Sbms		    st->s_afd, error));
1336191665Sbms		return error;
1337191665Sbms	}
1338191665Sbms
1339191665Sbms	st->s_afd = -1;
1340191665Sbms
1341191665Sbms	*retval = 0;
1342191665Sbms	return 0;
1343191665Sbms}
1344191665Sbms
1345191665Sbms
1346191665Sbmsstatic int
1347191665Sbms_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
1348191665Sbms	struct file *fp;
1349191665Sbms	struct thread *td;
1350191665Sbms	register_t *retval;
1351191665Sbms	int fd;
1352191665Sbms	u_long cmd;
1353191665Sbms	caddr_t dat;
1354191665Sbms{
1355191665Sbms	struct mkfifo_args ap;
1356191665Sbms
1357191665Sbms	/*
1358191665Sbms	 * This is a supposed to be a kernel and library only ioctl.
1359191665Sbms	 * It gets called before ti_bind, when we have a unix
1360191665Sbms	 * socket, to physically create the socket transport and
1361191665Sbms	 * ``reserve'' it. I don't know how this get reserved inside
1362191665Sbms	 * the kernel, but we are going to create it nevertheless.
1363191665Sbms	 */
1364191665Sbms	SCARG(&ap, path) = dat;
1365191665Sbms	SCARG(&ap, mode) = S_IFIFO;
1366191665Sbms
1367191665Sbms	return mkfifo(td, &ap);
1368191665Sbms}
1369191665Sbms
1370191665Sbmsstatic int
1371191665Sbms_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
1372191665Sbms	struct file *fp;
1373191665Sbms	struct thread *td;
1374191665Sbms	register_t *retval;
1375191665Sbms	int fd;
1376191665Sbms	u_long cmd;
1377191665Sbms	caddr_t dat;
1378191665Sbms{
1379191665Sbms	struct unlink_args ap;
1380191665Sbms
1381191665Sbms	/*
1382191665Sbms	 * This is a supposed to be a kernel and library only ioctl.
1383191665Sbms	 * I guess it is supposed to release the socket.
1384192923Sbms	 */
1385192923Sbms	SCARG(&ap, path) = dat;
1386191665Sbms
1387191665Sbms	return unlink(td, &ap);
1388191665Sbms}
1389191665Sbms
1390191665Sbmsstatic int
1391191665Sbmsi_str(fp, td, retval, fd, cmd, dat)
1392191665Sbms	struct file *fp;
1393191665Sbms	struct thread *td;
1394191665Sbms	register_t *retval;
1395191665Sbms	int fd;
1396191665Sbms	u_long cmd;
1397191665Sbms	caddr_t dat;
1398191665Sbms{
1399191665Sbms	int			 error;
1400191665Sbms	struct svr4_strioctl	 ioc;
1401191665Sbms
1402191665Sbms	if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
1403191665Sbms		return error;
1404191665Sbms
1405191665Sbms#ifdef DEBUG_SVR4
1406191665Sbms	if ((error = show_ioc(">", &ioc)) != 0)
1407191665Sbms		return error;
1408191665Sbms#endif /* DEBUG_SVR4 */
1409191665Sbms
1410191665Sbms	switch (ioc.cmd & 0xff00) {
1411191665Sbms	case SVR4_SIMOD:
1412191665Sbms		if ((error = sockmod(fp, fd, &ioc, td)) != 0)
1413191665Sbms			return error;
1414191665Sbms		break;
1415191665Sbms
1416191665Sbms	case SVR4_TIMOD:
1417191665Sbms		if ((error = timod(fp, fd, &ioc, td)) != 0)
1418191665Sbms			return error;
1419191665Sbms		break;
1420191665Sbms
1421191665Sbms	default:
1422191665Sbms		DPRINTF(("Unimplemented module %c %ld\n",
1423191665Sbms			 (char) (cmd >> 8), cmd & 0xff));
1424191665Sbms		return 0;
1425191665Sbms	}
1426191665Sbms
1427191665Sbms#ifdef DEBUG_SVR4
1428191665Sbms	if ((error = show_ioc("<", &ioc)) != 0)
1429191665Sbms		return error;
1430191665Sbms#endif /* DEBUG_SVR4 */
1431191665Sbms	return copyout(&ioc, dat, sizeof(ioc));
1432191665Sbms}
1433191665Sbms
1434191665Sbmsstatic int
1435191665Sbmsi_setsig(fp, td, retval, fd, cmd, dat)
1436191665Sbms	struct file *fp;
1437191665Sbms	struct thread *td;
1438191665Sbms	register_t *retval;
1439191665Sbms	int fd;
1440191665Sbms	u_long cmd;
1441191665Sbms	caddr_t dat;
1442191665Sbms{
1443191665Sbms	/*
1444191665Sbms	 * This is the best we can do for now; we cannot generate
1445191665Sbms	 * signals only for specific events so the signal mask gets
1446191665Sbms	 * ignored; we save it just to pass it to a possible I_GETSIG...
1447191665Sbms	 *
1448191665Sbms	 * We alse have to fix the O_ASYNC fcntl bit, so the
1449191665Sbms	 * process will get SIGPOLLs.
1450191665Sbms	 */
1451191665Sbms	struct fcntl_args fa;
1452191665Sbms	int error;
1453264364Sae	register_t oflags, flags;
1454191665Sbms	struct svr4_strm *st = svr4_stream_get(fp);
1455264364Sae
1456264364Sae	if (st == NULL) {
1457264364Sae		DPRINTF(("i_setsig: bad file descriptor\n"));
1458264364Sae		return EINVAL;
1459264364Sae	}
1460191665Sbms	/* get old status flags */
1461191665Sbms	SCARG(&fa, fd) = fd;
1462191665Sbms	SCARG(&fa, cmd) = F_GETFL;
1463191665Sbms	if ((error = fcntl(td, &fa)) != 0)
1464191665Sbms		return error;
1465191665Sbms
1466191665Sbms	oflags = td->td_retval[0];
1467191665Sbms
1468191665Sbms	/* update the flags */
1469191665Sbms	if (dat != NULL) {
1470191665Sbms		int mask;
1471191665Sbms
1472191665Sbms		flags = oflags | O_ASYNC;
1473191665Sbms		if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
1474191665Sbms			  DPRINTF(("i_setsig: bad eventmask pointer\n"));
1475191665Sbms			  return error;
1476191665Sbms		}
1477191665Sbms		if (mask & SVR4_S_ALLMASK) {
1478191665Sbms			  DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
1479191665Sbms			  return EINVAL;
1480191665Sbms		}
1481191665Sbms		st->s_eventmask = mask;
1482191665Sbms	}
1483191665Sbms	else {
1484191665Sbms		flags = oflags & ~O_ASYNC;
1485191665Sbms		st->s_eventmask = 0;
1486191665Sbms	}
1487191665Sbms
1488191665Sbms	/* set the new flags, if changed */
1489191665Sbms	if (flags != oflags) {
1490191665Sbms		SCARG(&fa, cmd) = F_SETFL;
1491191665Sbms		SCARG(&fa, arg) = (long) flags;
1492191665Sbms		if ((error = fcntl(td, &fa)) != 0)
1493191665Sbms			  return error;
1494191665Sbms		flags = td->td_retval[0];
1495191665Sbms	}
1496191665Sbms
1497191665Sbms	/* set up SIGIO receiver if needed */
1498191665Sbms	if (dat != NULL) {
1499191665Sbms		SCARG(&fa, cmd) = F_SETOWN;
1500191665Sbms		SCARG(&fa, arg) = (long) td->td_proc->p_pid;
1501191665Sbms		return fcntl(td, &fa);
1502191665Sbms	}
1503191665Sbms	return 0;
1504191665Sbms}
1505191665Sbms
1506191665Sbmsstatic int
1507191665Sbmsi_getsig(fp, td, retval, fd, cmd, dat)
1508191665Sbms	struct file *fp;
1509191665Sbms	struct thread *td;
1510191665Sbms	register_t *retval;
1511191665Sbms	int fd;
1512191665Sbms	u_long cmd;
1513191665Sbms	caddr_t dat;
1514191665Sbms{
1515191665Sbms	int error;
1516191665Sbms
1517191665Sbms	if (dat != NULL) {
1518191665Sbms		struct svr4_strm *st = svr4_stream_get(fp);
1519191665Sbms
1520191665Sbms		if (st == NULL) {
1521191665Sbms			DPRINTF(("i_getsig: bad file descriptor\n"));
1522191665Sbms			return EINVAL;
1523191665Sbms		}
1524191665Sbms		if ((error = copyout(&st->s_eventmask, dat,
1525191665Sbms				     sizeof(st->s_eventmask))) != 0) {
1526191665Sbms			DPRINTF(("i_getsig: bad eventmask pointer\n"));
1527191665Sbms			return error;
1528191665Sbms		}
1529191665Sbms	}
1530191665Sbms	return 0;
1531191665Sbms}
1532191665Sbms
1533191665Sbmsint
1534191665Sbmssvr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
1535191665Sbms	struct file *fp;
1536191665Sbms	struct thread *td;
1537191665Sbms	register_t *retval;
1538191665Sbms	int fd;
1539191665Sbms	u_long cmd;
1540191665Sbms	caddr_t dat;
1541191665Sbms{
1542191665Sbms	*retval = 0;
1543191665Sbms
1544191665Sbms	/*
1545191665Sbms	 * All the following stuff assumes "sockmod" is pushed...
1546191665Sbms	 */
1547191665Sbms	switch (cmd) {
1548191665Sbms	case SVR4_I_NREAD:
1549191665Sbms		DPRINTF(("I_NREAD\n"));
1550191665Sbms		return i_nread(fp, td, retval, fd, cmd, dat);
1551191665Sbms
1552191665Sbms	case SVR4_I_PUSH:
1553191665Sbms		DPRINTF(("I_PUSH %p\n", dat));
1554191665Sbms#if defined(DEBUG_SVR4)
1555191665Sbms		show_strbuf((struct svr4_strbuf *)dat);
1556191665Sbms#endif
1557191665Sbms		return 0;
1558191665Sbms
1559191665Sbms	case SVR4_I_POP:
1560191665Sbms		DPRINTF(("I_POP\n"));
1561191665Sbms		return 0;
1562191665Sbms
1563191665Sbms	case SVR4_I_LOOK:
1564191665Sbms		DPRINTF(("I_LOOK\n"));
1565191665Sbms		return 0;
1566191665Sbms
1567191665Sbms	case SVR4_I_FLUSH:
1568191665Sbms		DPRINTF(("I_FLUSH\n"));
1569191665Sbms		return 0;
1570191665Sbms
1571191665Sbms	case SVR4_I_SRDOPT:
1572191665Sbms		DPRINTF(("I_SRDOPT\n"));
1573191665Sbms		return 0;
1574191665Sbms
1575191665Sbms	case SVR4_I_GRDOPT:
1576191665Sbms		DPRINTF(("I_GRDOPT\n"));
1577191665Sbms		return 0;
1578191665Sbms
1579191665Sbms	case SVR4_I_STR:
1580191665Sbms		DPRINTF(("I_STR\n"));
1581191665Sbms		return i_str(fp, td, retval, fd, cmd, dat);
1582191665Sbms
1583191665Sbms	case SVR4_I_SETSIG:
1584191665Sbms		DPRINTF(("I_SETSIG\n"));
1585191665Sbms		return i_setsig(fp, td, retval, fd, cmd, dat);
1586191665Sbms
1587191665Sbms	case SVR4_I_GETSIG:
1588191665Sbms	        DPRINTF(("I_GETSIG\n"));
1589192923Sbms		return i_getsig(fp, td, retval, fd, cmd, dat);
1590192923Sbms
1591191665Sbms	case SVR4_I_FIND:
1592191665Sbms		DPRINTF(("I_FIND\n"));
1593192923Sbms		/*
1594192923Sbms		 * Here we are not pushing modules really, we just
1595192923Sbms		 * pretend all are present
1596192923Sbms		 */
1597192923Sbms		*retval = 0;
1598192923Sbms		return 0;
1599191665Sbms
1600191665Sbms	case SVR4_I_LINK:
1601192923Sbms		DPRINTF(("I_LINK\n"));
1602192923Sbms		return 0;
1603191665Sbms
1604191665Sbms	case SVR4_I_UNLINK:
1605191665Sbms		DPRINTF(("I_UNLINK\n"));
1606191665Sbms		return 0;
1607191665Sbms
1608191665Sbms	case SVR4_I_ERECVFD:
1609191665Sbms		DPRINTF(("I_ERECVFD\n"));
1610191665Sbms		return 0;
1611191665Sbms
1612191665Sbms	case SVR4_I_PEEK:
1613191665Sbms		DPRINTF(("I_PEEK\n"));
1614191665Sbms		return 0;
1615191665Sbms
1616191665Sbms	case SVR4_I_FDINSERT:
1617191665Sbms		DPRINTF(("I_FDINSERT\n"));
1618191665Sbms		return i_fdinsert(fp, td, retval, fd, cmd, dat);
1619191665Sbms
1620191665Sbms	case SVR4_I_SENDFD:
1621191665Sbms		DPRINTF(("I_SENDFD\n"));
1622191665Sbms		return 0;
1623191665Sbms
1624191665Sbms	case SVR4_I_RECVFD:
1625191665Sbms		DPRINTF(("I_RECVFD\n"));
1626191665Sbms		return 0;
1627191665Sbms
1628191665Sbms	case SVR4_I_SWROPT:
1629191665Sbms		DPRINTF(("I_SWROPT\n"));
1630191665Sbms		return 0;
1631191665Sbms
1632254629Sdelphij	case SVR4_I_GWROPT:
1633254629Sdelphij		DPRINTF(("I_GWROPT\n"));
1634191665Sbms		return 0;
1635191665Sbms
1636191665Sbms	case SVR4_I_LIST:
1637191665Sbms		DPRINTF(("I_LIST\n"));
1638191665Sbms		return 0;
1639191665Sbms
1640191665Sbms	case SVR4_I_PLINK:
1641191665Sbms		DPRINTF(("I_PLINK\n"));
1642191665Sbms		return 0;
1643191665Sbms
1644191665Sbms	case SVR4_I_PUNLINK:
1645191665Sbms		DPRINTF(("I_PUNLINK\n"));
1646191665Sbms		return 0;
1647191665Sbms
1648191665Sbms	case SVR4_I_SETEV:
1649191665Sbms		DPRINTF(("I_SETEV\n"));
1650191665Sbms		return 0;
1651191665Sbms
1652191665Sbms	case SVR4_I_GETEV:
1653191665Sbms		DPRINTF(("I_GETEV\n"));
1654191665Sbms		return 0;
1655191665Sbms
1656191665Sbms	case SVR4_I_STREV:
1657191665Sbms		DPRINTF(("I_STREV\n"));
1658191665Sbms		return 0;
1659191665Sbms
1660191665Sbms	case SVR4_I_UNSTREV:
1661191665Sbms		DPRINTF(("I_UNSTREV\n"));
1662191665Sbms		return 0;
1663191665Sbms
1664191665Sbms	case SVR4_I_FLUSHBAND:
1665191665Sbms		DPRINTF(("I_FLUSHBAND\n"));
1666191665Sbms		return 0;
1667191665Sbms
1668191665Sbms	case SVR4_I_CKBAND:
1669191665Sbms		DPRINTF(("I_CKBAND\n"));
1670191665Sbms		return 0;
1671191665Sbms
1672191665Sbms	case SVR4_I_GETBAND:
1673191665Sbms		DPRINTF(("I_GETBANK\n"));
1674191665Sbms		return 0;
1675191665Sbms
1676191665Sbms	case SVR4_I_ATMARK:
1677191665Sbms		DPRINTF(("I_ATMARK\n"));
1678191665Sbms		return 0;
1679191665Sbms
1680191665Sbms	case SVR4_I_SETCLTIME:
1681191665Sbms		DPRINTF(("I_SETCLTIME\n"));
1682191665Sbms		return 0;
1683191665Sbms
1684191665Sbms	case SVR4_I_GETCLTIME:
1685191665Sbms		DPRINTF(("I_GETCLTIME\n"));
1686191665Sbms		return 0;
1687191665Sbms
1688191665Sbms	case SVR4_I_CANPUT:
1689191665Sbms		DPRINTF(("I_CANPUT\n"));
1690191672Sbms		return 0;
1691191672Sbms
1692191672Sbms	case SVR4__I_BIND_RSVD:
1693191665Sbms		DPRINTF(("_I_BIND_RSVD\n"));
1694191665Sbms		return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
1695191672Sbms
1696191665Sbms	case SVR4__I_RELE_RSVD:
1697191665Sbms		DPRINTF(("_I_RELE_RSVD\n"));
1698191665Sbms		return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
1699191665Sbms
1700191665Sbms	default:
1701191665Sbms		DPRINTF(("unimpl cmd = %lx\n", cmd));
1702191665Sbms		break;
1703191665Sbms	}
1704191665Sbms
1705191665Sbms	return 0;
1706191665Sbms}
1707191665Sbms
1708191665Sbms
1709191665Sbms
1710191672Sbmsint
1711191665Sbmssvr4_sys_putmsg(td, uap)
1712191665Sbms	register struct thread *td;
1713191672Sbms	struct svr4_sys_putmsg_args *uap;
1714191665Sbms{
1715191665Sbms	struct file     *fp;
1716191672Sbms	int error;
1717191665Sbms
1718191665Sbms	if ((error = fget(td, uap->fd, &fp)) != 0) {
1719191665Sbms#ifdef DEBUG_SVR4
1720191672Sbms	        uprintf("putmsg: bad fp\n");
1721191672Sbms#endif
1722191665Sbms		return EBADF;
1723227481Sbz	}
1724191665Sbms	error = svr4_do_putmsg(td, uap, fp);
1725191665Sbms	fdrop(fp, td);
1726191665Sbms	return (error);
1727191665Sbms}
1728191665Sbms
1729191672Sbmsstatic int
1730191672Sbmssvr4_do_putmsg(td, uap, fp)
1731191665Sbms	struct thread *td;
1732191672Sbms	struct svr4_sys_putmsg_args *uap;
1733191665Sbms	struct file	*fp;
1734191665Sbms{
1735191665Sbms	struct svr4_strbuf dat, ctl;
1736191665Sbms	struct svr4_strmcmd sc;
1737191665Sbms	struct sockaddr_in sain;
1738191672Sbms	struct sockaddr_un saun;
1739191665Sbms	void *skp, *sup;
1740191665Sbms	int sasize, *retval;
1741191665Sbms	struct svr4_strm *st;
1742191665Sbms	int error;
1743191665Sbms	caddr_t sg;
1744191665Sbms
1745191665Sbms	retval = td->td_retval;
1746191665Sbms
1747191665Sbms#ifdef DEBUG_SVR4
1748191665Sbms	show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
1749191665Sbms		 SCARG(uap, dat), SCARG(uap, flags));
1750191665Sbms#endif /* DEBUG_SVR4 */
1751191665Sbms
1752191665Sbms	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1753191665Sbms
1754191665Sbms	if (SCARG(uap, ctl) != NULL) {
1755191665Sbms	  if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
1756191665Sbms#ifdef DEBUG_SVR4
1757191665Sbms	    uprintf("putmsg: copyin(): %d\n", error);
1758191672Sbms#endif
1759191672Sbms	    return error;
1760191672Sbms	  }
1761191672Sbms	}
1762191672Sbms	else
1763191672Sbms		ctl.len = -1;
1764191672Sbms
1765191672Sbms	if (SCARG(uap, dat) != NULL) {
1766191672Sbms	  if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
1767191672Sbms#ifdef DEBUG_SVR4
1768191672Sbms	    uprintf("putmsg: copyin(): %d (2)\n", error);
1769191672Sbms#endif
1770191672Sbms	    return error;
1771191672Sbms	  }
1772191672Sbms	}
1773231852Sbz	else
1774191672Sbms		dat.len = -1;
1775191672Sbms
1776292015Smelifaro	/*
1777292015Smelifaro	 * Only for sockets for now.
1778292015Smelifaro	 */
1779292015Smelifaro	if ((st = svr4_stream_get(fp)) == NULL) {
1780191672Sbms		DPRINTF(("putmsg: bad file type\n"));
1781191672Sbms		return EINVAL;
1782191672Sbms	}
1783191672Sbms
1784191672Sbms	if (ctl.len > sizeof(sc)) {
1785191672Sbms		DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
1786292015Smelifaro			 sizeof(struct svr4_strmcmd)));
1787292015Smelifaro		return EINVAL;
1788292015Smelifaro	}
1789292015Smelifaro
1790191672Sbms	if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
1791292015Smelifaro		return error;
1792191672Sbms
1793191672Sbms	switch (st->s_family) {
1794191672Sbms	case AF_INET:
1795191665Sbms	        if (sc.len != sizeof(sain)) {
1796191672Sbms		        if (sc.cmd == SVR4_TI_DATA_REQUEST) {
1797191672Sbms			        struct write_args wa;
1798191672Sbms
1799191665Sbms				/* Solaris seems to use sc.cmd = 3 to
1800191665Sbms				 * send "expedited" data.  telnet uses
1801191665Sbms				 * this for options processing, sending EOF,
1802191665Sbms				 * etc.  I'm sure other things use it too.
1803191665Sbms				 * I don't have any documentation
1804191665Sbms				 * on it, so I'm making a guess that this
1805191665Sbms				 * is how it works. newton@atdot.dotat.org XXX
1806191665Sbms				 */
1807191665Sbms				DPRINTF(("sending expedited data ??\n"));
1808191665Sbms				SCARG(&wa, fd) = SCARG(uap, fd);
1809191665Sbms				SCARG(&wa, buf) = dat.buf;
1810191665Sbms				SCARG(&wa, nbyte) = dat.len;
1811191665Sbms				return write(td, &wa);
1812191665Sbms			}
1813191665Sbms	                DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
1814191665Sbms	                return EINVAL;
1815199528Sbms	        }
1816191665Sbms	        netaddr_to_sockaddr_in(&sain, &sc);
1817191665Sbms	        skp = &sain;
1818191665Sbms	        sasize = sizeof(sain);
1819191665Sbms	        error = sain.sin_family != st->s_family;
1820191665Sbms		break;
1821191665Sbms
1822191665Sbms	case AF_LOCAL:
1823191665Sbms		if (ctl.len == 8) {
1824191665Sbms			/* We are doing an accept; succeed */
1825192923Sbms			DPRINTF(("putmsg: Do nothing\n"));
1826192923Sbms			*retval = 0;
1827192923Sbms			return 0;
1828192923Sbms		}
1829192923Sbms		else {
1830192923Sbms			/* Maybe we've been given a device/inode pair */
1831191665Sbms			udev_t *dev = SVR4_ADDROF(&sc);
1832191665Sbms			ino_t *ino = (ino_t *) &dev[1];
1833191665Sbms			skp = svr4_find_socket(td, fp, *dev, *ino);
1834191665Sbms			if (skp == NULL) {
1835191665Sbms				skp = &saun;
1836191665Sbms				/* I guess we have it by name */
1837191665Sbms				netaddr_to_sockaddr_un(skp, &sc);
1838191665Sbms			}
1839191665Sbms			sasize = sizeof(saun);
1840191665Sbms		}
1841191665Sbms		break;
1842191665Sbms
1843191665Sbms	default:
1844191672Sbms		DPRINTF(("putmsg: Unsupported address family %d\n",
1845191672Sbms			 st->s_family));
1846191672Sbms		return ENOSYS;
1847259884Sbz	}
1848191672Sbms
1849191672Sbms	sg = stackgap_init();
1850191672Sbms	sup = stackgap_alloc(&sg, sasize);
1851191665Sbms
1852191665Sbms	if ((error = copyout(skp, sup, sasize)) != 0)
1853191665Sbms		return error;
1854191665Sbms
1855191665Sbms	switch (st->s_cmd = sc.cmd) {
1856191665Sbms	case SVR4_TI_CONNECT_REQUEST:	/* connect 	*/
1857191665Sbms		{
1858191665Sbms			struct connect_args co;
1859191665Sbms
1860191665Sbms			SCARG(&co, s) = SCARG(uap, fd);
1861191665Sbms			SCARG(&co, name) = (void *) sup;
1862191665Sbms			SCARG(&co, namelen) = (int) sasize;
1863191665Sbms
1864191665Sbms			return connect(td, &co);
1865191665Sbms		}
1866191665Sbms
1867191665Sbms	case SVR4_TI_SENDTO_REQUEST:	/* sendto 	*/
1868191665Sbms		{
1869191665Sbms			struct msghdr msg;
1870191665Sbms			struct iovec aiov;
1871191665Sbms
1872191665Sbms			msg.msg_name = (caddr_t) sup;
1873191665Sbms			msg.msg_namelen = sasize;
1874191665Sbms			msg.msg_iov = &aiov;
1875191665Sbms			msg.msg_iovlen = 1;
1876191665Sbms			msg.msg_control = 0;
1877192923Sbms			msg.msg_flags = 0;
1878192923Sbms			aiov.iov_base = dat.buf;
1879192923Sbms			aiov.iov_len = dat.len;
1880192923Sbms#if 0
1881192923Sbms			error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
1882192923Sbms					      uio, 0, 0, 0, uio->uio_td);
1883192923Sbms#endif
1884192923Sbms			error = svr4_sendit(td, SCARG(uap, fd), &msg,
1885191665Sbms				       SCARG(uap, flags));
1886192923Sbms			DPRINTF(("sendto_request error: %d\n", error));
1887191665Sbms			*retval = 0;
1888191665Sbms			return error;
1889191665Sbms		}
1890191665Sbms
1891191665Sbms	default:
1892191665Sbms		DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
1893191665Sbms		return ENOSYS;
1894191665Sbms	}
1895191665Sbms}
1896191665Sbms
1897191665Sbmsint
1898191665Sbmssvr4_sys_getmsg(td, uap)
1899191665Sbms	struct thread *td;
1900191665Sbms	struct svr4_sys_getmsg_args *uap;
1901191665Sbms{
1902191665Sbms	struct file     *fp;
1903191665Sbms	int error;
1904191665Sbms
1905191665Sbms	if ((error = fget(td, uap->fd, &fp)) != 0) {
1906191665Sbms#ifdef DEBUG_SVR4
1907192923Sbms	        uprintf("getmsg: bad fp\n");
1908192923Sbms#endif
1909192923Sbms		return EBADF;
1910191665Sbms	}
1911192923Sbms	error = svr4_do_getmsg(td, uap, fp);
1912192923Sbms	fdrop(fp, td);
1913192923Sbms	return (error);
1914192923Sbms}
1915191672Sbms
1916192923Sbmsint
1917191672Sbmssvr4_do_getmsg(td, uap, fp)
1918191665Sbms	register struct thread *td;
1919191665Sbms	struct svr4_sys_getmsg_args *uap;
1920191665Sbms	struct file *fp;
1921191665Sbms{
1922191665Sbms	struct getpeername_args ga;
1923191665Sbms	struct accept_args aa;
1924191665Sbms	struct svr4_strbuf dat, ctl;
1925199526Sbms	struct svr4_strmcmd sc;
1926199526Sbms	int error, *retval;
1927199526Sbms	struct msghdr msg;
1928199526Sbms	struct iovec aiov;
1929199526Sbms	struct sockaddr_in sain;
1930199526Sbms	struct sockaddr_un saun;
1931199526Sbms	void *skp, *sup;
1932199526Sbms	int sasize;
1933199526Sbms	struct svr4_strm *st;
1934199526Sbms	int *flen;
1935199528Sbms	int fl;
1936199528Sbms	caddr_t sg;
1937199528Sbms
1938199528Sbms	retval = td->td_retval;
1939199528Sbms
1940199528Sbms	FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
1941199528Sbms
1942199528Sbms	memset(&sc, 0, sizeof(sc));
1943199528Sbms
1944199528Sbms#ifdef DEBUG_SVR4
1945199528Sbms	show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
1946199528Sbms		 SCARG(uap, dat), 0);
1947199528Sbms#endif /* DEBUG_SVR4 */
1948199528Sbms
1949199528Sbms	if (SCARG(uap, ctl) != NULL) {
1950199528Sbms		if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
1951199526Sbms			return error;
1952199528Sbms	}
1953199528Sbms	else {
1954199526Sbms		ctl.len = -1;
1955199526Sbms		ctl.maxlen = 0;
1956199526Sbms	}
1957199526Sbms
1958199526Sbms	if (SCARG(uap, dat) != NULL) {
1959199527Sbms	    	if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
1960199527Sbms			return error;
1961199527Sbms	}
1962199527Sbms	else {
1963199527Sbms		dat.len = -1;
1964199527Sbms		dat.maxlen = 0;
1965199527Sbms	}
1966199527Sbms
1967199527Sbms	/*
1968199526Sbms	 * Only for sockets for now.
1969199527Sbms	 */
1970199527Sbms	if ((st = svr4_stream_get(fp)) == NULL) {
1971191665Sbms		DPRINTF(("getmsg: bad file type\n"));
1972191665Sbms		return EINVAL;
1973191665Sbms	}
1974191665Sbms
1975191665Sbms	if (ctl.maxlen == -1 || dat.maxlen == -1) {
1976191665Sbms		DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
1977191665Sbms		return ENOSYS;
1978191665Sbms	}
1979191665Sbms
1980191665Sbms	switch (st->s_family) {
1981191665Sbms	case AF_INET:
1982191665Sbms		skp = &sain;
1983191665Sbms		sasize = sizeof(sain);
1984191665Sbms		break;
1985191665Sbms
1986191665Sbms	case AF_LOCAL:
1987191665Sbms		skp = &saun;
1988191665Sbms		sasize = sizeof(saun);
1989191665Sbms		break;
1990191665Sbms
1991191665Sbms	default:
1992191665Sbms		DPRINTF(("getmsg: Unsupported address family %d\n",
1993191665Sbms			 st->s_family));
1994191665Sbms		return ENOSYS;
1995191665Sbms	}
1996191665Sbms
1997191665Sbms	sg = stackgap_init();
1998191665Sbms	sup = stackgap_alloc(&sg, sasize);
1999191665Sbms	flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
2000191665Sbms
2001191665Sbms	fl = sasize;
2002191665Sbms	if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
2003199526Sbms		return error;
2004199526Sbms
2005199527Sbms	switch (st->s_cmd) {
2006199527Sbms	case SVR4_TI_CONNECT_REQUEST:
2007199527Sbms		DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
2008199528Sbms		/*
2009199528Sbms		 * We do the connect in one step, so the putmsg should
2010191665Sbms		 * have gotten the error.
2011191665Sbms		 */
2012191665Sbms		sc.cmd = SVR4_TI_OK_REPLY;
2013191665Sbms		sc.len = 0;
2014191665Sbms
2015191665Sbms		ctl.len = 8;
2016191665Sbms		dat.len = -1;
2017191665Sbms		fl = 1;
2018191665Sbms		st->s_cmd = sc.cmd;
2019191665Sbms		break;
2020191665Sbms
2021191665Sbms	case SVR4_TI_OK_REPLY:
2022191665Sbms		DPRINTF(("getmsg: TI_OK_REPLY\n"));
2023191665Sbms		/*
2024191665Sbms		 * We are immediately after a connect reply, so we send
2025191665Sbms		 * a connect verification.
2026199526Sbms		 */
2027199526Sbms
2028199526Sbms		SCARG(&ga, fdes) = SCARG(uap, fd);
2029199526Sbms		SCARG(&ga, asa) = (void *) sup;
2030199526Sbms		SCARG(&ga, alen) = flen;
2031199526Sbms
2032191665Sbms		if ((error = getpeername(td, &ga)) != 0) {
2033191665Sbms			DPRINTF(("getmsg: getpeername failed %d\n", error));
2034191665Sbms			return error;
2035191665Sbms		}
2036191665Sbms
2037191665Sbms		if ((error = copyin(sup, skp, sasize)) != 0)
2038191665Sbms			return error;
2039191665Sbms
2040191665Sbms		sc.cmd = SVR4_TI_CONNECT_REPLY;
2041191665Sbms		sc.pad[0] = 0x4;
2042264364Sae		sc.offs = 0x18;
2043264364Sae		sc.pad[1] = 0x14;
2044191665Sbms		sc.pad[2] = 0x04000402;
2045264364Sae
2046191665Sbms		switch (st->s_family) {
2047191665Sbms		case AF_INET:
2048191665Sbms			sc.len = sasize;
2049191665Sbms			sockaddr_to_netaddr_in(&sc, &sain);
2050264364Sae			break;
2051191665Sbms
2052191665Sbms		case AF_LOCAL:
2053264364Sae			sc.len = sasize + 4;
2054264364Sae			sockaddr_to_netaddr_un(&sc, &saun);
2055264364Sae			break;
2056264364Sae
2057264364Sae		default:
2058264364Sae			return ENOSYS;
2059191665Sbms		}
2060191665Sbms
2061191665Sbms		ctl.len = 40;
2062191665Sbms		dat.len = -1;
2063191665Sbms		fl = 0;
2064191665Sbms		st->s_cmd = sc.cmd;
2065191665Sbms		break;
2066191665Sbms
2067191665Sbms	case SVR4_TI__ACCEPT_OK:
2068191665Sbms		DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
2069191665Sbms		/*
2070191665Sbms		 * We do the connect in one step, so the putmsg should
2071191665Sbms		 * have gotten the error.
2072191665Sbms		 */
2073191665Sbms		sc.cmd = SVR4_TI_OK_REPLY;
2074191665Sbms		sc.len = 1;
2075191665Sbms
2076191665Sbms		ctl.len = 8;
2077191665Sbms		dat.len = -1;
2078191665Sbms		fl = 1;
2079191665Sbms		st->s_cmd = SVR4_TI__ACCEPT_WAIT;
2080191665Sbms		break;
2081191665Sbms
2082191665Sbms	case SVR4_TI__ACCEPT_WAIT:
2083191665Sbms		DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
2084191665Sbms		/*
2085191665Sbms		 * We are after a listen, so we try to accept...
2086191665Sbms		 */
2087191665Sbms		SCARG(&aa, s) = SCARG(uap, fd);
2088191665Sbms		SCARG(&aa, name) = (void *) sup;
2089191665Sbms		SCARG(&aa, anamelen) = flen;
2090191665Sbms
2091192923Sbms		if ((error = accept(td, &aa)) != 0) {
2092191665Sbms			DPRINTF(("getmsg: accept failed %d\n", error));
2093191665Sbms			return error;
2094191665Sbms		}
2095191665Sbms
2096191665Sbms		st->s_afd = *retval;
2097191665Sbms
2098191665Sbms		DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
2099192923Sbms
2100191665Sbms		if ((error = copyin(sup, skp, sasize)) != 0)
2101191665Sbms			return error;
2102191665Sbms
2103191665Sbms		sc.cmd = SVR4_TI_ACCEPT_REPLY;
2104191665Sbms		sc.offs = 0x18;
2105191665Sbms		sc.pad[0] = 0x0;
2106191665Sbms
2107192923Sbms		switch (st->s_family) {
2108191665Sbms		case AF_INET:
2109191665Sbms			sc.pad[1] = 0x28;
2110191665Sbms			sockaddr_to_netaddr_in(&sc, &sain);
2111191665Sbms			ctl.len = 40;
2112191665Sbms			sc.len = sasize;
2113191665Sbms			break;
2114191665Sbms
2115191665Sbms		case AF_LOCAL:
2116191665Sbms			sc.pad[1] = 0x00010000;
2117192923Sbms			sc.pad[2] = 0xf6bcdaa0;	/* I don't know what that is */
2118192923Sbms			sc.pad[3] = 0x00010000;
2119192923Sbms			ctl.len = 134;
2120192923Sbms			sc.len = sasize + 4;
2121192923Sbms			break;
2122192923Sbms
2123192923Sbms		default:
2124191665Sbms			return ENOSYS;
2125192923Sbms		}
2126191665Sbms
2127191665Sbms		dat.len = -1;
2128191665Sbms		fl = 0;
2129191665Sbms		st->s_cmd = SVR4_TI__ACCEPT_OK;
2130191665Sbms		break;
2131191665Sbms
2132191665Sbms	case SVR4_TI_SENDTO_REQUEST:
2133192923Sbms		DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
2134192923Sbms		if (ctl.maxlen > 36 && ctl.len < 36)
2135192923Sbms		    ctl.len = 36;
2136192923Sbms
2137191665Sbms		if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
2138191665Sbms			return error;
2139191665Sbms
2140191665Sbms		switch (st->s_family) {
2141191665Sbms		case AF_INET:
2142191665Sbms			sockaddr_to_netaddr_in(&sc, &sain);
2143191665Sbms			break;
2144191665Sbms
2145191665Sbms		case AF_LOCAL:
2146191665Sbms			sockaddr_to_netaddr_un(&sc, &saun);
2147191665Sbms			break;
2148191665Sbms
2149191665Sbms		default:
2150191665Sbms			return ENOSYS;
2151191665Sbms		}
2152191665Sbms
2153191665Sbms		msg.msg_name = (caddr_t) sup;
2154191665Sbms		msg.msg_namelen = sasize;
2155191665Sbms		msg.msg_iov = &aiov;
2156191665Sbms		msg.msg_iovlen = 1;
2157191665Sbms		msg.msg_control = 0;
2158191665Sbms		aiov.iov_base = dat.buf;
2159192923Sbms		aiov.iov_len = dat.maxlen;
2160192923Sbms		msg.msg_flags = 0;
2161192923Sbms
2162192923Sbms		error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen);
2163192923Sbms
2164192923Sbms		if (error) {
2165192923Sbms			DPRINTF(("getmsg: recvit failed %d\n", error));
2166192923Sbms			return error;
2167191665Sbms		}
2168192923Sbms
2169192923Sbms		if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
2170192923Sbms			return error;
2171191665Sbms
2172191665Sbms		sc.cmd = SVR4_TI_RECVFROM_IND;
2173191665Sbms
2174191665Sbms		switch (st->s_family) {
2175191665Sbms		case AF_INET:
2176191665Sbms			sc.len = sasize;
2177191665Sbms			sockaddr_to_netaddr_in(&sc, &sain);
2178191665Sbms			break;
2179191665Sbms
2180191665Sbms		case AF_LOCAL:
2181191665Sbms			sc.len = sasize + 4;
2182191665Sbms			sockaddr_to_netaddr_un(&sc, &saun);
2183191665Sbms			break;
2184192923Sbms
2185192923Sbms		default:
2186192923Sbms			return ENOSYS;
2187192923Sbms		}
2188192923Sbms
2189191672Sbms		dat.len = *retval;
2190192923Sbms		fl = 0;
2191259884Sbz		st->s_cmd = sc.cmd;
2192192923Sbms		break;
2193192923Sbms
2194192923Sbms	default:
2195192923Sbms		st->s_cmd = sc.cmd;
2196192923Sbms		if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
2197192923Sbms		        struct read_args ra;
2198192923Sbms
2199192923Sbms			/* More weirdness:  Again, I can't find documentation
2200192923Sbms			 * to back this up, but when a process does a generic
2201192923Sbms			 * "getmsg()" call it seems that the command field is
2202195755Sbms			 * zero and the length of the data area is zero.  I
2203195755Sbms			 * think processes expect getmsg() to fill in dat.len
2204195755Sbms			 * after reading at most dat.maxlen octets from the
2205195755Sbms			 * stream.  Since we're using sockets I can let
2206192923Sbms			 * read() look after it and frob return values
2207192923Sbms			 * appropriately (or inappropriately :-)
2208192923Sbms			 *   -- newton@atdot.dotat.org        XXX
2209192923Sbms			 */
2210192923Sbms			SCARG(&ra, fd) = SCARG(uap, fd);
2211192923Sbms			SCARG(&ra, buf) = dat.buf;
2212195755Sbms			SCARG(&ra, nbyte) = dat.maxlen;
2213195755Sbms			if ((error = read(td, &ra)) != 0) {
2214195755Sbms			        return error;
2215195755Sbms			}
2216195755Sbms			dat.len = *retval;
2217195755Sbms			*retval = 0;
2218195755Sbms			st->s_cmd = SVR4_TI_SENDTO_REQUEST;
2219195755Sbms			break;
2220192923Sbms		}
2221192923Sbms		DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
2222192923Sbms		return EINVAL;
2223191672Sbms	}
2224192923Sbms
2225192923Sbms	if (SCARG(uap, ctl)) {
2226192923Sbms		if (ctl.len != -1)
2227191672Sbms			if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
2228191665Sbms				return error;
2229191665Sbms
2230191665Sbms		if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
2231191665Sbms			return error;
2232191665Sbms	}
2233191665Sbms
2234191665Sbms	if (SCARG(uap, dat)) {
2235191665Sbms		if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
2236191665Sbms			return error;
2237191665Sbms	}
2238191665Sbms
2239191665Sbms	if (SCARG(uap, flags)) { /* XXX: Need translation */
2240191665Sbms		if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
2241191665Sbms			return error;
2242191665Sbms	}
2243191665Sbms
2244191665Sbms	*retval = 0;
2245191665Sbms
2246191665Sbms#ifdef DEBUG_SVR4
2247191665Sbms	show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
2248191665Sbms		 SCARG(uap, dat), fl);
2249191665Sbms#endif /* DEBUG_SVR4 */
2250191665Sbms	return error;
2251191665Sbms}
2252191665Sbms
2253191665Sbmsint svr4_sys_send(td, uap)
2254191665Sbms	struct thread *td;
2255191665Sbms	struct svr4_sys_send_args *uap;
2256191665Sbms{
2257191665Sbms	struct osend_args osa;
2258191665Sbms	SCARG(&osa, s) = SCARG(uap, s);
2259191665Sbms	SCARG(&osa, buf) = SCARG(uap, buf);
2260191665Sbms	SCARG(&osa, len) = SCARG(uap, len);
2261191665Sbms	SCARG(&osa, flags) = SCARG(uap, flags);
2262191665Sbms	return osend(td, &osa);
2263191665Sbms}
2264191665Sbms
2265191665Sbmsint svr4_sys_recv(td, uap)
2266191665Sbms	struct thread *td;
2267191665Sbms	struct svr4_sys_recv_args *uap;
2268191665Sbms{
2269191665Sbms	struct orecv_args ora;
2270191665Sbms	SCARG(&ora, s) = SCARG(uap, s);
2271191665Sbms	SCARG(&ora, buf) = SCARG(uap, buf);
2272191665Sbms	SCARG(&ora, len) = SCARG(uap, len);
2273191665Sbms	SCARG(&ora, flags) = SCARG(uap, flags);
2274191665Sbms	return orecv(td, &ora);
2275191665Sbms}
2276191665Sbms
2277191665Sbms/*
2278191665Sbms * XXX This isn't necessary, but it's handy for inserting debug code into
2279191665Sbms * sendto().  Let's leave it here for now...
2280191665Sbms */
2281191665Sbmsint
2282191665Sbmssvr4_sys_sendto(td, uap)
2283191665Sbms        struct thread *td;
2284191665Sbms        struct svr4_sys_sendto_args *uap;
2285191665Sbms{
2286191665Sbms        struct sendto_args sa;
2287191665Sbms
2288191665Sbms	SCARG(&sa, s) = SCARG(uap, s);
2289264364Sae	SCARG(&sa, buf) = SCARG(uap, buf);
2290191665Sbms	SCARG(&sa, len) = SCARG(uap, len);
2291191665Sbms	SCARG(&sa, flags) = SCARG(uap, flags);
2292264364Sae	SCARG(&sa, to) = (caddr_t)SCARG(uap, to);
2293264364Sae	SCARG(&sa, tolen) = SCARG(uap, tolen);
2294264364Sae
2295264364Sae	DPRINTF(("calling sendto()\n"));
2296264364Sae	return sendto(td, &sa);
2297264364Sae}
2298191665Sbms
2299191665Sbms