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