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