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