1 /* uipc_socket.c 6.10 85/04/02 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "dir.h" 6 #include "user.h" 7 #include "proc.h" 8 #include "file.h" 9 #include "inode.h" 10 #include "buf.h" 11 #include "mbuf.h" 12 #include "un.h" 13 #include "domain.h" 14 #include "protosw.h" 15 #include "socket.h" 16 #include "socketvar.h" 17 #include "stat.h" 18 #include "ioctl.h" 19 #include "uio.h" 20 #include "../net/route.h" 21 #include "../netinet/in.h" 22 #include "../net/if.h" 23 24 /* 25 * Socket operation routines. 26 * These routines are called by the routines in 27 * sys_socket.c or from a system process, and 28 * implement the semantics of socket operations by 29 * switching out to the protocol specific routines. 30 * 31 * TODO: 32 * sostat 33 * test socketpair 34 * PR_RIGHTS 35 * clean up select, async 36 * out-of-band is a kludge 37 */ 38 /*ARGSUSED*/ 39 socreate(dom, aso, type, proto) 40 struct socket **aso; 41 register int type; 42 int proto; 43 { 44 register struct protosw *prp; 45 register struct socket *so; 46 register struct mbuf *m; 47 register int error; 48 49 if (proto) 50 prp = pffindproto(dom, proto); 51 else 52 prp = pffindtype(dom, type); 53 if (prp == 0) 54 return (EPROTONOSUPPORT); 55 if (prp->pr_type != type) 56 return (EPROTOTYPE); 57 m = m_getclr(M_WAIT, MT_SOCKET); 58 if (m == 0) 59 return (ENOBUFS); 60 so = mtod(m, struct socket *); 61 so->so_options = 0; 62 so->so_state = 0; 63 so->so_type = type; 64 if (u.u_uid == 0) 65 so->so_state = SS_PRIV; 66 so->so_proto = prp; 67 error = 68 (*prp->pr_usrreq)(so, PRU_ATTACH, 69 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 70 if (error) { 71 so->so_state |= SS_NOFDREF; 72 sofree(so); 73 return (error); 74 } 75 *aso = so; 76 return (0); 77 } 78 79 sobind(so, nam) 80 struct socket *so; 81 struct mbuf *nam; 82 { 83 int s = splnet(); 84 int error; 85 86 error = 87 (*so->so_proto->pr_usrreq)(so, PRU_BIND, 88 (struct mbuf *)0, nam, (struct mbuf *)0); 89 splx(s); 90 return (error); 91 } 92 93 solisten(so, backlog) 94 register struct socket *so; 95 int backlog; 96 { 97 int s = splnet(), error; 98 99 error = 100 (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 101 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 102 if (error) { 103 splx(s); 104 return (error); 105 } 106 if (so->so_q == 0) { 107 so->so_q = so; 108 so->so_q0 = so; 109 so->so_options |= SO_ACCEPTCONN; 110 } 111 if (backlog < 0) 112 backlog = 0; 113 so->so_qlimit = MIN(backlog, SOMAXCONN); 114 splx(s); 115 return (0); 116 } 117 118 sofree(so) 119 register struct socket *so; 120 { 121 122 if (so->so_head) { 123 if (!soqremque(so, 0) && !soqremque(so, 1)) 124 panic("sofree dq"); 125 so->so_head = 0; 126 } 127 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 128 return; 129 sbrelease(&so->so_snd); 130 sorflush(so); 131 (void) m_free(dtom(so)); 132 } 133 134 /* 135 * Close a socket on last file table reference removal. 136 * Initiate disconnect if connected. 137 * Free socket when disconnect complete. 138 */ 139 soclose(so) 140 register struct socket *so; 141 { 142 int s = splnet(); /* conservative */ 143 int error; 144 145 if (so->so_options & SO_ACCEPTCONN) { 146 while (so->so_q0 != so) 147 (void) soabort(so->so_q0); 148 while (so->so_q != so) 149 (void) soabort(so->so_q); 150 } 151 if (so->so_pcb == 0) 152 goto discard; 153 if (so->so_state & SS_ISCONNECTED) { 154 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 155 error = sodisconnect(so, (struct mbuf *)0); 156 if (error) 157 goto drop; 158 } 159 if (so->so_options & SO_LINGER) { 160 if ((so->so_state & SS_ISDISCONNECTING) && 161 (so->so_state & SS_NBIO)) 162 goto drop; 163 while (so->so_state & SS_ISCONNECTED) 164 sleep((caddr_t)&so->so_timeo, PZERO+1); 165 } 166 } 167 drop: 168 if (so->so_pcb) { 169 int error2 = 170 (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 171 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 172 if (error == 0) 173 error = error2; 174 } 175 discard: 176 if (so->so_state & SS_NOFDREF) 177 panic("soclose: NOFDREF"); 178 so->so_state |= SS_NOFDREF; 179 sofree(so); 180 splx(s); 181 return (error); 182 } 183 184 /* 185 * Must be called at splnet... 186 */ 187 soabort(so) 188 struct socket *so; 189 { 190 191 return ( 192 (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 193 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 194 } 195 196 soaccept(so, nam) 197 register struct socket *so; 198 struct mbuf *nam; 199 { 200 int s = splnet(); 201 int error; 202 203 if ((so->so_state & SS_NOFDREF) == 0) 204 panic("soaccept: !NOFDREF"); 205 so->so_state &= ~SS_NOFDREF; 206 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 207 (struct mbuf *)0, nam, (struct mbuf *)0); 208 splx(s); 209 return (error); 210 } 211 212 soconnect(so, nam) 213 register struct socket *so; 214 struct mbuf *nam; 215 { 216 int s = splnet(); 217 int error; 218 219 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 220 error = EISCONN; 221 goto bad; 222 } 223 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 224 (struct mbuf *)0, nam, (struct mbuf *)0); 225 bad: 226 splx(s); 227 return (error); 228 } 229 230 soconnect2(so1, so2) 231 register struct socket *so1; 232 struct socket *so2; 233 { 234 int s = splnet(); 235 int error; 236 237 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 238 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 239 splx(s); 240 return (error); 241 } 242 243 sodisconnect(so, nam) 244 register struct socket *so; 245 struct mbuf *nam; 246 { 247 int s = splnet(); 248 int error; 249 250 if ((so->so_state & SS_ISCONNECTED) == 0) { 251 error = ENOTCONN; 252 goto bad; 253 } 254 if (so->so_state & SS_ISDISCONNECTING) { 255 error = EALREADY; 256 goto bad; 257 } 258 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 259 (struct mbuf *)0, nam, (struct mbuf *)0); 260 bad: 261 splx(s); 262 return (error); 263 } 264 265 /* 266 * Send on a socket. 267 * If send must go all at once and message is larger than 268 * send buffering, then hard error. 269 * Lock against other senders. 270 * If must go all at once and not enough room now, then 271 * inform user that this would block and do nothing. 272 * Otherwise, if nonblocking, send as much as possible. 273 */ 274 sosend(so, nam, uio, flags, rights) 275 register struct socket *so; 276 struct mbuf *nam; 277 register struct uio *uio; 278 int flags; 279 struct mbuf *rights; 280 { 281 struct mbuf *top = 0; 282 register struct mbuf *m, **mp; 283 register int space; 284 int len, error = 0, s, dontroute, first = 1; 285 286 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 287 return (EMSGSIZE); 288 dontroute = 289 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 290 (so->so_proto->pr_flags & PR_ATOMIC); 291 u.u_ru.ru_msgsnd++; 292 #define snderr(errno) { error = errno; splx(s); goto release; } 293 294 restart: 295 sblock(&so->so_snd); 296 do { 297 s = splnet(); 298 if (so->so_state & SS_CANTSENDMORE) { 299 psignal(u.u_procp, SIGPIPE); 300 snderr(EPIPE); 301 } 302 if (so->so_error) { 303 error = so->so_error; 304 so->so_error = 0; /* ??? */ 305 splx(s); 306 goto release; 307 } 308 if ((so->so_state & SS_ISCONNECTED) == 0) { 309 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 310 snderr(ENOTCONN); 311 if (nam == 0) 312 snderr(EDESTADDRREQ); 313 } 314 if (flags & MSG_OOB) 315 space = 1024; 316 else { 317 space = sbspace(&so->so_snd); 318 if (space <= 0 || 319 (sosendallatonce(so) && space < uio->uio_resid) || 320 (uio->uio_resid >= CLBYTES && space < CLBYTES && 321 so->so_snd.sb_cc >= CLBYTES && 322 (so->so_state & SS_NBIO) == 0)) { 323 if (so->so_state & SS_NBIO) { 324 if (first) 325 error = EWOULDBLOCK; 326 splx(s); 327 goto release; 328 } 329 sbunlock(&so->so_snd); 330 sbwait(&so->so_snd); 331 splx(s); 332 goto restart; 333 } 334 } 335 splx(s); 336 mp = ⊤ 337 while (uio->uio_resid > 0 && space > 0) { 338 register struct iovec *iov = uio->uio_iov; 339 340 if (iov->iov_len == 0) { 341 uio->uio_iov++; 342 uio->uio_iovcnt--; 343 if (uio->uio_iovcnt < 0) 344 panic("sosend"); 345 continue; 346 } 347 MGET(m, M_WAIT, MT_DATA); 348 if (m == NULL) { 349 error = ENOBUFS; /* SIGPIPE? */ 350 goto release; 351 } 352 if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 353 register struct mbuf *p; 354 MCLGET(p, 1); 355 if (p == 0) 356 goto nopages; 357 m->m_off = (int)p - (int)m; 358 len = CLBYTES; 359 } else { 360 nopages: 361 len = MIN(MLEN, iov->iov_len); 362 } 363 error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 364 m->m_len = len; 365 *mp = m; 366 if (error) 367 goto release; 368 mp = &m->m_next; 369 space -= len; 370 } 371 if (top) { 372 if (dontroute) 373 so->so_options |= SO_DONTROUTE; 374 s = splnet(); 375 error = (*so->so_proto->pr_usrreq)(so, 376 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 377 top, (caddr_t)nam, rights); 378 splx(s); 379 if (dontroute) 380 so->so_options &= ~SO_DONTROUTE; 381 } 382 top = 0; 383 first = 0; 384 if (error) 385 break; 386 } while (uio->uio_resid); 387 388 release: 389 sbunlock(&so->so_snd); 390 if (top) 391 m_freem(top); 392 return (error); 393 } 394 395 soreceive(so, aname, uio, flags, rightsp) 396 register struct socket *so; 397 struct mbuf **aname; 398 register struct uio *uio; 399 int flags; 400 struct mbuf **rightsp; 401 { 402 register struct mbuf *m, *n; 403 register int len, error = 0, s, tomark; 404 struct protosw *pr = so->so_proto; 405 struct mbuf *nextrecord; 406 int moff; 407 408 if (rightsp) 409 *rightsp = 0; 410 if (aname) 411 *aname = 0; 412 if (flags & MSG_OOB) { 413 m = m_get(M_WAIT, MT_DATA); 414 if (m == 0) 415 return (ENOBUFS); 416 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 417 m, (struct mbuf *)0, (struct mbuf *)0); 418 if (error) 419 goto bad; 420 do { 421 len = uio->uio_resid; 422 if (len > m->m_len) 423 len = m->m_len; 424 error = 425 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 426 m = m_free(m); 427 } while (uio->uio_resid && error == 0 && m); 428 bad: 429 if (m) 430 m_freem(m); 431 return (error); 432 } 433 434 restart: 435 sblock(&so->so_rcv); 436 s = splnet(); 437 438 #define rcverr(errno) { error = errno; splx(s); goto release; } 439 if (so->so_rcv.sb_cc == 0) { 440 if (so->so_error) { 441 error = so->so_error; 442 so->so_error = 0; 443 splx(s); 444 goto release; 445 } 446 if (so->so_state & SS_CANTRCVMORE) { 447 splx(s); 448 goto release; 449 } 450 if ((so->so_state & SS_ISCONNECTED) == 0 && 451 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 452 rcverr(ENOTCONN); 453 if (so->so_state & SS_NBIO) 454 rcverr(EWOULDBLOCK); 455 sbunlock(&so->so_rcv); 456 sbwait(&so->so_rcv); 457 splx(s); 458 goto restart; 459 } 460 u.u_ru.ru_msgrcv++; 461 m = so->so_rcv.sb_mb; 462 if (pr->pr_flags & PR_ADDR) { 463 if (m == 0 || m->m_type != MT_SONAME) 464 panic("receive 1a"); 465 if (flags & MSG_PEEK) { 466 if (aname) 467 *aname = m_copy(m, 0, m->m_len); 468 else 469 m = m->m_act; 470 } else { 471 if (aname) { 472 *aname = m; 473 sbfree(&so->so_rcv, m); 474 if(m->m_next) panic("receive 1b"); 475 so->so_rcv.sb_mb = m = m->m_act; 476 } else 477 m = sbdroprecord(&so->so_rcv); 478 } 479 } 480 if (m && m->m_type == MT_RIGHTS) { 481 if ((pr->pr_flags & PR_RIGHTS) == 0) 482 panic("receive 2a"); 483 if (flags & MSG_PEEK) { 484 if (rightsp) 485 *rightsp = m_copy(m, 0, m->m_len); 486 else 487 m = m->m_act; 488 } else { 489 if (rightsp) { 490 *rightsp = m; 491 sbfree(&so->so_rcv, m); 492 if(m->m_next) panic("receive 2b"); 493 so->so_rcv.sb_mb = m = m->m_act; 494 } else 495 m = sbdroprecord(&so->so_rcv); 496 } 497 } 498 if (m == 0) 499 panic("receive 3"); 500 moff = 0; 501 tomark = so->so_oobmark; 502 while (m && uio->uio_resid > 0 && error == 0) { 503 len = uio->uio_resid; 504 so->so_state &= ~SS_RCVATMARK; 505 if (tomark && len > tomark) 506 len = tomark; 507 if (moff+len > m->m_len - moff) 508 len = m->m_len - moff; 509 splx(s); 510 error = 511 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 512 s = splnet(); 513 if (len == m->m_len) { 514 if ((flags & MSG_PEEK) == 0) { 515 nextrecord = m->m_act; 516 sbfree(&so->so_rcv, m); 517 MFREE(m, n); 518 if (m = n) 519 m->m_act = nextrecord; 520 so->so_rcv.sb_mb = m; 521 } else 522 m = m->m_next; 523 moff = 0; 524 } else { 525 if (flags & MSG_PEEK) 526 moff += len; 527 else { 528 m->m_off += len; 529 m->m_len -= len; 530 so->so_rcv.sb_cc -= len; 531 } 532 } 533 if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 534 so->so_oobmark -= len; 535 if (so->so_oobmark == 0) { 536 so->so_state |= SS_RCVATMARK; 537 break; 538 } 539 } 540 if (tomark) { 541 tomark -= len; 542 if (tomark == 0) 543 break; 544 } 545 } 546 if ((flags & MSG_PEEK) == 0) { 547 if (m == 0) 548 so->so_rcv.sb_mb = nextrecord; 549 else if (pr->pr_flags & PR_ATOMIC) 550 (void) sbdroprecord(&so->so_rcv); 551 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 552 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 553 (struct mbuf *)0, (struct mbuf *)0); 554 } 555 release: 556 sbunlock(&so->so_rcv); 557 if (error == 0 && rightsp && *rightsp && pr->pr_domain->dom_externalize) 558 error = (*pr->pr_domain->dom_externalize)(*rightsp); 559 splx(s); 560 return (error); 561 } 562 563 soshutdown(so, how) 564 register struct socket *so; 565 register int how; 566 { 567 register struct protosw *pr = so->so_proto; 568 569 how++; 570 if (how & FREAD) 571 sorflush(so); 572 if (how & FWRITE) 573 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 574 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 575 return (0); 576 } 577 578 sorflush(so) 579 register struct socket *so; 580 { 581 register struct sockbuf *sb = &so->so_rcv; 582 register struct protosw *pr = so->so_proto; 583 register int s; 584 struct sockbuf asb; 585 586 sblock(sb); 587 s = splimp(); 588 socantrcvmore(so); 589 sbunlock(sb); 590 asb = *sb; 591 bzero((caddr_t)sb, sizeof (*sb)); 592 splx(s); 593 if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 594 (*pr->pr_domain->dom_dispose)(asb.sb_mb); 595 sbrelease(&asb); 596 } 597 598 sosetopt(so, level, optname, m0) 599 register struct socket *so; 600 int level, optname; 601 struct mbuf *m0; 602 { 603 int error = 0; 604 register struct mbuf *m = m0; 605 606 if (level != SOL_SOCKET) { 607 if (so->so_proto && so->so_proto->pr_ctloutput) 608 return ((*so->so_proto->pr_ctloutput) 609 (PRCO_SETOPT, so, level, optname, &m0)); 610 error = ENOPROTOOPT; 611 } else { 612 switch (optname) { 613 614 case SO_LINGER: 615 if (m == NULL || m->m_len != sizeof (struct linger)) { 616 error = EINVAL; 617 goto bad; 618 } 619 so->so_linger = mtod(m, struct linger *)->l_linger; 620 /* fall thru... */ 621 622 case SO_DEBUG: 623 case SO_KEEPALIVE: 624 case SO_DONTROUTE: 625 case SO_USELOOPBACK: 626 case SO_BROADCAST: 627 case SO_REUSEADDR: 628 if (m == NULL || m->m_len < sizeof (int)) { 629 error = EINVAL; 630 goto bad; 631 } 632 if (*mtod(m, int *)) 633 so->so_options |= optname; 634 else 635 so->so_options &= ~optname; 636 break; 637 638 case SO_SNDBUF: 639 case SO_RCVBUF: 640 case SO_SNDLOWAT: 641 case SO_RCVLOWAT: 642 case SO_SNDTIMEO: 643 case SO_RCVTIMEO: 644 if (m == NULL || m->m_len < sizeof (int)) { 645 error = EINVAL; 646 goto bad; 647 } 648 switch (optname) { 649 650 case SO_SNDBUF: 651 case SO_RCVBUF: 652 if (sbreserve(optname == SO_SNDBUF ? &so->so_snd : 653 &so->so_rcv, *mtod(m, int *)) == 0) { 654 error = ENOBUFS; 655 goto bad; 656 } 657 break; 658 659 case SO_SNDLOWAT: 660 so->so_snd.sb_lowat = *mtod(m, int *); 661 break; 662 case SO_RCVLOWAT: 663 so->so_rcv.sb_lowat = *mtod(m, int *); 664 break; 665 case SO_SNDTIMEO: 666 so->so_snd.sb_timeo = *mtod(m, int *); 667 break; 668 case SO_RCVTIMEO: 669 so->so_rcv.sb_timeo = *mtod(m, int *); 670 break; 671 } 672 break; 673 674 default: 675 error = ENOPROTOOPT; 676 break; 677 } 678 } 679 bad: 680 if (m) 681 (void) m_free(m); 682 return (error); 683 } 684 685 sogetopt(so, level, optname, mp) 686 register struct socket *so; 687 int level, optname; 688 struct mbuf **mp; 689 { 690 register struct mbuf *m; 691 692 if (level != SOL_SOCKET) { 693 if (so->so_proto && so->so_proto->pr_ctloutput) { 694 return ((*so->so_proto->pr_ctloutput) 695 (PRCO_GETOPT, so, level, optname, mp)); 696 } else 697 return (ENOPROTOOPT); 698 } else { 699 m = m_get(M_WAIT, MT_SOOPTS); 700 if (m == NULL) 701 return (ENOBUFS); 702 switch (optname) { 703 704 case SO_LINGER: 705 m->m_len = sizeof (struct linger); 706 mtod(m, struct linger *)->l_onoff = 707 so->so_options & SO_LINGER; 708 mtod(m, struct linger *)->l_linger = so->so_linger; 709 break; 710 711 case SO_USELOOPBACK: 712 case SO_DONTROUTE: 713 case SO_DEBUG: 714 case SO_KEEPALIVE: 715 case SO_REUSEADDR: 716 case SO_BROADCAST: 717 m->m_len = sizeof (int); 718 *mtod(m, int *) = so->so_options & optname; 719 break; 720 721 case SO_SNDBUF: 722 *mtod(m, int *) = so->so_snd.sb_hiwat; 723 break; 724 725 case SO_RCVBUF: 726 *mtod(m, int *) = so->so_rcv.sb_hiwat; 727 break; 728 729 case SO_SNDLOWAT: 730 *mtod(m, int *) = so->so_snd.sb_lowat; 731 break; 732 733 case SO_RCVLOWAT: 734 *mtod(m, int *) = so->so_rcv.sb_lowat; 735 break; 736 737 case SO_SNDTIMEO: 738 *mtod(m, int *) = so->so_snd.sb_timeo; 739 break; 740 741 case SO_RCVTIMEO: 742 *mtod(m, int *) = so->so_rcv.sb_timeo; 743 break; 744 745 default: 746 m_free(m); 747 return (ENOPROTOOPT); 748 } 749 *mp = m; 750 return (0); 751 } 752 } 753 754 sohasoutofband(so) 755 register struct socket *so; 756 { 757 758 if (so->so_pgrp == 0) 759 return; 760 if (so->so_pgrp > 0) 761 gsignal(so->so_pgrp, SIGURG); 762 else { 763 struct proc *p = pfind(-so->so_pgrp); 764 765 if (p) 766 psignal(p, SIGURG); 767 } 768 } 769