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