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.2.1.1 (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 = { 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 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 } 261 break; 262 263 case PRU_SLOWTIMO: 264 break; 265 266 default: 267 panic("piusrreq"); 268 } 269 release: 270 if (m) 271 m_freem(m); 272 return (error); 273 } 274 275 /* 276 * Both send and receive buffers are allocated PIPSIZ bytes of buffering 277 * for stream sockets, although the total for sender and receiver is 278 * actually only PIPSIZ. 279 * Datagram sockets really use the sendspace as the maximum datagram size, 280 * and don't really want to reserve the sendspace. Their recvspace should 281 * be large enough for at least one max-size datagram plus address. 282 */ 283 #define PIPSIZ 4096 284 int unpst_sendspace = PIPSIZ; 285 int unpst_recvspace = PIPSIZ; 286 int unpdg_sendspace = 2*1024; /* really max datagram size */ 287 int unpdg_recvspace = 4*1024; 288 289 int unp_rights; /* file descriptors in flight */ 290 291 unp_attach(so) 292 struct socket *so; 293 { 294 register struct mbuf *m; 295 register struct unpcb *unp; 296 int error; 297 298 switch (so->so_type) { 299 300 case SOCK_STREAM: 301 error = soreserve(so, unpst_sendspace, unpst_recvspace); 302 break; 303 304 case SOCK_DGRAM: 305 error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 306 break; 307 } 308 if (error) 309 return (error); 310 m = m_getclr(M_DONTWAIT, MT_PCB); 311 if (m == NULL) 312 return (ENOBUFS); 313 unp = mtod(m, struct unpcb *); 314 so->so_pcb = (caddr_t)unp; 315 unp->unp_socket = so; 316 return (0); 317 } 318 319 unp_detach(unp) 320 register struct unpcb *unp; 321 { 322 323 if (unp->unp_vnode) { 324 unp->unp_vnode->v_socket = 0; 325 vrele(unp->unp_vnode); 326 unp->unp_vnode = 0; 327 } 328 if (unp->unp_conn) 329 unp_disconnect(unp); 330 while (unp->unp_refs) 331 unp_drop(unp->unp_refs, ECONNRESET); 332 soisdisconnected(unp->unp_socket); 333 unp->unp_socket->so_pcb = 0; 334 m_freem(unp->unp_addr); 335 (void) m_free(dtom(unp)); 336 if (unp_rights) 337 unp_gc(); 338 } 339 340 unp_bind(unp, nam) 341 struct unpcb *unp; 342 struct mbuf *nam; 343 { 344 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 345 register struct vnode *vp; 346 register struct nameidata *ndp = &u.u_nd; 347 struct vattr vattr; 348 int error; 349 350 ndp->ni_dirp = soun->sun_path; 351 if (unp->unp_vnode != 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 | LOCKPARENT; 356 ndp->ni_segflg = UIO_SYSSPACE; 357 if (error = namei(ndp)) 358 return (error); 359 vp = ndp->ni_vp; 360 if (vp != NULL) { 361 vop_abortop(ndp); 362 return (EADDRINUSE); 363 } 364 vattr_null(&vattr); 365 vattr.va_type = VSOCK; 366 vattr.va_mode = 0777; 367 if (error = vop_create(ndp, &vattr)) 368 return (error); 369 vp = ndp->ni_vp; 370 vp->v_socket = unp->unp_socket; 371 unp->unp_vnode = vp; 372 unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); 373 vop_unlock(vp); 374 return (0); 375 } 376 377 unp_connect(so, nam) 378 struct socket *so; 379 struct mbuf *nam; 380 { 381 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 382 register struct vnode *vp; 383 int error; 384 register struct socket *so2; 385 register struct nameidata *ndp = &u.u_nd; 386 387 ndp->ni_dirp = soun->sun_path; 388 if (nam->m_len + (nam->m_off - MMINOFF) == MLEN) 389 return (EMSGSIZE); 390 *(mtod(nam, caddr_t) + nam->m_len) = 0; 391 ndp->ni_nameiop = LOOKUP | FOLLOW; 392 ndp->ni_segflg = UIO_SYSSPACE; 393 if (error = namei(ndp)) 394 return (error); 395 vp = ndp->ni_vp; 396 if (error = vn_access(vp, VWRITE, u.u_cred)) 397 goto bad; 398 if (vp->v_type != VSOCK) { 399 error = ENOTSOCK; 400 goto bad; 401 } 402 so2 = vp->v_socket; 403 if (so2 == 0) { 404 error = ECONNREFUSED; 405 goto bad; 406 } 407 if (so->so_type != so2->so_type) { 408 error = EPROTOTYPE; 409 goto bad; 410 } 411 if (so->so_proto->pr_flags & PR_CONNREQUIRED && 412 ((so2->so_options&SO_ACCEPTCONN) == 0 || 413 (so2 = sonewconn(so2)) == 0)) { 414 error = ECONNREFUSED; 415 goto bad; 416 } 417 error = unp_connect2(so, so2); 418 bad: 419 vrele(vp); 420 return (error); 421 } 422 423 unp_connect2(so, so2) 424 register struct socket *so; 425 register struct socket *so2; 426 { 427 register struct unpcb *unp = sotounpcb(so); 428 register struct unpcb *unp2; 429 430 if (so2->so_type != so->so_type) 431 return (EPROTOTYPE); 432 unp2 = sotounpcb(so2); 433 unp->unp_conn = unp2; 434 switch (so->so_type) { 435 436 case SOCK_DGRAM: 437 unp->unp_nextref = unp2->unp_refs; 438 unp2->unp_refs = unp; 439 soisconnected(so); 440 break; 441 442 case SOCK_STREAM: 443 unp2->unp_conn = unp; 444 soisconnected(so2); 445 soisconnected(so); 446 break; 447 448 default: 449 panic("unp_connect2"); 450 } 451 return (0); 452 } 453 454 unp_disconnect(unp) 455 struct unpcb *unp; 456 { 457 register struct unpcb *unp2 = unp->unp_conn; 458 459 if (unp2 == 0) 460 return; 461 unp->unp_conn = 0; 462 switch (unp->unp_socket->so_type) { 463 464 case SOCK_DGRAM: 465 if (unp2->unp_refs == unp) 466 unp2->unp_refs = unp->unp_nextref; 467 else { 468 unp2 = unp2->unp_refs; 469 for (;;) { 470 if (unp2 == 0) 471 panic("unp_disconnect"); 472 if (unp2->unp_nextref == unp) 473 break; 474 unp2 = unp2->unp_nextref; 475 } 476 unp2->unp_nextref = unp->unp_nextref; 477 } 478 unp->unp_nextref = 0; 479 unp->unp_socket->so_state &= ~SS_ISCONNECTED; 480 break; 481 482 case SOCK_STREAM: 483 soisdisconnected(unp->unp_socket); 484 unp2->unp_conn = 0; 485 soisdisconnected(unp2->unp_socket); 486 break; 487 } 488 } 489 490 #ifdef notdef 491 unp_abort(unp) 492 struct unpcb *unp; 493 { 494 495 unp_detach(unp); 496 } 497 #endif 498 499 /*ARGSUSED*/ 500 unp_usrclosed(unp) 501 struct unpcb *unp; 502 { 503 504 } 505 506 unp_drop(unp, errno) 507 struct unpcb *unp; 508 int errno; 509 { 510 struct socket *so = unp->unp_socket; 511 512 so->so_error = errno; 513 unp_disconnect(unp); 514 if (so->so_head) { 515 so->so_pcb = (caddr_t) 0; 516 m_freem(unp->unp_addr); 517 (void) m_free(dtom(unp)); 518 sofree(so); 519 } 520 } 521 522 #ifdef notdef 523 unp_drain() 524 { 525 526 } 527 #endif 528 529 unp_externalize(rights) 530 struct mbuf *rights; 531 { 532 int newfds = rights->m_len / sizeof (int); 533 register int i; 534 register struct file **rp = mtod(rights, struct file **); 535 register struct file *fp; 536 int f; 537 538 if (newfds > ufavail()) { 539 for (i = 0; i < newfds; i++) { 540 fp = *rp; 541 unp_discard(fp); 542 *rp++ = 0; 543 } 544 return (EMSGSIZE); 545 } 546 for (i = 0; i < newfds; i++) { 547 if (ufalloc(0, &f)) 548 panic("unp_externalize"); 549 fp = *rp; 550 u.u_ofile[f] = fp; 551 fp->f_msgcount--; 552 unp_rights--; 553 *(int *)rp++ = f; 554 } 555 return (0); 556 } 557 558 unp_internalize(rights) 559 struct mbuf *rights; 560 { 561 register struct file **rp; 562 int oldfds = rights->m_len / sizeof (int); 563 register int i; 564 register struct file *fp; 565 566 rp = mtod(rights, struct file **); 567 for (i = 0; i < oldfds; i++) 568 if (getf(*(int *)rp++) == 0) 569 return (EBADF); 570 rp = mtod(rights, struct file **); 571 for (i = 0; i < oldfds; i++) { 572 fp = getf(*(int *)rp); 573 *rp++ = fp; 574 fp->f_count++; 575 fp->f_msgcount++; 576 unp_rights++; 577 } 578 return (0); 579 } 580 581 int unp_defer, unp_gcing; 582 int unp_mark(); 583 extern struct domain unixdomain; 584 585 unp_gc() 586 { 587 register struct file *fp; 588 register struct socket *so; 589 590 if (unp_gcing) 591 return; 592 unp_gcing = 1; 593 restart: 594 unp_defer = 0; 595 for (fp = file; fp < fileNFILE; fp++) 596 fp->f_flag &= ~(FMARK|FDEFER); 597 do { 598 for (fp = file; fp < fileNFILE; fp++) { 599 if (fp->f_count == 0) 600 continue; 601 if (fp->f_flag & FDEFER) { 602 fp->f_flag &= ~FDEFER; 603 unp_defer--; 604 } else { 605 if (fp->f_flag & FMARK) 606 continue; 607 if (fp->f_count == fp->f_msgcount) 608 continue; 609 fp->f_flag |= FMARK; 610 } 611 if (fp->f_type != DTYPE_SOCKET) 612 continue; 613 so = (struct socket *)fp->f_data; 614 if (so->so_proto->pr_domain != &unixdomain || 615 (so->so_proto->pr_flags&PR_RIGHTS) == 0) 616 continue; 617 if (so->so_rcv.sb_flags & SB_LOCK) { 618 sbwait(&so->so_rcv); 619 goto restart; 620 } 621 unp_scan(so->so_rcv.sb_mb, unp_mark); 622 } 623 } while (unp_defer); 624 for (fp = file; fp < fileNFILE; fp++) { 625 if (fp->f_count == 0) 626 continue; 627 if (fp->f_count == fp->f_msgcount && (fp->f_flag & FMARK) == 0) 628 while (fp->f_msgcount) 629 unp_discard(fp); 630 } 631 unp_gcing = 0; 632 } 633 634 unp_dispose(m) 635 struct mbuf *m; 636 { 637 int unp_discard(); 638 639 if (m) 640 unp_scan(m, unp_discard); 641 } 642 643 unp_scan(m0, op) 644 register struct mbuf *m0; 645 int (*op)(); 646 { 647 register struct mbuf *m; 648 register struct file **rp; 649 register int i; 650 int qfds; 651 652 while (m0) { 653 for (m = m0; m; m = m->m_next) 654 if (m->m_type == MT_RIGHTS && m->m_len) { 655 qfds = m->m_len / sizeof (struct file *); 656 rp = mtod(m, struct file **); 657 for (i = 0; i < qfds; i++) 658 (*op)(*rp++); 659 break; /* XXX, but saves time */ 660 } 661 m0 = m0->m_act; 662 } 663 } 664 665 unp_mark(fp) 666 struct file *fp; 667 { 668 669 if (fp->f_flag & FMARK) 670 return; 671 unp_defer++; 672 fp->f_flag |= (FMARK|FDEFER); 673 } 674 675 unp_discard(fp) 676 struct file *fp; 677 { 678 679 fp->f_msgcount--; 680 unp_rights--; 681 closef(fp); 682 } 683