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.6 (Berkeley) 05/25/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 u_long unpst_sendspace = PIPSIZ; 286 u_long unpst_recvspace = PIPSIZ; 287 u_long unpdg_sendspace = 2*1024; /* really max datagram size */ 288 u_long 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 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 300 switch (so->so_type) { 301 302 case SOCK_STREAM: 303 error = soreserve(so, unpst_sendspace, unpst_recvspace); 304 break; 305 306 case SOCK_DGRAM: 307 error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 308 break; 309 } 310 if (error) 311 return (error); 312 } 313 m = m_getclr(M_DONTWAIT, MT_PCB); 314 if (m == NULL) 315 return (ENOBUFS); 316 unp = mtod(m, struct unpcb *); 317 so->so_pcb = (caddr_t)unp; 318 unp->unp_socket = so; 319 return (0); 320 } 321 322 unp_detach(unp) 323 register struct unpcb *unp; 324 { 325 326 if (unp->unp_inode) { 327 unp->unp_inode->i_socket = 0; 328 irele(unp->unp_inode); 329 unp->unp_inode = 0; 330 } 331 if (unp->unp_conn) 332 unp_disconnect(unp); 333 while (unp->unp_refs) 334 unp_drop(unp->unp_refs, ECONNRESET); 335 soisdisconnected(unp->unp_socket); 336 unp->unp_socket->so_pcb = 0; 337 m_freem(unp->unp_addr); 338 (void) m_free(dtom(unp)); 339 if (unp_rights) 340 unp_gc(); 341 } 342 343 unp_bind(unp, nam) 344 struct unpcb *unp; 345 struct mbuf *nam; 346 { 347 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 348 register struct inode *ip; 349 register struct nameidata *ndp = &u.u_nd; 350 int error; 351 352 ndp->ni_dirp = soun->sun_path; 353 if (unp->unp_inode != NULL || nam->m_len == MLEN) 354 return (EINVAL); 355 *(mtod(nam, caddr_t) + nam->m_len) = 0; 356 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 357 ndp->ni_nameiop = CREATE | FOLLOW; 358 ndp->ni_segflg = UIO_SYSSPACE; 359 ip = namei(ndp); 360 if (ip) { 361 iput(ip); 362 return (EADDRINUSE); 363 } 364 if (error = u.u_error) { 365 u.u_error = 0; /* XXX */ 366 return (error); 367 } 368 ip = maknode(IFSOCK | 0777, ndp); 369 if (ip == NULL) { 370 error = u.u_error; /* XXX */ 371 u.u_error = 0; /* XXX */ 372 return (error); 373 } 374 ip->i_socket = unp->unp_socket; 375 unp->unp_inode = ip; 376 unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); 377 iunlock(ip); /* but keep reference */ 378 return (0); 379 } 380 381 unp_connect(so, nam) 382 struct socket *so; 383 struct mbuf *nam; 384 { 385 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 386 register struct inode *ip; 387 register struct socket *so2, *so3; 388 register struct nameidata *ndp = &u.u_nd; 389 struct unpcb *unp2, *unp3; 390 int error; 391 392 ndp->ni_dirp = soun->sun_path; 393 if (nam->m_len + (nam->m_off - MMINOFF) == MLEN) 394 return (EMSGSIZE); 395 *(mtod(nam, caddr_t) + nam->m_len) = 0; 396 ndp->ni_nameiop = LOOKUP | FOLLOW; 397 ndp->ni_segflg = UIO_SYSSPACE; 398 ip = namei(ndp); 399 if (ip == 0) { 400 error = u.u_error; 401 u.u_error = 0; 402 return (error); /* XXX */ 403 } 404 if (access(ip, IWRITE)) { 405 error = u.u_error; 406 u.u_error = 0; /* XXX */ 407 goto bad; 408 } 409 if ((ip->i_mode&IFMT) != IFSOCK) { 410 error = ENOTSOCK; 411 goto bad; 412 } 413 so2 = ip->i_socket; 414 if (so2 == 0) { 415 error = ECONNREFUSED; 416 goto bad; 417 } 418 if (so->so_type != so2->so_type) { 419 error = EPROTOTYPE; 420 goto bad; 421 } 422 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 423 if ((so2->so_options & SO_ACCEPTCONN) == 0 || 424 (so3 = sonewconn(so2)) == 0) { 425 error = ECONNREFUSED; 426 goto bad; 427 } 428 unp2 = sotounpcb(so2); 429 unp3 = sotounpcb(so3); 430 if (unp2->unp_addr) 431 unp3->unp_addr = m_copy(unp2->unp_addr, 0, M_COPYALL); 432 so2 = so3; 433 } 434 error = unp_connect2(so, so2); 435 bad: 436 iput(ip); 437 return (error); 438 } 439 440 unp_connect2(so, so2) 441 register struct socket *so; 442 register struct socket *so2; 443 { 444 register struct unpcb *unp = sotounpcb(so); 445 register struct unpcb *unp2; 446 447 if (so2->so_type != so->so_type) 448 return (EPROTOTYPE); 449 unp2 = sotounpcb(so2); 450 unp->unp_conn = unp2; 451 switch (so->so_type) { 452 453 case SOCK_DGRAM: 454 unp->unp_nextref = unp2->unp_refs; 455 unp2->unp_refs = unp; 456 soisconnected(so); 457 break; 458 459 case SOCK_STREAM: 460 unp2->unp_conn = unp; 461 soisconnected(so2); 462 soisconnected(so); 463 break; 464 465 default: 466 panic("unp_connect2"); 467 } 468 return (0); 469 } 470 471 unp_disconnect(unp) 472 struct unpcb *unp; 473 { 474 register struct unpcb *unp2 = unp->unp_conn; 475 476 if (unp2 == 0) 477 return; 478 unp->unp_conn = 0; 479 switch (unp->unp_socket->so_type) { 480 481 case SOCK_DGRAM: 482 if (unp2->unp_refs == unp) 483 unp2->unp_refs = unp->unp_nextref; 484 else { 485 unp2 = unp2->unp_refs; 486 for (;;) { 487 if (unp2 == 0) 488 panic("unp_disconnect"); 489 if (unp2->unp_nextref == unp) 490 break; 491 unp2 = unp2->unp_nextref; 492 } 493 unp2->unp_nextref = unp->unp_nextref; 494 } 495 unp->unp_nextref = 0; 496 unp->unp_socket->so_state &= ~SS_ISCONNECTED; 497 break; 498 499 case SOCK_STREAM: 500 soisdisconnected(unp->unp_socket); 501 unp2->unp_conn = 0; 502 soisdisconnected(unp2->unp_socket); 503 break; 504 } 505 } 506 507 #ifdef notdef 508 unp_abort(unp) 509 struct unpcb *unp; 510 { 511 512 unp_detach(unp); 513 } 514 #endif 515 516 /*ARGSUSED*/ 517 unp_usrclosed(unp) 518 struct unpcb *unp; 519 { 520 521 } 522 523 unp_drop(unp, errno) 524 struct unpcb *unp; 525 int errno; 526 { 527 struct socket *so = unp->unp_socket; 528 529 so->so_error = errno; 530 unp_disconnect(unp); 531 if (so->so_head) { 532 so->so_pcb = (caddr_t) 0; 533 m_freem(unp->unp_addr); 534 (void) m_free(dtom(unp)); 535 sofree(so); 536 } 537 } 538 539 #ifdef notdef 540 unp_drain() 541 { 542 543 } 544 #endif 545 546 unp_externalize(rights) 547 struct mbuf *rights; 548 { 549 int newfds = rights->m_len / sizeof (int); 550 register int i; 551 register struct file **rp = mtod(rights, struct file **); 552 register struct file *fp; 553 int f; 554 555 if (newfds > ufavail()) { 556 for (i = 0; i < newfds; i++) { 557 fp = *rp; 558 unp_discard(fp); 559 *rp++ = 0; 560 } 561 return (EMSGSIZE); 562 } 563 for (i = 0; i < newfds; i++) { 564 f = ufalloc(0); 565 if (f < 0) 566 panic("unp_externalize"); 567 fp = *rp; 568 u.u_ofile[f] = fp; 569 fp->f_msgcount--; 570 unp_rights--; 571 *(int *)rp++ = f; 572 } 573 return (0); 574 } 575 576 unp_internalize(rights) 577 struct mbuf *rights; 578 { 579 register struct file **rp; 580 int oldfds = rights->m_len / sizeof (int); 581 register int i; 582 register struct file *fp; 583 584 rp = mtod(rights, struct file **); 585 for (i = 0; i < oldfds; i++) 586 if (getf(*(int *)rp++) == 0) 587 return (EBADF); 588 rp = mtod(rights, struct file **); 589 for (i = 0; i < oldfds; i++) { 590 fp = getf(*(int *)rp); 591 *rp++ = fp; 592 fp->f_count++; 593 fp->f_msgcount++; 594 unp_rights++; 595 } 596 return (0); 597 } 598 599 int unp_defer, unp_gcing; 600 int unp_mark(); 601 extern struct domain unixdomain; 602 603 unp_gc() 604 { 605 register struct file *fp; 606 register struct socket *so; 607 608 if (unp_gcing) 609 return; 610 unp_gcing = 1; 611 restart: 612 unp_defer = 0; 613 for (fp = file; fp < fileNFILE; fp++) 614 fp->f_flag &= ~(FMARK|FDEFER); 615 do { 616 for (fp = file; fp < fileNFILE; fp++) { 617 if (fp->f_count == 0) 618 continue; 619 if (fp->f_flag & FDEFER) { 620 fp->f_flag &= ~FDEFER; 621 unp_defer--; 622 } else { 623 if (fp->f_flag & FMARK) 624 continue; 625 if (fp->f_count == fp->f_msgcount) 626 continue; 627 fp->f_flag |= FMARK; 628 } 629 if (fp->f_type != DTYPE_SOCKET || 630 (so = (struct socket *)fp->f_data) == 0) 631 continue; 632 if (so->so_proto->pr_domain != &unixdomain || 633 (so->so_proto->pr_flags&PR_RIGHTS) == 0) 634 continue; 635 if (so->so_rcv.sb_flags & SB_LOCK) { 636 sbwait(&so->so_rcv); 637 goto restart; 638 } 639 unp_scan(so->so_rcv.sb_mb, unp_mark); 640 } 641 } while (unp_defer); 642 for (fp = file; fp < fileNFILE; fp++) { 643 if (fp->f_count == 0) 644 continue; 645 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0) 646 while (fp->f_msgcount) 647 unp_discard(fp); 648 } 649 unp_gcing = 0; 650 } 651 652 unp_dispose(m) 653 struct mbuf *m; 654 { 655 int unp_discard(); 656 657 if (m) 658 unp_scan(m, unp_discard); 659 } 660 661 unp_scan(m0, op) 662 register struct mbuf *m0; 663 int (*op)(); 664 { 665 register struct mbuf *m; 666 register struct file **rp; 667 register int i; 668 int qfds; 669 670 while (m0) { 671 for (m = m0; m; m = m->m_next) 672 if (m->m_type == MT_RIGHTS && m->m_len) { 673 qfds = m->m_len / sizeof (struct file *); 674 rp = mtod(m, struct file **); 675 for (i = 0; i < qfds; i++) 676 (*op)(*rp++); 677 break; /* XXX, but saves time */ 678 } 679 m0 = m0->m_act; 680 } 681 } 682 683 unp_mark(fp) 684 struct file *fp; 685 { 686 687 if (fp->f_flag & FMARK) 688 return; 689 unp_defer++; 690 fp->f_flag |= (FMARK|FDEFER); 691 } 692 693 unp_discard(fp) 694 struct file *fp; 695 { 696 697 fp->f_msgcount--; 698 unp_rights--; 699 closef(fp); 700 } 701