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