1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)uipc_usrreq.c 7.10 (Berkeley) 05/02/89 18 */ 19 20 #include "param.h" 21 #include "dir.h" 22 #include "user.h" 23 #include "mbuf.h" 24 #include "domain.h" 25 #include "protosw.h" 26 #include "socket.h" 27 #include "socketvar.h" 28 #include "unpcb.h" 29 #include "un.h" 30 #include "vnode.h" 31 #include "mount.h" 32 #include "file.h" 33 #include "stat.h" 34 35 /* 36 * Unix communications domain. 37 * 38 * TODO: 39 * SEQPACKET, RDM 40 * rethink name space problems 41 * need a proper out-of-band 42 */ 43 struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX }; 44 ino_t unp_vno; /* prototype for fake vnode numbers */ 45 46 /*ARGSUSED*/ 47 uipc_usrreq(so, req, m, nam, rights) 48 struct socket *so; 49 int req; 50 struct mbuf *m, *nam, *rights; 51 { 52 struct unpcb *unp = sotounpcb(so); 53 register struct socket *so2; 54 int error = 0; 55 56 if (req == PRU_CONTROL) 57 return (EOPNOTSUPP); 58 if (req != PRU_SEND && rights && rights->m_len) { 59 error = EOPNOTSUPP; 60 goto release; 61 } 62 if (unp == 0 && req != PRU_ATTACH) { 63 error = EINVAL; 64 goto release; 65 } 66 switch (req) { 67 68 case PRU_ATTACH: 69 if (unp) { 70 error = EISCONN; 71 break; 72 } 73 error = unp_attach(so); 74 break; 75 76 case PRU_DETACH: 77 unp_detach(unp); 78 break; 79 80 case PRU_BIND: 81 error = unp_bind(unp, nam); 82 break; 83 84 case PRU_LISTEN: 85 if (unp->unp_vnode == 0) 86 error = EINVAL; 87 break; 88 89 case PRU_CONNECT: 90 error = unp_connect(so, nam); 91 break; 92 93 case PRU_CONNECT2: 94 error = unp_connect2(so, (struct socket *)nam); 95 break; 96 97 case PRU_DISCONNECT: 98 unp_disconnect(unp); 99 break; 100 101 case PRU_ACCEPT: 102 /* 103 * Pass back name of connected socket, 104 * if it was bound and we are still connected 105 * (our peer may have closed already!). 106 */ 107 if (unp->unp_conn && unp->unp_conn->unp_addr) { 108 nam->m_len = unp->unp_conn->unp_addr->m_len; 109 bcopy(mtod(unp->unp_conn->unp_addr, caddr_t), 110 mtod(nam, caddr_t), (unsigned)nam->m_len); 111 } else { 112 nam->m_len = sizeof(sun_noname); 113 *(mtod(nam, struct sockaddr *)) = sun_noname; 114 } 115 break; 116 117 case PRU_SHUTDOWN: 118 socantsendmore(so); 119 unp_usrclosed(unp); 120 break; 121 122 case PRU_RCVD: 123 switch (so->so_type) { 124 125 case SOCK_DGRAM: 126 panic("uipc 1"); 127 /*NOTREACHED*/ 128 129 case SOCK_STREAM: 130 #define rcv (&so->so_rcv) 131 #define snd (&so2->so_snd) 132 if (unp->unp_conn == 0) 133 break; 134 so2 = unp->unp_conn->unp_socket; 135 /* 136 * Adjust backpressure on sender 137 * and wakeup any waiting to write. 138 */ 139 snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt; 140 unp->unp_mbcnt = rcv->sb_mbcnt; 141 snd->sb_hiwat += unp->unp_cc - rcv->sb_cc; 142 unp->unp_cc = rcv->sb_cc; 143 sowwakeup(so2); 144 #undef snd 145 #undef rcv 146 break; 147 148 default: 149 panic("uipc 2"); 150 } 151 break; 152 153 case PRU_SEND: 154 if (rights) { 155 error = unp_internalize(rights); 156 if (error) 157 break; 158 } 159 switch (so->so_type) { 160 161 case SOCK_DGRAM: { 162 struct sockaddr *from; 163 164 if (nam) { 165 if (unp->unp_conn) { 166 error = EISCONN; 167 break; 168 } 169 error = unp_connect(so, nam); 170 if (error) 171 break; 172 } else { 173 if (unp->unp_conn == 0) { 174 error = ENOTCONN; 175 break; 176 } 177 } 178 so2 = unp->unp_conn->unp_socket; 179 if (unp->unp_addr) 180 from = mtod(unp->unp_addr, struct sockaddr *); 181 else 182 from = &sun_noname; 183 if (sbspace(&so2->so_rcv) > 0 && 184 sbappendaddr(&so2->so_rcv, from, m, rights)) { 185 sorwakeup(so2); 186 m = 0; 187 } else 188 error = ENOBUFS; 189 if (nam) 190 unp_disconnect(unp); 191 break; 192 } 193 194 case SOCK_STREAM: 195 #define rcv (&so2->so_rcv) 196 #define snd (&so->so_snd) 197 if (so->so_state & SS_CANTSENDMORE) { 198 error = EPIPE; 199 break; 200 } 201 if (unp->unp_conn == 0) 202 panic("uipc 3"); 203 so2 = unp->unp_conn->unp_socket; 204 /* 205 * Send to paired receive port, and then reduce 206 * send buffer hiwater marks to maintain backpressure. 207 * Wake up readers. 208 */ 209 if (rights) 210 (void)sbappendrights(rcv, m, rights); 211 else 212 sbappend(rcv, m); 213 snd->sb_mbmax -= 214 rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt; 215 unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt; 216 snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc; 217 unp->unp_conn->unp_cc = rcv->sb_cc; 218 sorwakeup(so2); 219 m = 0; 220 #undef snd 221 #undef rcv 222 break; 223 224 default: 225 panic("uipc 4"); 226 } 227 break; 228 229 case PRU_ABORT: 230 unp_drop(unp, ECONNABORTED); 231 break; 232 233 case PRU_SENSE: 234 ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; 235 if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { 236 so2 = unp->unp_conn->unp_socket; 237 ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; 238 } 239 ((struct stat *) m)->st_dev = NODEV; 240 if (unp->unp_vno == 0) 241 unp->unp_vno = unp_vno++; 242 ((struct stat *) m)->st_ino = unp->unp_vno; 243 return (0); 244 245 case PRU_RCVOOB: 246 return (EOPNOTSUPP); 247 248 case PRU_SENDOOB: 249 error = EOPNOTSUPP; 250 break; 251 252 case PRU_SOCKADDR: 253 if (unp->unp_addr) { 254 nam->m_len = unp->unp_addr->m_len; 255 bcopy(mtod(unp->unp_addr, caddr_t), 256 mtod(nam, caddr_t), (unsigned)nam->m_len); 257 } else 258 nam->m_len = 0; 259 break; 260 261 case PRU_PEERADDR: 262 if (unp->unp_conn && unp->unp_conn->unp_addr) { 263 nam->m_len = unp->unp_conn->unp_addr->m_len; 264 bcopy(mtod(unp->unp_conn->unp_addr, caddr_t), 265 mtod(nam, caddr_t), (unsigned)nam->m_len); 266 } else 267 nam->m_len = 0; 268 break; 269 270 case PRU_SLOWTIMO: 271 break; 272 273 default: 274 panic("piusrreq"); 275 } 276 release: 277 if (m) 278 m_freem(m); 279 return (error); 280 } 281 282 /* 283 * Both send and receive buffers are allocated PIPSIZ bytes of buffering 284 * for stream sockets, although the total for sender and receiver is 285 * actually only PIPSIZ. 286 * Datagram sockets really use the sendspace as the maximum datagram size, 287 * and don't really want to reserve the sendspace. Their recvspace should 288 * be large enough for at least one max-size datagram plus address. 289 */ 290 #define PIPSIZ 4096 291 u_long unpst_sendspace = PIPSIZ; 292 u_long unpst_recvspace = PIPSIZ; 293 u_long unpdg_sendspace = 2*1024; /* really max datagram size */ 294 u_long unpdg_recvspace = 4*1024; 295 296 int unp_rights; /* file descriptors in flight */ 297 298 unp_attach(so) 299 struct socket *so; 300 { 301 register struct mbuf *m; 302 register struct unpcb *unp; 303 int error; 304 305 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 306 switch (so->so_type) { 307 308 case SOCK_STREAM: 309 error = soreserve(so, unpst_sendspace, unpst_recvspace); 310 break; 311 312 case SOCK_DGRAM: 313 error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 314 break; 315 } 316 if (error) 317 return (error); 318 } 319 m = m_getclr(M_DONTWAIT, MT_PCB); 320 if (m == NULL) 321 return (ENOBUFS); 322 unp = mtod(m, struct unpcb *); 323 so->so_pcb = (caddr_t)unp; 324 unp->unp_socket = so; 325 return (0); 326 } 327 328 unp_detach(unp) 329 register struct unpcb *unp; 330 { 331 332 if (unp->unp_vnode) { 333 unp->unp_vnode->v_socket = 0; 334 vrele(unp->unp_vnode); 335 unp->unp_vnode = 0; 336 } 337 if (unp->unp_conn) 338 unp_disconnect(unp); 339 while (unp->unp_refs) 340 unp_drop(unp->unp_refs, ECONNRESET); 341 soisdisconnected(unp->unp_socket); 342 unp->unp_socket->so_pcb = 0; 343 m_freem(unp->unp_addr); 344 (void) m_free(dtom(unp)); 345 if (unp_rights) 346 unp_gc(); 347 } 348 349 unp_bind(unp, nam) 350 struct unpcb *unp; 351 struct mbuf *nam; 352 { 353 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 354 register struct vnode *vp; 355 register struct nameidata *ndp = &u.u_nd; 356 struct vattr vattr; 357 int error; 358 359 ndp->ni_dirp = soun->sun_path; 360 if (unp->unp_vnode != NULL) 361 return (EINVAL); 362 if (nam->m_len == MLEN) { 363 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0) 364 return (EINVAL); 365 } else 366 *(mtod(nam, caddr_t) + nam->m_len) = 0; 367 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 368 ndp->ni_nameiop = CREATE | FOLLOW | LOCKPARENT; 369 ndp->ni_segflg = UIO_SYSSPACE; 370 if (error = namei(ndp)) 371 return (error); 372 vp = ndp->ni_vp; 373 if (vp != NULL) { 374 vop_abortop(ndp); 375 return (EADDRINUSE); 376 } 377 vattr_null(&vattr); 378 vattr.va_type = VSOCK; 379 vattr.va_mode = 0777; 380 if (error = vop_create(ndp, &vattr)) 381 return (error); 382 vp = ndp->ni_vp; 383 vp->v_socket = unp->unp_socket; 384 unp->unp_vnode = vp; 385 unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); 386 vop_unlock(vp); 387 return (0); 388 } 389 390 unp_connect(so, nam) 391 struct socket *so; 392 struct mbuf *nam; 393 { 394 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 395 register struct vnode *vp; 396 register struct socket *so2, *so3; 397 register struct nameidata *ndp = &u.u_nd; 398 struct unpcb *unp2, *unp3; 399 int error; 400 401 ndp->ni_dirp = soun->sun_path; 402 if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) { /* XXX */ 403 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0) 404 return (EMSGSIZE); 405 } else 406 *(mtod(nam, caddr_t) + nam->m_len) = 0; 407 ndp->ni_nameiop = LOOKUP | FOLLOW; 408 ndp->ni_segflg = UIO_SYSSPACE; 409 if (error = namei(ndp)) 410 return (error); 411 vp = ndp->ni_vp; 412 if (error = vn_access(vp, VWRITE, u.u_cred)) 413 goto bad; 414 if (vp->v_type != VSOCK) { 415 error = ENOTSOCK; 416 goto bad; 417 } 418 so2 = vp->v_socket; 419 if (so2 == 0) { 420 error = ECONNREFUSED; 421 goto bad; 422 } 423 if (so->so_type != so2->so_type) { 424 error = EPROTOTYPE; 425 goto bad; 426 } 427 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 428 if ((so2->so_options & SO_ACCEPTCONN) == 0 || 429 (so3 = sonewconn(so2)) == 0) { 430 error = ECONNREFUSED; 431 goto bad; 432 } 433 unp2 = sotounpcb(so2); 434 unp3 = sotounpcb(so3); 435 if (unp2->unp_addr) 436 unp3->unp_addr = 437 m_copy(unp2->unp_addr, 0, (int)M_COPYALL); 438 so2 = so3; 439 } 440 error = unp_connect2(so, so2); 441 bad: 442 vrele(vp); 443 return (error); 444 } 445 446 unp_connect2(so, so2) 447 register struct socket *so; 448 register struct socket *so2; 449 { 450 register struct unpcb *unp = sotounpcb(so); 451 register struct unpcb *unp2; 452 453 if (so2->so_type != so->so_type) 454 return (EPROTOTYPE); 455 unp2 = sotounpcb(so2); 456 unp->unp_conn = unp2; 457 switch (so->so_type) { 458 459 case SOCK_DGRAM: 460 unp->unp_nextref = unp2->unp_refs; 461 unp2->unp_refs = unp; 462 soisconnected(so); 463 break; 464 465 case SOCK_STREAM: 466 unp2->unp_conn = unp; 467 soisconnected(so2); 468 soisconnected(so); 469 break; 470 471 default: 472 panic("unp_connect2"); 473 } 474 return (0); 475 } 476 477 unp_disconnect(unp) 478 struct unpcb *unp; 479 { 480 register struct unpcb *unp2 = unp->unp_conn; 481 482 if (unp2 == 0) 483 return; 484 unp->unp_conn = 0; 485 switch (unp->unp_socket->so_type) { 486 487 case SOCK_DGRAM: 488 if (unp2->unp_refs == unp) 489 unp2->unp_refs = unp->unp_nextref; 490 else { 491 unp2 = unp2->unp_refs; 492 for (;;) { 493 if (unp2 == 0) 494 panic("unp_disconnect"); 495 if (unp2->unp_nextref == unp) 496 break; 497 unp2 = unp2->unp_nextref; 498 } 499 unp2->unp_nextref = unp->unp_nextref; 500 } 501 unp->unp_nextref = 0; 502 unp->unp_socket->so_state &= ~SS_ISCONNECTED; 503 break; 504 505 case SOCK_STREAM: 506 soisdisconnected(unp->unp_socket); 507 unp2->unp_conn = 0; 508 soisdisconnected(unp2->unp_socket); 509 break; 510 } 511 } 512 513 #ifdef notdef 514 unp_abort(unp) 515 struct unpcb *unp; 516 { 517 518 unp_detach(unp); 519 } 520 #endif 521 522 /*ARGSUSED*/ 523 unp_usrclosed(unp) 524 struct unpcb *unp; 525 { 526 527 } 528 529 unp_drop(unp, errno) 530 struct unpcb *unp; 531 int errno; 532 { 533 struct socket *so = unp->unp_socket; 534 535 so->so_error = errno; 536 unp_disconnect(unp); 537 if (so->so_head) { 538 so->so_pcb = (caddr_t) 0; 539 m_freem(unp->unp_addr); 540 (void) m_free(dtom(unp)); 541 sofree(so); 542 } 543 } 544 545 #ifdef notdef 546 unp_drain() 547 { 548 549 } 550 #endif 551 552 unp_externalize(rights) 553 struct mbuf *rights; 554 { 555 int newfds = rights->m_len / sizeof (int); 556 register int i; 557 register struct file **rp = mtod(rights, struct file **); 558 register struct file *fp; 559 int f; 560 561 if (newfds > ufavail()) { 562 for (i = 0; i < newfds; i++) { 563 fp = *rp; 564 unp_discard(fp); 565 *rp++ = 0; 566 } 567 return (EMSGSIZE); 568 } 569 for (i = 0; i < newfds; i++) { 570 if (ufalloc(0, &f)) 571 panic("unp_externalize"); 572 fp = *rp; 573 u.u_ofile[f] = fp; 574 fp->f_msgcount--; 575 unp_rights--; 576 *(int *)rp++ = f; 577 } 578 return (0); 579 } 580 581 unp_internalize(rights) 582 struct mbuf *rights; 583 { 584 register struct file **rp; 585 int oldfds = rights->m_len / sizeof (int); 586 register int i; 587 register struct file *fp; 588 589 rp = mtod(rights, struct file **); 590 for (i = 0; i < oldfds; i++) 591 if (getf(*(int *)rp++) == 0) 592 return (EBADF); 593 rp = mtod(rights, struct file **); 594 for (i = 0; i < oldfds; i++) { 595 fp = getf(*(int *)rp); 596 *rp++ = fp; 597 fp->f_count++; 598 fp->f_msgcount++; 599 unp_rights++; 600 } 601 return (0); 602 } 603 604 int unp_defer, unp_gcing; 605 int unp_mark(); 606 extern struct domain unixdomain; 607 608 unp_gc() 609 { 610 register struct file *fp; 611 register struct socket *so; 612 613 if (unp_gcing) 614 return; 615 unp_gcing = 1; 616 restart: 617 unp_defer = 0; 618 for (fp = file; fp < fileNFILE; fp++) 619 fp->f_flag &= ~(FMARK|FDEFER); 620 do { 621 for (fp = file; fp < fileNFILE; fp++) { 622 if (fp->f_count == 0) 623 continue; 624 if (fp->f_flag & FDEFER) { 625 fp->f_flag &= ~FDEFER; 626 unp_defer--; 627 } else { 628 if (fp->f_flag & FMARK) 629 continue; 630 if (fp->f_count == fp->f_msgcount) 631 continue; 632 fp->f_flag |= FMARK; 633 } 634 if (fp->f_type != DTYPE_SOCKET || 635 (so = (struct socket *)fp->f_data) == 0) 636 continue; 637 if (so->so_proto->pr_domain != &unixdomain || 638 (so->so_proto->pr_flags&PR_RIGHTS) == 0) 639 continue; 640 if (so->so_rcv.sb_flags & SB_LOCK) { 641 sbwait(&so->so_rcv); 642 goto restart; 643 } 644 unp_scan(so->so_rcv.sb_mb, unp_mark); 645 } 646 } while (unp_defer); 647 for (fp = file; fp < fileNFILE; fp++) { 648 if (fp->f_count == 0) 649 continue; 650 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0) 651 while (fp->f_msgcount) 652 unp_discard(fp); 653 } 654 unp_gcing = 0; 655 } 656 657 unp_dispose(m) 658 struct mbuf *m; 659 { 660 int unp_discard(); 661 662 if (m) 663 unp_scan(m, unp_discard); 664 } 665 666 unp_scan(m0, op) 667 register struct mbuf *m0; 668 int (*op)(); 669 { 670 register struct mbuf *m; 671 register struct file **rp; 672 register int i; 673 int qfds; 674 675 while (m0) { 676 for (m = m0; m; m = m->m_next) 677 if (m->m_type == MT_RIGHTS && m->m_len) { 678 qfds = m->m_len / sizeof (struct file *); 679 rp = mtod(m, struct file **); 680 for (i = 0; i < qfds; i++) 681 (*op)(*rp++); 682 break; /* XXX, but saves time */ 683 } 684 m0 = m0->m_act; 685 } 686 } 687 688 unp_mark(fp) 689 struct file *fp; 690 { 691 692 if (fp->f_flag & FMARK) 693 return; 694 unp_defer++; 695 fp->f_flag |= (FMARK|FDEFER); 696 } 697 698 unp_discard(fp) 699 struct file *fp; 700 { 701 702 fp->f_msgcount--; 703 unp_rights--; 704 closef(fp); 705 } 706