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