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