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