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