Annotation of sys/compat/svr4/svr4_stream.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: svr4_stream.c,v 1.19 2005/11/21 18:16:38 millert Exp $ */
! 2: /* $NetBSD: svr4_stream.c,v 1.19 1996/12/22 23:00:03 fvdl Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Christos Zoulas.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: /*
! 34: * Pretend that we have streams...
! 35: * Yes, this is gross.
! 36: *
! 37: * ToDo: The state machine for getmsg needs re-thinking
! 38: */
! 39:
! 40: #include <sys/param.h>
! 41: #include <sys/kernel.h>
! 42: #include <sys/systm.h>
! 43: #include <sys/buf.h>
! 44: #include <sys/malloc.h>
! 45: #include <sys/ioctl.h>
! 46: #include <sys/tty.h>
! 47: #include <sys/file.h>
! 48: #include <sys/filedesc.h>
! 49: #include <sys/selinfo.h>
! 50: #include <sys/socket.h>
! 51: #include <sys/socketvar.h>
! 52: #include <sys/un.h>
! 53: #include <net/if.h>
! 54: #include <netinet/in.h>
! 55: #include <sys/mount.h>
! 56: #include <sys/proc.h>
! 57: #include <sys/vnode.h>
! 58: #include <sys/device.h>
! 59: #include <sys/stat.h>
! 60:
! 61: #include <sys/syscallargs.h>
! 62:
! 63: #include <compat/svr4/svr4_types.h>
! 64: #include <compat/svr4/svr4_util.h>
! 65: #include <compat/svr4/svr4_signal.h>
! 66: #include <compat/svr4/svr4_syscallargs.h>
! 67: #include <compat/svr4/svr4_stropts.h>
! 68: #include <compat/svr4/svr4_timod.h>
! 69: #include <compat/svr4/svr4_sockmod.h>
! 70: #include <compat/svr4/svr4_ioctl.h>
! 71: #include <compat/svr4/svr4_socket.h>
! 72:
! 73: /* Utils */
! 74: static int clean_pipe(struct proc *, const char *);
! 75: static void getparm(struct file *, struct svr4_si_sockparms *);
! 76:
! 77: /* Address Conversions */
! 78: static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
! 79: const struct sockaddr_in *);
! 80: static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
! 81: const struct sockaddr_un *);
! 82: static void netaddr_to_sockaddr_in(struct sockaddr_in *,
! 83: const struct svr4_strmcmd *);
! 84: static void netaddr_to_sockaddr_un(struct sockaddr_un *,
! 85: const struct svr4_strmcmd *);
! 86:
! 87: /* stream ioctls */
! 88: static int i_nread(struct file *, struct proc *, register_t *, int,
! 89: u_long, caddr_t);
! 90: static int i_fdinsert(struct file *, struct proc *, register_t *, int,
! 91: u_long, caddr_t);
! 92: static int i_str(struct file *, struct proc *, register_t *, int,
! 93: u_long, caddr_t);
! 94: static int _i_bind_rsvd(struct file *, struct proc *, register_t *, int,
! 95: u_long, caddr_t);
! 96: static int _i_rele_rsvd(struct file *, struct proc *, register_t *, int,
! 97: u_long, caddr_t);
! 98:
! 99: /* i_str sockmod calls */
! 100: static int sockmod(struct file *, int, struct svr4_strioctl *,
! 101: struct proc *);
! 102: static int si_listen(struct file *, int, struct svr4_strioctl *,
! 103: struct proc *);
! 104: static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
! 105: struct proc *);
! 106: static int si_sockparams(struct file *, int, struct svr4_strioctl *,
! 107: struct proc *);
! 108: static int si_shutdown(struct file *, int, struct svr4_strioctl *,
! 109: struct proc *);
! 110: static int si_getudata(struct file *, int, struct svr4_strioctl *,
! 111: struct proc *);
! 112:
! 113: /* i_str timod calls */
! 114: static int timod(struct file *, int, struct svr4_strioctl *,
! 115: struct proc *);
! 116: static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
! 117: struct proc *);
! 118: static int ti_bind(struct file *, int, struct svr4_strioctl *,
! 119: struct proc *);
! 120:
! 121: #ifdef DEBUG_SVR4
! 122: static void bufprint(u_char *, size_t);
! 123: static int show_ioc(const char *, struct svr4_strioctl *);
! 124: static int show_strbuf(struct svr4_strbuf *);
! 125: static void show_msg(const char *, int, struct svr4_strbuf *,
! 126: struct svr4_strbuf *, int);
! 127:
! 128: static void
! 129: bufprint(buf, len)
! 130: u_char *buf;
! 131: size_t len;
! 132: {
! 133: size_t i;
! 134:
! 135: uprintf("\n\t");
! 136: for (i = 0; i < len; i++) {
! 137: uprintf("%x ", buf[i]);
! 138: if (i && (i % 16) == 0)
! 139: uprintf("\n\t");
! 140: }
! 141: }
! 142:
! 143: static int
! 144: show_ioc(str, ioc)
! 145: const char *str;
! 146: struct svr4_strioctl *ioc;
! 147: {
! 148: u_char *ptr;
! 149: int error;
! 150: int len;
! 151:
! 152: len = ioc->len;
! 153: if (len > 1024)
! 154: len = 1024;
! 155:
! 156: if (len <= 0)
! 157: return 0;
! 158:
! 159: ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
! 160: uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
! 161: str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
! 162:
! 163: if ((error = copyin(ioc->buf, ptr, len)) != 0) {
! 164: free((char *) ptr, M_TEMP);
! 165: return error;
! 166: }
! 167:
! 168: bufprint(ptr, len);
! 169:
! 170: uprintf("}\n");
! 171:
! 172: free((char *) ptr, M_TEMP);
! 173: return 0;
! 174: }
! 175:
! 176:
! 177: static int
! 178: show_strbuf(str)
! 179: struct svr4_strbuf *str;
! 180: {
! 181: int error;
! 182: u_char *ptr = NULL;
! 183: int maxlen = str->maxlen;
! 184: int len = str->len;
! 185:
! 186: if (maxlen > 8192)
! 187: maxlen = 8192;
! 188:
! 189: if (maxlen < 0)
! 190: maxlen = 0;
! 191:
! 192: if (len >= maxlen)
! 193: len = maxlen;
! 194:
! 195: if (len > 0) {
! 196: ptr = (u_char *)malloc(len, M_TEMP, M_WAITOK);
! 197:
! 198: if ((error = copyin(str->buf, ptr, len)) != 0) {
! 199: free((char *) ptr, M_TEMP);
! 200: return error;
! 201: }
! 202: }
! 203:
! 204: uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
! 205:
! 206: if (ptr)
! 207: bufprint(ptr, len);
! 208:
! 209: uprintf("]}");
! 210:
! 211: if (ptr)
! 212: free((char *) ptr, M_TEMP);
! 213:
! 214: return 0;
! 215: }
! 216:
! 217:
! 218: static void
! 219: show_msg(str, fd, ctl, dat, flags)
! 220: const char *str;
! 221: int fd;
! 222: struct svr4_strbuf *ctl;
! 223: struct svr4_strbuf *dat;
! 224: int flags;
! 225: {
! 226: struct svr4_strbuf buf;
! 227: int error;
! 228:
! 229: uprintf("%s(%d", str, fd);
! 230: if (ctl != NULL) {
! 231: if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
! 232: return;
! 233: show_strbuf(&buf);
! 234: }
! 235: else
! 236: uprintf(", NULL");
! 237:
! 238: if (dat != NULL) {
! 239: if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
! 240: return;
! 241: show_strbuf(&buf);
! 242: }
! 243: else
! 244: uprintf(", NULL");
! 245:
! 246: uprintf(", %x);\n", flags);
! 247: }
! 248: #endif /* DEBUG_SVR4 */
! 249:
! 250: /*
! 251: * We are faced with an interesting situation. On svr4 unix sockets
! 252: * are really pipes. But we really have sockets, and we might as
! 253: * well use them. At the point where svr4 calls TI_BIND, it has
! 254: * already created a named pipe for the socket using mknod(2).
! 255: * We need to create a socket with the same name when we bind,
! 256: * so we need to remove the pipe before, otherwise we'll get address
! 257: * already in use. So we *carefully* remove the pipe, to avoid
! 258: * using this as a random file removal tool. We use system calls
! 259: * to avoid code duplication.
! 260: */
! 261: static int
! 262: clean_pipe(p, path)
! 263: struct proc *p;
! 264: const char *path;
! 265: {
! 266: struct sys_lstat_args la;
! 267: struct sys_unlink_args ua;
! 268: register_t retval;
! 269: struct stat st;
! 270: int error;
! 271: caddr_t sg = stackgap_init(p->p_emul);
! 272: size_t l = strlen(path) + 1;
! 273:
! 274: SCARG(&la, path) = stackgap_alloc(&sg, l);
! 275: SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
! 276:
! 277: if ((error = copyout((char *) path, (char *) SCARG(&la, path), l)) != 0)
! 278: return error;
! 279:
! 280: if ((error = sys_lstat(p, &la, &retval)) != 0)
! 281: return 0;
! 282:
! 283: if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
! 284: return 0;
! 285:
! 286: /*
! 287: * Make sure we are dealing with a mode 0 named pipe.
! 288: */
! 289: if ((st.st_mode & S_IFMT) != S_IFIFO)
! 290: return 0;
! 291:
! 292: if ((st.st_mode & ALLPERMS) != 0)
! 293: return 0;
! 294:
! 295: SCARG(&ua, path) = SCARG(&la, path);
! 296:
! 297: if ((error = sys_unlink(p, &ua, &retval)) != 0) {
! 298: DPRINTF(("clean_pipe: unlink failed %d\n", error));
! 299: return error;
! 300: }
! 301:
! 302: return 0;
! 303: }
! 304:
! 305:
! 306: static void
! 307: sockaddr_to_netaddr_in(sc, sain)
! 308: struct svr4_strmcmd *sc;
! 309: const struct sockaddr_in *sain;
! 310: {
! 311: struct svr4_netaddr_in *na;
! 312: na = SVR4_ADDROF(sc);
! 313:
! 314: na->family = sain->sin_family;
! 315: na->port = sain->sin_port;
! 316: na->addr = sain->sin_addr.s_addr;
! 317: DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
! 318: na->addr));
! 319: }
! 320:
! 321:
! 322: static void
! 323: sockaddr_to_netaddr_un(sc, saun)
! 324: struct svr4_strmcmd *sc;
! 325: const struct sockaddr_un *saun;
! 326: {
! 327: struct svr4_netaddr_un *na;
! 328: char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 -
! 329: sizeof(*sc);
! 330: const char *src;
! 331:
! 332: na = SVR4_ADDROF(sc);
! 333: na->family = saun->sun_family;
! 334: for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
! 335: if (dst == edst)
! 336: break;
! 337: DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
! 338: }
! 339:
! 340:
! 341: static void
! 342: netaddr_to_sockaddr_in(sain, sc)
! 343: struct sockaddr_in *sain;
! 344: const struct svr4_strmcmd *sc;
! 345: {
! 346: const struct svr4_netaddr_in *na;
! 347:
! 348:
! 349: na = SVR4_ADDROF(sc);
! 350: bzero(sain, sizeof(*sain));
! 351: sain->sin_len = sizeof(*sain);
! 352: sain->sin_family = na->family;
! 353: sain->sin_port = na->port;
! 354: sain->sin_addr.s_addr = na->addr;
! 355: DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
! 356: sain->sin_port, sain->sin_addr.s_addr));
! 357: }
! 358:
! 359:
! 360: static void
! 361: netaddr_to_sockaddr_un(saun, sc)
! 362: struct sockaddr_un *saun;
! 363: const struct svr4_strmcmd *sc;
! 364: {
! 365: const struct svr4_netaddr_un *na;
! 366: char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
! 367: const char *src;
! 368:
! 369: na = SVR4_ADDROF(sc);
! 370: bzero(saun, sizeof(*saun));
! 371: saun->sun_family = na->family;
! 372: for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
! 373: if (dst == edst)
! 374: break;
! 375: saun->sun_len = dst - saun->sun_path;
! 376: DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
! 377: saun->sun_path));
! 378: }
! 379:
! 380:
! 381: static void
! 382: getparm(fp, pa)
! 383: struct file *fp;
! 384: struct svr4_si_sockparms *pa;
! 385: {
! 386: struct svr4_strm *st = svr4_stream_get(fp);
! 387: struct socket *so = (struct socket *) fp->f_data;
! 388:
! 389: if (st == NULL)
! 390: return;
! 391:
! 392: pa->family = st->s_family;
! 393:
! 394: switch (so->so_type) {
! 395: case SOCK_DGRAM:
! 396: pa->type = SVR4_SOCK_DGRAM;
! 397: pa->protocol = IPPROTO_UDP;
! 398: return;
! 399:
! 400: case SOCK_STREAM:
! 401: pa->type = SVR4_SOCK_STREAM;
! 402: pa->protocol = IPPROTO_IP;
! 403: return;
! 404:
! 405: case SOCK_RAW:
! 406: pa->type = SVR4_SOCK_RAW;
! 407: pa->protocol = IPPROTO_RAW;
! 408: return;
! 409:
! 410: default:
! 411: pa->type = 0;
! 412: pa->protocol = 0;
! 413: return;
! 414: }
! 415: }
! 416:
! 417:
! 418: static int
! 419: si_ogetudata(fp, fd, ioc, p)
! 420: struct file *fp;
! 421: int fd;
! 422: struct svr4_strioctl *ioc;
! 423: struct proc *p;
! 424: {
! 425: int error;
! 426: struct svr4_si_oudata ud;
! 427: struct svr4_si_sockparms pa;
! 428:
! 429: if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
! 430: DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
! 431: sizeof(ud), ioc->len));
! 432: return EINVAL;
! 433: }
! 434:
! 435: if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
! 436: return error;
! 437:
! 438: getparm(fp, &pa);
! 439:
! 440: switch (pa.family) {
! 441: case AF_INET:
! 442: ud.tidusize = 16384;
! 443: ud.addrsize = sizeof(struct sockaddr_in);
! 444: if (pa.type == SVR4_SOCK_STREAM)
! 445: ud.etsdusize = 1;
! 446: else
! 447: ud.etsdusize = 0;
! 448: break;
! 449:
! 450: case AF_UNIX:
! 451: ud.tidusize = 65536;
! 452: ud.addrsize = 128;
! 453: ud.etsdusize = 128;
! 454: break;
! 455:
! 456: default:
! 457: DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
! 458: pa.family));
! 459: return ENOSYS;
! 460: }
! 461:
! 462: /* I have no idea what these should be! */
! 463: ud.optsize = 128;
! 464: ud.tsdusize = 128;
! 465: ud.servtype = pa.type;
! 466:
! 467: /* XXX: Fixme */
! 468: ud.so_state = 0;
! 469: ud.so_options = 0;
! 470: return copyout(&ud, ioc->buf, ioc->len);
! 471: }
! 472:
! 473:
! 474: static int
! 475: si_sockparams(fp, fd, ioc, p)
! 476: struct file *fp;
! 477: int fd;
! 478: struct svr4_strioctl *ioc;
! 479: struct proc *p;
! 480: {
! 481: struct svr4_si_sockparms pa;
! 482:
! 483: getparm(fp, &pa);
! 484: return copyout(&pa, ioc->buf, sizeof(pa));
! 485: }
! 486:
! 487:
! 488: static int
! 489: si_listen(fp, fd, ioc, p)
! 490: struct file *fp;
! 491: int fd;
! 492: struct svr4_strioctl *ioc;
! 493: struct proc *p;
! 494: {
! 495: int error;
! 496: struct svr4_strm *st = svr4_stream_get(fp);
! 497: register_t retval;
! 498: struct svr4_strmcmd lst;
! 499: struct sys_listen_args la;
! 500:
! 501: if (st == NULL)
! 502: return EINVAL;
! 503:
! 504: if (ioc->len > sizeof(lst))
! 505: return EINVAL;
! 506:
! 507: if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
! 508: return error;
! 509:
! 510: if (lst.cmd != SVR4_TI_BIND_REQUEST) {
! 511: DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
! 512: return EINVAL;
! 513: }
! 514:
! 515: /*
! 516: * We are making assumptions again...
! 517: */
! 518: SCARG(&la, s) = fd;
! 519: DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
! 520: SCARG(&la, backlog) = 5;
! 521:
! 522: if ((error = sys_listen(p, &la, &retval)) != 0) {
! 523: DPRINTF(("SI_LISTEN: listen failed %d\n", error));
! 524: return error;
! 525: }
! 526:
! 527: st->s_cmd = SVR4_TI__ACCEPT_WAIT;
! 528: lst.cmd = SVR4_TI_BIND_REPLY;
! 529:
! 530: switch (st->s_family) {
! 531: case AF_INET:
! 532: /* XXX: Fill the length here */
! 533: break;
! 534:
! 535: case AF_UNIX:
! 536: lst.len = 140;
! 537: lst.pad[28] = 0x00000000; /* magic again */
! 538: lst.pad[29] = 0x00000800; /* magic again */
! 539: lst.pad[30] = 0x80001400; /* magic again */
! 540: break;
! 541:
! 542: default:
! 543: DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
! 544: st->s_family));
! 545: return ENOSYS;
! 546: }
! 547:
! 548:
! 549: if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
! 550: return error;
! 551:
! 552: return 0;
! 553: }
! 554:
! 555:
! 556: static int
! 557: si_getudata(fp, fd, ioc, p)
! 558: struct file *fp;
! 559: int fd;
! 560: struct svr4_strioctl *ioc;
! 561: struct proc *p;
! 562: {
! 563: int error;
! 564: struct svr4_si_udata ud;
! 565:
! 566: if (sizeof(ud) != ioc->len) {
! 567: DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
! 568: sizeof(ud), ioc->len));
! 569: return EINVAL;
! 570: }
! 571:
! 572: if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
! 573: return error;
! 574:
! 575: getparm(fp, &ud.sockparms);
! 576:
! 577: switch (ud.sockparms.family) {
! 578: case AF_INET:
! 579: ud.tidusize = 16384;
! 580: ud.tsdusize = 16384;
! 581: ud.addrsize = sizeof(struct sockaddr_in);
! 582: if (ud.sockparms.type == SVR4_SOCK_STREAM)
! 583: ud.etsdusize = 1;
! 584: else
! 585: ud.etsdusize = 0;
! 586: ud.optsize = 0;
! 587: break;
! 588:
! 589: case AF_UNIX:
! 590: ud.tidusize = 65536;
! 591: ud.tsdusize = 128;
! 592: ud.addrsize = 128;
! 593: ud.etsdusize = 128;
! 594: ud.optsize = 128;
! 595: break;
! 596:
! 597: default:
! 598: DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
! 599: ud.sockparms.family));
! 600: return ENOSYS;
! 601: }
! 602:
! 603: ud.servtype = ud.sockparms.type;
! 604:
! 605: /* XXX: Fixme */
! 606: ud.so_state = 0;
! 607: ud.so_options = 0;
! 608: return copyout(&ud, ioc->buf, sizeof(ud));
! 609: }
! 610:
! 611:
! 612: static int
! 613: si_shutdown(fp, fd, ioc, p)
! 614: struct file *fp;
! 615: int fd;
! 616: struct svr4_strioctl *ioc;
! 617: struct proc *p;
! 618: {
! 619: int error;
! 620: struct sys_shutdown_args ap;
! 621: register_t retval;
! 622:
! 623: if (ioc->len != sizeof(SCARG(&ap, how))) {
! 624: DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
! 625: sizeof(SCARG(&ap, how)), ioc->len));
! 626: return EINVAL;
! 627: }
! 628:
! 629: if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
! 630: return error;
! 631:
! 632: SCARG(&ap, s) = fd;
! 633:
! 634: return sys_shutdown(p, &ap, &retval);
! 635: }
! 636:
! 637: static int
! 638: sockmod(fp, fd, ioc, p)
! 639: struct file *fp;
! 640: int fd;
! 641: struct svr4_strioctl *ioc;
! 642: struct proc *p;
! 643: {
! 644: switch (ioc->cmd) {
! 645: case SVR4_SI_OGETUDATA:
! 646: DPRINTF(("SI_OGETUDATA\n"));
! 647: return si_ogetudata(fp, fd, ioc, p);
! 648:
! 649: case SVR4_SI_SHUTDOWN:
! 650: DPRINTF(("SI_SHUTDOWN\n"));
! 651: return si_shutdown(fp, fd, ioc, p);
! 652:
! 653: case SVR4_SI_LISTEN:
! 654: DPRINTF(("SI_LISTEN\n"));
! 655: return si_listen(fp, fd, ioc, p);
! 656:
! 657: case SVR4_SI_SETMYNAME:
! 658: DPRINTF(("SI_SETMYNAME\n"));
! 659: return 0;
! 660:
! 661: case SVR4_SI_SETPEERNAME:
! 662: DPRINTF(("SI_SETPEERNAME\n"));
! 663: return 0;
! 664:
! 665: case SVR4_SI_GETINTRANSIT:
! 666: DPRINTF(("SI_GETINTRANSIT\n"));
! 667: return 0;
! 668:
! 669: case SVR4_SI_TCL_LINK:
! 670: DPRINTF(("SI_TCL_LINK\n"));
! 671: return 0;
! 672:
! 673: case SVR4_SI_TCL_UNLINK:
! 674: DPRINTF(("SI_TCL_UNLINK\n"));
! 675: return 0;
! 676:
! 677: case SVR4_SI_SOCKPARAMS:
! 678: DPRINTF(("SI_SOCKPARAMS\n"));
! 679: return si_sockparams(fp, fd, ioc, p);
! 680:
! 681: case SVR4_SI_GETUDATA:
! 682: DPRINTF(("SI_GETUDATA\n"));
! 683: return si_getudata(fp, fd, ioc, p);
! 684:
! 685: default:
! 686: DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
! 687: return 0;
! 688:
! 689: }
! 690: }
! 691:
! 692:
! 693: static int
! 694: ti_getinfo(fp, fd, ioc, p)
! 695: struct file *fp;
! 696: int fd;
! 697: struct svr4_strioctl *ioc;
! 698: struct proc *p;
! 699: {
! 700: int error;
! 701: struct svr4_infocmd info;
! 702:
! 703: bzero(&info, sizeof(info));
! 704:
! 705: if (ioc->len > sizeof(info))
! 706: return EINVAL;
! 707:
! 708: if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
! 709: return error;
! 710:
! 711: if (info.cmd != SVR4_TI_INFO_REQUEST)
! 712: return EINVAL;
! 713:
! 714: info.cmd = SVR4_TI_INFO_REPLY;
! 715: info.tsdu = 0;
! 716: info.etsdu = 1;
! 717: info.cdata = -2;
! 718: info.ddata = -2;
! 719: info.addr = 16;
! 720: info.opt = -1;
! 721: info.tidu = 16384;
! 722: info.serv = 2;
! 723: info.current = 0;
! 724: info.provider = 2;
! 725:
! 726: ioc->len = sizeof(info);
! 727: if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
! 728: return error;
! 729:
! 730: return 0;
! 731: }
! 732:
! 733:
! 734: static int
! 735: ti_bind(fp, fd, ioc, p)
! 736: struct file *fp;
! 737: int fd;
! 738: struct svr4_strioctl *ioc;
! 739: struct proc *p;
! 740: {
! 741: int error;
! 742: struct svr4_strm *st = svr4_stream_get(fp);
! 743: struct sockaddr_in sain;
! 744: struct sockaddr_un saun;
! 745: register_t retval;
! 746: caddr_t sg;
! 747: void *skp, *sup = NULL;
! 748: int sasize;
! 749: struct svr4_strmcmd bnd;
! 750: struct sys_bind_args ba;
! 751:
! 752: if (st == NULL) {
! 753: DPRINTF(("ti_bind: bad file descriptor\n"));
! 754: return EINVAL;
! 755: }
! 756:
! 757: if (ioc->len > sizeof(bnd))
! 758: return EINVAL;
! 759:
! 760: if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
! 761: return error;
! 762:
! 763: if (bnd.cmd != SVR4_TI_BIND_REQUEST) {
! 764: DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
! 765: return EINVAL;
! 766: }
! 767:
! 768: switch (st->s_family) {
! 769: case AF_INET:
! 770: skp = &sain;
! 771: sasize = sizeof(sain);
! 772:
! 773: if (bnd.offs == 0)
! 774: goto reply;
! 775:
! 776: netaddr_to_sockaddr_in(&sain, &bnd);
! 777:
! 778: DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
! 779: sain.sin_family, sain.sin_port,
! 780: sain.sin_addr.s_addr));
! 781: break;
! 782:
! 783: case AF_UNIX:
! 784: skp = &saun;
! 785: sasize = sizeof(saun);
! 786: if (bnd.offs == 0)
! 787: goto reply;
! 788:
! 789: netaddr_to_sockaddr_un(&saun, &bnd);
! 790:
! 791: if (saun.sun_path[0] == '\0')
! 792: goto reply;
! 793:
! 794: DPRINTF(("TI_BIND: fam %d, path %s\n",
! 795: saun.sun_family, saun.sun_path));
! 796:
! 797: if ((error = clean_pipe(p, saun.sun_path)) != 0)
! 798: return error;
! 799:
! 800: bnd.pad[28] = 0x00001000; /* magic again */
! 801: break;
! 802:
! 803: default:
! 804: DPRINTF(("TI_BIND: Unsupported address family %d\n",
! 805: st->s_family));
! 806: return ENOSYS;
! 807: }
! 808:
! 809: sg = stackgap_init(p->p_emul);
! 810: sup = stackgap_alloc(&sg, sasize);
! 811:
! 812: if ((error = copyout(skp, sup, sasize)) != 0)
! 813: return error;
! 814:
! 815: SCARG(&ba, s) = fd;
! 816: DPRINTF(("TI_BIND: fileno %d\n", fd));
! 817: SCARG(&ba, name) = (void *)sup;
! 818: SCARG(&ba, namelen) = sasize;
! 819:
! 820: if ((error = sys_bind(p, &ba, &retval)) != 0) {
! 821: DPRINTF(("TI_BIND: bind failed %d\n", error));
! 822: return error;
! 823: }
! 824:
! 825: reply:
! 826: if (sup == NULL) {
! 827: bzero(&bnd, sizeof(bnd));
! 828: bnd.len = sasize + 4;
! 829: bnd.offs = 0x10; /* XXX */
! 830: }
! 831:
! 832: bnd.cmd = SVR4_TI_BIND_REPLY;
! 833:
! 834: if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
! 835: return error;
! 836:
! 837: return 0;
! 838: }
! 839:
! 840:
! 841: static int
! 842: timod(fp, fd, ioc, p)
! 843: struct file *fp;
! 844: int fd;
! 845: struct svr4_strioctl *ioc;
! 846: struct proc *p;
! 847: {
! 848: switch (ioc->cmd) {
! 849: case SVR4_TI_GETINFO:
! 850: DPRINTF(("TI_GETINFO\n"));
! 851: return ti_getinfo(fp, fd, ioc, p);
! 852:
! 853: case SVR4_TI_OPTMGMT:
! 854: DPRINTF(("TI_OPTMGMT\n"));
! 855: return 0;
! 856:
! 857: case SVR4_TI_BIND:
! 858: DPRINTF(("TI_BIND\n"));
! 859: return ti_bind(fp, fd, ioc, p);
! 860:
! 861: case SVR4_TI_UNBIND:
! 862: DPRINTF(("TI_UNBIND\n"));
! 863: return 0;
! 864:
! 865: default:
! 866: DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
! 867: return 0;
! 868: }
! 869: }
! 870:
! 871:
! 872: int
! 873: svr4_stream_ti_ioctl(fp, p, retval, fd, cmd, dat)
! 874: struct file *fp;
! 875: struct proc *p;
! 876: register_t *retval;
! 877: int fd;
! 878: u_long cmd;
! 879: caddr_t dat;
! 880: {
! 881: struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
! 882: struct svr4_strm *st = svr4_stream_get(fp);
! 883: int error;
! 884: void *skp, *sup;
! 885: struct sockaddr_in sain;
! 886: struct sockaddr_un saun;
! 887: struct svr4_strmcmd sc;
! 888: socklen_t sasize, samax;
! 889: caddr_t sg;
! 890: int *lenp;
! 891:
! 892: if (st == NULL)
! 893: return EINVAL;
! 894:
! 895: sc.offs = 0x10;
! 896:
! 897: switch (st->s_family) {
! 898: case AF_INET:
! 899: skp = &sain;
! 900: samax = sizeof(sain);
! 901: break;
! 902:
! 903: case AF_UNIX:
! 904: skp = &saun;
! 905: samax = sizeof(saun);
! 906: break;
! 907:
! 908: default:
! 909: DPRINTF(("ti_ioctl: Unsupported address family %d\n",
! 910: st->s_family));
! 911: return ENOSYS;
! 912: }
! 913:
! 914: sg = stackgap_init(p->p_emul);
! 915: sup = stackgap_alloc(&sg, samax);
! 916: lenp = stackgap_alloc(&sg, sizeof(*lenp));
! 917:
! 918: if ((error = copyout(&samax, lenp, sizeof(*lenp))) != 0) {
! 919: DPRINTF(("ti_ioctl: error copying out lenp\n"));
! 920: return error;
! 921: }
! 922:
! 923: switch (cmd) {
! 924: case SVR4_TI_GETMYNAME:
! 925: DPRINTF(("TI_GETMYNAME\n"));
! 926: {
! 927: struct sys_getsockname_args ap;
! 928: SCARG(&ap, fdes) = fd;
! 929: SCARG(&ap, asa) = sup;
! 930: SCARG(&ap, alen) = lenp;
! 931: if ((error = sys_getsockname(p, &ap, retval)) != 0) {
! 932: DPRINTF(("ti_ioctl: getsockname error\n"));
! 933: return error;
! 934: }
! 935: }
! 936: break;
! 937:
! 938: case SVR4_TI_GETPEERNAME:
! 939: DPRINTF(("TI_GETPEERNAME\n"));
! 940: {
! 941: struct sys_getpeername_args ap;
! 942: SCARG(&ap, fdes) = fd;
! 943: SCARG(&ap, asa) = sup;
! 944: SCARG(&ap, alen) = lenp;
! 945: if ((error = sys_getpeername(p, &ap, retval)) != 0) {
! 946: DPRINTF(("ti_ioctl: getpeername error\n"));
! 947: return error;
! 948: }
! 949: }
! 950: break;
! 951:
! 952: case SVR4_TI_SETMYNAME:
! 953: DPRINTF(("TI_SETMYNAME\n"));
! 954: return 0;
! 955:
! 956: case SVR4_TI_SETPEERNAME:
! 957: DPRINTF(("TI_SETPEERNAME\n"));
! 958: return 0;
! 959: default:
! 960: DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
! 961: return ENOSYS;
! 962: }
! 963:
! 964: if ((error = copyin(sup, skp, samax)) != 0) {
! 965: DPRINTF(("ti_ioctl: error copying in socket data\n"));
! 966: return error;
! 967: }
! 968:
! 969: if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
! 970: DPRINTF(("ti_ioctl: error copying in socket size\n"));
! 971: return error;
! 972: }
! 973:
! 974: if (sasize < 0 || sasize > samax) {
! 975: DPRINTF(("ti_ioctl: invalid socklen on stack\n"));
! 976: error = EINVAL;
! 977: return error;
! 978: }
! 979:
! 980: if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
! 981: DPRINTF(("ti_ioctl: error copying in strbuf\n"));
! 982: return error;
! 983: }
! 984:
! 985: switch (st->s_family) {
! 986: case AF_INET:
! 987: sockaddr_to_netaddr_in(&sc, &sain);
! 988: skb.len = sasize;
! 989: break;
! 990:
! 991: case AF_UNIX:
! 992: sockaddr_to_netaddr_un(&sc, &saun);
! 993: skb.len = sasize + 4;
! 994: break;
! 995:
! 996: default:
! 997: return ENOSYS;
! 998: }
! 999:
! 1000: if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
! 1001: DPRINTF(("ti_ioctl: error copying out socket data\n"));
! 1002: return error;
! 1003: }
! 1004:
! 1005: if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
! 1006: DPRINTF(("ti_ioctl: error copying out strbuf\n"));
! 1007: return error;
! 1008: }
! 1009:
! 1010: return error;
! 1011: }
! 1012:
! 1013: static int
! 1014: i_nread(fp, p, retval, fd, cmd, dat)
! 1015: struct file *fp;
! 1016: struct proc *p;
! 1017: register_t *retval;
! 1018: int fd;
! 1019: u_long cmd;
! 1020: caddr_t dat;
! 1021: {
! 1022: int error;
! 1023: int nread = 0;
! 1024:
! 1025: /*
! 1026: * We are supposed to return the message length in nread, and the
! 1027: * number of messages in retval. We don't have the notion of number
! 1028: * of stream messages, so we just find out if we have any bytes waiting
! 1029: * for us, and if we do, then we assume that we have at least one
! 1030: * message waiting for us.
! 1031: */
! 1032: if ((error = (*fp->f_ops->fo_ioctl)(fp, FIONREAD,
! 1033: (caddr_t) &nread, p)) != 0)
! 1034: return error;
! 1035:
! 1036: if (nread != 0)
! 1037: *retval = 1;
! 1038: else
! 1039: *retval = 0;
! 1040:
! 1041: return copyout(&nread, dat, sizeof(nread));
! 1042: }
! 1043:
! 1044: static int
! 1045: i_fdinsert(fp, p, retval, fd, cmd, dat)
! 1046: struct file *fp;
! 1047: struct proc *p;
! 1048: register_t *retval;
! 1049: int fd;
! 1050: u_long cmd;
! 1051: caddr_t dat;
! 1052: {
! 1053: /*
! 1054: * Major hack again here. We assume that we are using this to
! 1055: * implement accept(2). If that is the case, we have already
! 1056: * called accept, and we have stored the file descriptor in
! 1057: * afd. We find the file descriptor that the code wants to use
! 1058: * in fd insert, and then we dup2() our accepted file descriptor
! 1059: * to it.
! 1060: */
! 1061: int error;
! 1062: struct svr4_strm *st = svr4_stream_get(fp);
! 1063: struct svr4_strfdinsert fdi;
! 1064: struct sys_dup2_args d2p;
! 1065: struct sys_close_args clp;
! 1066:
! 1067: if (st == NULL) {
! 1068: DPRINTF(("fdinsert: bad file type\n"));
! 1069: return EINVAL;
! 1070: }
! 1071:
! 1072: if (st->s_afd == -1) {
! 1073: DPRINTF(("fdinsert: accept fd not found\n"));
! 1074: return ENOENT;
! 1075: }
! 1076:
! 1077: if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
! 1078: DPRINTF(("fdinsert: copyin failed %d\n", error));
! 1079: return error;
! 1080: }
! 1081:
! 1082: SCARG(&d2p, from) = st->s_afd;
! 1083: SCARG(&d2p, to) = fdi.fd;
! 1084:
! 1085: if ((error = sys_dup2(p, &d2p, retval)) != 0) {
! 1086: DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
! 1087: st->s_afd, fdi.fd, error));
! 1088: return error;
! 1089: }
! 1090:
! 1091: SCARG(&clp, fd) = st->s_afd;
! 1092:
! 1093: if ((error = sys_close(p, &clp, retval)) != 0) {
! 1094: DPRINTF(("fdinsert: close(%d) failed %d\n",
! 1095: st->s_afd, error));
! 1096: return error;
! 1097: }
! 1098:
! 1099: st->s_afd = -1;
! 1100:
! 1101: *retval = 0;
! 1102: return 0;
! 1103: }
! 1104:
! 1105:
! 1106: static int
! 1107: _i_bind_rsvd(fp, p, retval, fd, cmd, dat)
! 1108: struct file *fp;
! 1109: struct proc *p;
! 1110: register_t *retval;
! 1111: int fd;
! 1112: u_long cmd;
! 1113: caddr_t dat;
! 1114: {
! 1115: struct sys_mknod_args ap;
! 1116:
! 1117: /*
! 1118: * This is a supposed to be a kernel and library only ioctl.
! 1119: * It gets called before ti_bind, when we have a unix
! 1120: * socket, to physically create the socket transport and
! 1121: * ``reserve'' it. I don't know how this get reserved inside
! 1122: * the kernel, but we are going to create it nevertheless.
! 1123: */
! 1124: SCARG(&ap, path) = dat;
! 1125: SCARG(&ap, mode) = S_IFIFO;
! 1126:
! 1127: return sys_mkfifo(p, &ap, retval);
! 1128: }
! 1129:
! 1130: static int
! 1131: _i_rele_rsvd(fp, p, retval, fd, cmd, dat)
! 1132: struct file *fp;
! 1133: struct proc *p;
! 1134: register_t *retval;
! 1135: int fd;
! 1136: u_long cmd;
! 1137: caddr_t dat;
! 1138: {
! 1139: struct sys_unlink_args ap;
! 1140:
! 1141: /*
! 1142: * This is a supposed to be a kernel and library only ioctl.
! 1143: * I guess it is supposed to release the socket.
! 1144: */
! 1145: SCARG(&ap, path) = dat;
! 1146:
! 1147: return sys_unlink(p, &ap, retval);
! 1148: }
! 1149:
! 1150: static int
! 1151: i_str(fp, p, retval, fd, cmd, dat)
! 1152: struct file *fp;
! 1153: struct proc *p;
! 1154: register_t *retval;
! 1155: int fd;
! 1156: u_long cmd;
! 1157: caddr_t dat;
! 1158: {
! 1159: int error;
! 1160: struct svr4_strioctl ioc;
! 1161:
! 1162: if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
! 1163: return error;
! 1164:
! 1165: #ifdef DEBUG_SVR4
! 1166: if ((error = show_ioc(">", &ioc)) != 0)
! 1167: return error;
! 1168: #endif /* DEBUG_SVR4 */
! 1169:
! 1170: switch (ioc.cmd & 0xff00) {
! 1171: case SVR4_SIMOD:
! 1172: if ((error = sockmod(fp, fd, &ioc, p)) != 0)
! 1173: return error;
! 1174: break;
! 1175:
! 1176: case SVR4_TIMOD:
! 1177: if ((error = timod(fp, fd, &ioc, p)) != 0)
! 1178: return error;
! 1179: break;
! 1180:
! 1181: default:
! 1182: DPRINTF(("Unimplemented module %c %ld\n",
! 1183: (char) (cmd >> 8), cmd & 0xff));
! 1184: return 0;
! 1185: }
! 1186:
! 1187: #ifdef DEBUG_SVR4
! 1188: if ((error = show_ioc("<", &ioc)) != 0)
! 1189: return error;
! 1190: #endif /* DEBUG_SVR4 */
! 1191: return copyout(&ioc, dat, sizeof(ioc));
! 1192: }
! 1193:
! 1194:
! 1195: int
! 1196: svr4_stream_ioctl(fp, p, retval, fd, cmd, dat)
! 1197: struct file *fp;
! 1198: struct proc *p;
! 1199: register_t *retval;
! 1200: int fd;
! 1201: u_long cmd;
! 1202: caddr_t dat;
! 1203: {
! 1204: *retval = 0;
! 1205:
! 1206: /*
! 1207: * All the following stuff assumes "sockmod" is pushed...
! 1208: */
! 1209: switch (cmd) {
! 1210: case SVR4_I_NREAD:
! 1211: DPRINTF(("I_NREAD\n"));
! 1212: return i_nread(fp, p, retval, fd, cmd, dat);
! 1213:
! 1214: case SVR4_I_PUSH:
! 1215: DPRINTF(("I_PUSH\n"));
! 1216: return 0;
! 1217:
! 1218: case SVR4_I_POP:
! 1219: DPRINTF(("I_POP\n"));
! 1220: return 0;
! 1221:
! 1222: case SVR4_I_LOOK:
! 1223: DPRINTF(("I_LOOK\n"));
! 1224: return 0;
! 1225:
! 1226: case SVR4_I_FLUSH:
! 1227: DPRINTF(("I_FLUSH\n"));
! 1228: return 0;
! 1229:
! 1230: case SVR4_I_SRDOPT:
! 1231: DPRINTF(("I_SRDOPT\n"));
! 1232: return 0;
! 1233:
! 1234: case SVR4_I_GRDOPT:
! 1235: DPRINTF(("I_GRDOPT\n"));
! 1236: return 0;
! 1237:
! 1238: case SVR4_I_STR:
! 1239: DPRINTF(("I_STR\n"));
! 1240: return i_str(fp, p, retval, fd, cmd, dat);
! 1241:
! 1242: case SVR4_I_SETSIG:
! 1243: DPRINTF(("I_SETSIG\n"));
! 1244: /*
! 1245: * This is the best we can do for now; we cannot generate
! 1246: * signals only for specific events so the signal mask gets
! 1247: * ignored.
! 1248: *
! 1249: * We alse have to fix the O_ASYNC fcntl bit, so the
! 1250: * process will get SIGPOLLs. */
! 1251: {
! 1252: struct sys_fcntl_args fa;
! 1253: int error;
! 1254: register_t oflags, flags;
! 1255:
! 1256: /* get old status flags */
! 1257: SCARG(&fa, fd) = fd;
! 1258: SCARG(&fa, cmd) = F_GETFL;
! 1259: if ((error = sys_fcntl(p, &fa, &oflags)) != 0)
! 1260: return error;
! 1261:
! 1262: /* update the flags */
! 1263: if ((long) dat != 0)
! 1264: flags = oflags | O_ASYNC;
! 1265: else
! 1266: flags = oflags & ~O_ASYNC;
! 1267:
! 1268: /* set the new flags, if changed */
! 1269: if (flags != oflags) {
! 1270: SCARG(&fa, cmd) = F_SETFL;
! 1271: SCARG(&fa, arg) = (void *) flags;
! 1272: if ((error = sys_fcntl(p, &fa, &flags)) != 0)
! 1273: return error;
! 1274: }
! 1275:
! 1276: /* set up SIGIO receiver if needed */
! 1277: if ((long) dat != 0) {
! 1278: SCARG(&fa, cmd) = F_SETOWN;
! 1279: SCARG(&fa, arg) = (void *) p->p_pid;
! 1280: return sys_fcntl(p, &fa, retval);
! 1281: }
! 1282: }
! 1283:
! 1284: case SVR4_I_GETSIG:
! 1285: DPRINTF(("I_GETSIG\n"));
! 1286: return EINVAL;
! 1287:
! 1288: case SVR4_I_FIND:
! 1289: DPRINTF(("I_FIND\n"));
! 1290: /*
! 1291: * Here we are not pushing modules really, we just
! 1292: * pretend all are present
! 1293: */
! 1294: *retval = 1;
! 1295: return 0;
! 1296:
! 1297: case SVR4_I_LINK:
! 1298: DPRINTF(("I_LINK\n"));
! 1299: return 0;
! 1300:
! 1301: case SVR4_I_UNLINK:
! 1302: DPRINTF(("I_UNLINK\n"));
! 1303: return 0;
! 1304:
! 1305: case SVR4_I_ERECVFD:
! 1306: DPRINTF(("I_ERECVFD\n"));
! 1307: return 0;
! 1308:
! 1309: case SVR4_I_PEEK:
! 1310: DPRINTF(("I_PEEK\n"));
! 1311: return 0;
! 1312:
! 1313: case SVR4_I_FDINSERT:
! 1314: DPRINTF(("I_FDINSERT\n"));
! 1315: return i_fdinsert(fp, p, retval, fd, cmd, dat);
! 1316:
! 1317: case SVR4_I_SENDFD:
! 1318: DPRINTF(("I_SENDFD\n"));
! 1319: return 0;
! 1320:
! 1321: case SVR4_I_RECVFD:
! 1322: DPRINTF(("I_RECVFD\n"));
! 1323: return 0;
! 1324:
! 1325: case SVR4_I_SWROPT:
! 1326: DPRINTF(("I_SWROPT\n"));
! 1327: return 0;
! 1328:
! 1329: case SVR4_I_GWROPT:
! 1330: DPRINTF(("I_GWROPT\n"));
! 1331: return 0;
! 1332:
! 1333: case SVR4_I_LIST:
! 1334: DPRINTF(("I_LIST\n"));
! 1335: return 0;
! 1336:
! 1337: case SVR4_I_PLINK:
! 1338: DPRINTF(("I_PLINK\n"));
! 1339: return 0;
! 1340:
! 1341: case SVR4_I_PUNLINK:
! 1342: DPRINTF(("I_PUNLINK\n"));
! 1343: return 0;
! 1344:
! 1345: case SVR4_I_SETEV:
! 1346: DPRINTF(("I_SETEV\n"));
! 1347: return 0;
! 1348:
! 1349: case SVR4_I_GETEV:
! 1350: DPRINTF(("I_GETEV\n"));
! 1351: return 0;
! 1352:
! 1353: case SVR4_I_STREV:
! 1354: DPRINTF(("I_STREV\n"));
! 1355: return 0;
! 1356:
! 1357: case SVR4_I_UNSTREV:
! 1358: DPRINTF(("I_UNSTREV\n"));
! 1359: return 0;
! 1360:
! 1361: case SVR4_I_FLUSHBAND:
! 1362: DPRINTF(("I_FLUSHBAND\n"));
! 1363: return 0;
! 1364:
! 1365: case SVR4_I_CKBAND:
! 1366: DPRINTF(("I_CKBAND\n"));
! 1367: return 0;
! 1368:
! 1369: case SVR4_I_GETBAND:
! 1370: DPRINTF(("I_GETBANK\n"));
! 1371: return 0;
! 1372:
! 1373: case SVR4_I_ATMARK:
! 1374: DPRINTF(("I_ATMARK\n"));
! 1375: return 0;
! 1376:
! 1377: case SVR4_I_SETCLTIME:
! 1378: DPRINTF(("I_SETCLTIME\n"));
! 1379: return 0;
! 1380:
! 1381: case SVR4_I_GETCLTIME:
! 1382: DPRINTF(("I_GETCLTIME\n"));
! 1383: return 0;
! 1384:
! 1385: case SVR4_I_CANPUT:
! 1386: DPRINTF(("I_CANPUT\n"));
! 1387: return 0;
! 1388:
! 1389: case SVR4__I_BIND_RSVD:
! 1390: DPRINTF(("_I_BIND_RSVD\n"));
! 1391: return _i_bind_rsvd(fp, p, retval, fd, cmd, dat);
! 1392:
! 1393: case SVR4__I_RELE_RSVD:
! 1394: DPRINTF(("_I_RELE_RSVD\n"));
! 1395: return _i_rele_rsvd(fp, p, retval, fd, cmd, dat);
! 1396:
! 1397: default:
! 1398: DPRINTF(("unimpl cmd = %lx\n", cmd));
! 1399: break;
! 1400: }
! 1401:
! 1402: return 0;
! 1403: }
! 1404:
! 1405:
! 1406:
! 1407:
! 1408: int
! 1409: svr4_sys_putmsg(p, v, retval)
! 1410: register struct proc *p;
! 1411: void *v;
! 1412: register_t *retval;
! 1413: {
! 1414: struct svr4_sys_putmsg_args *uap = v;
! 1415: struct filedesc *fdp = p->p_fd;
! 1416: struct file *fp;
! 1417: struct svr4_strbuf dat, ctl;
! 1418: struct svr4_strmcmd sc;
! 1419: struct sockaddr_in sain;
! 1420: struct sockaddr_un saun;
! 1421: void *skp, *sup;
! 1422: int sasize;
! 1423: struct svr4_strm *st;
! 1424: int error;
! 1425: caddr_t sg;
! 1426:
! 1427: #ifdef DEBUG_SVR4
! 1428: show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
! 1429: SCARG(uap, dat), SCARG(uap, flags));
! 1430: #endif /* DEBUG_SVR4 */
! 1431:
! 1432: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
! 1433: return EBADF;
! 1434: FREF(fp);
! 1435:
! 1436: if (SCARG(uap, ctl) != NULL) {
! 1437: if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
! 1438: goto out;
! 1439: }
! 1440: else
! 1441: ctl.len = -1;
! 1442:
! 1443: if (SCARG(uap, dat) != NULL) {
! 1444: if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
! 1445: goto out;
! 1446: }
! 1447: else
! 1448: dat.len = -1;
! 1449:
! 1450: /*
! 1451: * Only for sockets for now.
! 1452: */
! 1453: if ((st = svr4_stream_get(fp)) == NULL) {
! 1454: DPRINTF(("putmsg: bad file type\n"));
! 1455: error = EINVAL;
! 1456: goto out;
! 1457: }
! 1458:
! 1459: if (ctl.len > sizeof(sc)) {
! 1460: DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
! 1461: sizeof(struct svr4_strmcmd)));
! 1462: error = EINVAL;
! 1463: goto out;
! 1464: }
! 1465:
! 1466: if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
! 1467: goto out;
! 1468:
! 1469: switch (st->s_family) {
! 1470: case AF_INET:
! 1471: if (sc.len != sizeof(sain)) {
! 1472: DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
! 1473: error = ENOSYS;
! 1474: goto out;
! 1475: }
! 1476: netaddr_to_sockaddr_in(&sain, &sc);
! 1477: skp = &sain;
! 1478: sasize = sizeof(sain);
! 1479: error = sain.sin_family != st->s_family;
! 1480: break;
! 1481:
! 1482: case AF_UNIX:
! 1483: if (ctl.len == 8) {
! 1484: /* We are doing an accept; succeed */
! 1485: DPRINTF(("putmsg: Do nothing\n"));
! 1486: *retval = 0;
! 1487: error = 0;
! 1488: goto out;
! 1489: } else {
! 1490: /* Maybe we've been given a device/inode pair */
! 1491: dev_t *dev = SVR4_ADDROF(&sc);
! 1492: ino_t *ino = (ino_t *) &dev[1];
! 1493: skp = svr4_find_socket(p, fp, *dev, *ino);
! 1494: if (skp == NULL) {
! 1495: skp = &saun;
! 1496: /* I guess we have it by name */
! 1497: netaddr_to_sockaddr_un(skp, &sc);
! 1498: }
! 1499: sasize = sizeof(saun);
! 1500: }
! 1501: break;
! 1502:
! 1503: default:
! 1504: DPRINTF(("putmsg: Unsupported address family %d\n",
! 1505: st->s_family));
! 1506: error = ENOSYS;
! 1507: goto out;
! 1508: }
! 1509:
! 1510: sg = stackgap_init(p->p_emul);
! 1511: sup = stackgap_alloc(&sg, sasize);
! 1512:
! 1513: if ((error = copyout(skp, sup, sasize)) != 0)
! 1514: goto out;
! 1515:
! 1516: switch (st->s_cmd = sc.cmd) {
! 1517: case SVR4_TI_CONNECT_REQUEST: /* connect */
! 1518: {
! 1519: struct sys_connect_args co;
! 1520:
! 1521: SCARG(&co, s) = SCARG(uap, fd);
! 1522: SCARG(&co, name) = (void *)sup;
! 1523: SCARG(&co, namelen) = (int)sasize;
! 1524: error = sys_connect(p, &co, retval);
! 1525: goto out;
! 1526: }
! 1527:
! 1528: case SVR4_TI_SENDTO_REQUEST: /* sendto */
! 1529: {
! 1530: struct msghdr msg;
! 1531: struct iovec aiov;
! 1532:
! 1533: msg.msg_name = (caddr_t) sup;
! 1534: msg.msg_namelen = sasize;
! 1535: msg.msg_iov = &aiov;
! 1536: msg.msg_iovlen = 1;
! 1537: msg.msg_control = 0;
! 1538: msg.msg_flags = 0;
! 1539: aiov.iov_base = dat.buf;
! 1540: aiov.iov_len = dat.len;
! 1541: error = sendit(p, SCARG(uap, fd), &msg,
! 1542: SCARG(uap, flags), retval);
! 1543:
! 1544: *retval = 0;
! 1545: goto out;
! 1546: }
! 1547:
! 1548: default:
! 1549: DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
! 1550: error = ENOSYS;
! 1551: goto out;
! 1552: }
! 1553:
! 1554: out:
! 1555: FRELE(fp);
! 1556: return (error);
! 1557: }
! 1558:
! 1559:
! 1560: int
! 1561: svr4_sys_getmsg(p, v, retval)
! 1562: register struct proc *p;
! 1563: void *v;
! 1564: register_t *retval;
! 1565: {
! 1566: struct svr4_sys_getmsg_args *uap = v;
! 1567: struct filedesc *fdp = p->p_fd;
! 1568: struct file *fp;
! 1569: struct sys_getpeername_args ga;
! 1570: struct sys_accept_args aa;
! 1571: struct svr4_strbuf dat, ctl;
! 1572: struct svr4_strmcmd sc;
! 1573: int error;
! 1574: struct msghdr msg;
! 1575: struct iovec aiov;
! 1576: struct sockaddr_in sain;
! 1577: struct sockaddr_un saun;
! 1578: void *skp, *sup;
! 1579: int sasize;
! 1580: struct svr4_strm *st;
! 1581: int *flen;
! 1582: int fl;
! 1583: caddr_t sg;
! 1584:
! 1585: bzero(&sc, sizeof(sc));
! 1586:
! 1587: #ifdef DEBUG_SVR4
! 1588: show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
! 1589: SCARG(uap, dat), 0);
! 1590: #endif /* DEBUG_SVR4 */
! 1591:
! 1592: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
! 1593: return EBADF;
! 1594: FREF(fp);
! 1595:
! 1596: if (SCARG(uap, ctl) != NULL) {
! 1597: if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
! 1598: goto out;
! 1599: }
! 1600: else {
! 1601: ctl.len = -1;
! 1602: ctl.maxlen = 0;
! 1603: }
! 1604:
! 1605: if (SCARG(uap, dat) != NULL) {
! 1606: if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
! 1607: goto out;
! 1608: }
! 1609: else {
! 1610: dat.len = -1;
! 1611: dat.maxlen = 0;
! 1612: }
! 1613:
! 1614: /*
! 1615: * Only for sockets for now.
! 1616: */
! 1617: if ((st = svr4_stream_get(fp)) == NULL) {
! 1618: DPRINTF(("getmsg: bad file type\n"));
! 1619: error = EINVAL;
! 1620: goto out;
! 1621: }
! 1622:
! 1623: if (ctl.maxlen == -1 || dat.maxlen == -1) {
! 1624: DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
! 1625: error = ENOSYS;
! 1626: goto out;
! 1627: }
! 1628:
! 1629: switch (st->s_family) {
! 1630: case AF_INET:
! 1631: skp = &sain;
! 1632: sasize = sizeof(sain);
! 1633: break;
! 1634:
! 1635: case AF_UNIX:
! 1636: skp = &saun;
! 1637: sasize = sizeof(saun);
! 1638: break;
! 1639:
! 1640: default:
! 1641: DPRINTF(("getmsg: Unsupported address family %d\n",
! 1642: st->s_family));
! 1643: error = ENOSYS;
! 1644: goto out;
! 1645: }
! 1646:
! 1647: sg = stackgap_init(p->p_emul);
! 1648: sup = stackgap_alloc(&sg, sasize);
! 1649: flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
! 1650:
! 1651: fl = sasize;
! 1652: if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
! 1653: goto out;
! 1654:
! 1655: switch (st->s_cmd) {
! 1656: case SVR4_TI_CONNECT_REQUEST:
! 1657: DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
! 1658: /*
! 1659: * We do the connect in one step, so the putmsg should
! 1660: * have gotten the error.
! 1661: */
! 1662: sc.cmd = SVR4_TI_OK_REPLY;
! 1663: sc.len = 0;
! 1664:
! 1665: ctl.len = 8;
! 1666: dat.len = -1;
! 1667: fl = 1;
! 1668: st->s_cmd = sc.cmd;
! 1669: break;
! 1670:
! 1671: case SVR4_TI_OK_REPLY:
! 1672: DPRINTF(("getmsg: TI_OK_REPLY\n"));
! 1673:
! 1674: /*
! 1675: * We are immediately after a connect reply, so we send
! 1676: * a connect verification.
! 1677: */
! 1678: SCARG(&ga, fdes) = SCARG(uap, fd);
! 1679: SCARG(&ga, asa) = (void *)sup;
! 1680: SCARG(&ga, alen) = flen;
! 1681:
! 1682: if ((error = sys_getpeername(p, &ga, retval)) != 0) {
! 1683: DPRINTF(("getmsg: getpeername failed %d\n", error));
! 1684: goto out;
! 1685: }
! 1686:
! 1687: if ((error = copyin(sup, skp, sasize)) != 0)
! 1688: goto out;
! 1689:
! 1690: sc.cmd = SVR4_TI_CONNECT_REPLY;
! 1691: sc.pad[0] = 0x4;
! 1692: sc.offs = 0x18;
! 1693: sc.pad[1] = 0x14;
! 1694: sc.pad[2] = 0x04000402;
! 1695:
! 1696: switch (st->s_family) {
! 1697: case AF_INET:
! 1698: sc.len = sasize;
! 1699: sockaddr_to_netaddr_in(&sc, &sain);
! 1700: break;
! 1701:
! 1702: case AF_UNIX:
! 1703: sc.len = sasize + 4;
! 1704: sockaddr_to_netaddr_un(&sc, &saun);
! 1705: break;
! 1706:
! 1707: default:
! 1708: error = ENOSYS;
! 1709: goto out;
! 1710: }
! 1711:
! 1712: ctl.len = 40;
! 1713: dat.len = -1;
! 1714: fl = 0;
! 1715: st->s_cmd = sc.cmd;
! 1716: break;
! 1717:
! 1718: case SVR4_TI__ACCEPT_OK:
! 1719: DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
! 1720: /*
! 1721: * We do the connect in one step, so the putmsg should
! 1722: * have gotten the error.
! 1723: */
! 1724: sc.cmd = SVR4_TI_OK_REPLY;
! 1725: sc.len = 1;
! 1726:
! 1727: ctl.len = 8;
! 1728: dat.len = -1;
! 1729: fl = 1;
! 1730: st->s_cmd = SVR4_TI__ACCEPT_WAIT;
! 1731: break;
! 1732:
! 1733: case SVR4_TI__ACCEPT_WAIT:
! 1734: DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
! 1735: /*
! 1736: * We are after a listen, so we try to accept...
! 1737: */
! 1738: SCARG(&aa, s) = SCARG(uap, fd);
! 1739: SCARG(&aa, name) = (void *)sup;
! 1740: SCARG(&aa, anamelen) = flen;
! 1741:
! 1742: if ((error = sys_accept(p, &aa, retval)) != 0) {
! 1743: DPRINTF(("getmsg: accept failed %d\n", error));
! 1744: goto out;
! 1745: }
! 1746:
! 1747: st->s_afd = *retval;
! 1748:
! 1749: DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
! 1750:
! 1751: if ((error = copyin(sup, skp, sasize)) != 0)
! 1752: goto out;
! 1753:
! 1754: sc.cmd = SVR4_TI_ACCEPT_REPLY;
! 1755: sc.len = sasize;
! 1756: sc.offs = 0x18;
! 1757: sc.pad[0] = 0x0;
! 1758: sc.pad[1] = 0x28;
! 1759: sc.pad[2] = 0x3;
! 1760:
! 1761: switch (st->s_family) {
! 1762: case AF_INET:
! 1763: sc.pad[1] = 0x28;
! 1764: sockaddr_to_netaddr_in(&sc, &sain);
! 1765: ctl.len = 40;
! 1766: sc.len = sasize;
! 1767: break;
! 1768:
! 1769: case AF_UNIX:
! 1770: sc.pad[1] = 0x00010000;
! 1771: sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
! 1772: sc.pad[3] = 0x00010000;
! 1773: ctl.len = 134;
! 1774: sc.len = sasize + 4;
! 1775: break;
! 1776:
! 1777: default:
! 1778: error = ENOSYS;
! 1779: goto out;
! 1780: }
! 1781:
! 1782: ctl.len = 40;
! 1783: dat.len = -1;
! 1784: fl = 0;
! 1785: st->s_cmd = SVR4_TI__ACCEPT_OK;
! 1786: break;
! 1787:
! 1788: case SVR4_TI_SENDTO_REQUEST:
! 1789: DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
! 1790: if (ctl.maxlen > 36 && ctl.len < 36)
! 1791: ctl.len = 36;
! 1792:
! 1793: if (ctl.len > sizeof(sc))
! 1794: ctl.len = sizeof(sc);
! 1795:
! 1796: if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
! 1797: goto out;
! 1798:
! 1799: switch (st->s_family) {
! 1800: case AF_INET:
! 1801: sockaddr_to_netaddr_in(&sc, &sain);
! 1802: break;
! 1803:
! 1804: case AF_UNIX:
! 1805: sockaddr_to_netaddr_un(&sc, &saun);
! 1806: break;
! 1807:
! 1808: default:
! 1809: error = ENOSYS;
! 1810: goto out;
! 1811: }
! 1812:
! 1813: msg.msg_name = (caddr_t) sup;
! 1814: msg.msg_namelen = sasize;
! 1815: msg.msg_iov = &aiov;
! 1816: msg.msg_iovlen = 1;
! 1817: msg.msg_control = 0;
! 1818: aiov.iov_base = dat.buf;
! 1819: aiov.iov_len = dat.maxlen;
! 1820: msg.msg_flags = 0;
! 1821:
! 1822: error = recvit(p, SCARG(uap, fd), &msg, (caddr_t) flen, retval);
! 1823:
! 1824: if (error) {
! 1825: DPRINTF(("getmsg: recvit failed %d\n", error));
! 1826: goto out;
! 1827: }
! 1828:
! 1829: if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
! 1830: goto out;
! 1831:
! 1832: sc.cmd = SVR4_TI_RECVFROM_REPLY;
! 1833:
! 1834: switch (st->s_family) {
! 1835: case AF_INET:
! 1836: sc.len = sasize;
! 1837: sockaddr_to_netaddr_in(&sc, &sain);
! 1838: break;
! 1839:
! 1840: case AF_UNIX:
! 1841: sc.len = sasize + 4;
! 1842: sockaddr_to_netaddr_un(&sc, &saun);
! 1843: break;
! 1844:
! 1845: default:
! 1846: error = ENOSYS;
! 1847: goto out;
! 1848: }
! 1849:
! 1850: dat.len = *retval;
! 1851: fl = 0;
! 1852: st->s_cmd = sc.cmd;
! 1853: break;
! 1854:
! 1855: default:
! 1856: st->s_cmd = sc.cmd;
! 1857: DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
! 1858: error = EINVAL;
! 1859: goto out;
! 1860: }
! 1861:
! 1862: if (SCARG(uap, ctl)) {
! 1863: if (ctl.len != -1)
! 1864: if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
! 1865: goto out;
! 1866:
! 1867: if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
! 1868: goto out;
! 1869: }
! 1870:
! 1871: if (SCARG(uap, dat)) {
! 1872: if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
! 1873: goto out;
! 1874: }
! 1875:
! 1876: if (SCARG(uap, flags)) { /* XXX: Need translation */
! 1877: if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
! 1878: goto out;
! 1879: }
! 1880:
! 1881: *retval = 0;
! 1882:
! 1883: #ifdef DEBUG_SVR4
! 1884: show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
! 1885: SCARG(uap, dat), fl);
! 1886: #endif /* DEBUG_SVR4 */
! 1887: out:
! 1888: FRELE(fp);
! 1889: return error;
! 1890: }
CVSweb