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