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