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