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