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