1 /* uipc_socket.c 6.14 85/06/08 */ 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 * test socketpair 33 * clean up async 34 * out-of-band is a kludge 35 */ 36 /*ARGSUSED*/ 37 socreate(dom, aso, type, proto) 38 struct socket **aso; 39 register int type; 40 int proto; 41 { 42 register struct protosw *prp; 43 register struct socket *so; 44 register struct mbuf *m; 45 register int error; 46 47 if (proto) 48 prp = pffindproto(dom, proto, type); 49 else 50 prp = pffindtype(dom, type); 51 if (prp == 0) 52 return (EPROTONOSUPPORT); 53 if (prp->pr_type != type) 54 return (EPROTOTYPE); 55 m = m_getclr(M_WAIT, MT_SOCKET); 56 so = mtod(m, struct socket *); 57 so->so_options = 0; 58 so->so_state = 0; 59 so->so_type = type; 60 if (u.u_uid == 0) 61 so->so_state = SS_PRIV; 62 so->so_proto = prp; 63 error = 64 (*prp->pr_usrreq)(so, PRU_ATTACH, 65 (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0); 66 if (error) { 67 so->so_state |= SS_NOFDREF; 68 sofree(so); 69 return (error); 70 } 71 *aso = so; 72 return (0); 73 } 74 75 sobind(so, nam) 76 struct socket *so; 77 struct mbuf *nam; 78 { 79 int s = splnet(); 80 int error; 81 82 error = 83 (*so->so_proto->pr_usrreq)(so, PRU_BIND, 84 (struct mbuf *)0, nam, (struct mbuf *)0); 85 splx(s); 86 return (error); 87 } 88 89 solisten(so, backlog) 90 register struct socket *so; 91 int backlog; 92 { 93 int s = splnet(), error; 94 95 error = 96 (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 97 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 98 if (error) { 99 splx(s); 100 return (error); 101 } 102 if (so->so_q == 0) { 103 so->so_q = so; 104 so->so_q0 = so; 105 so->so_options |= SO_ACCEPTCONN; 106 } 107 if (backlog < 0) 108 backlog = 0; 109 so->so_qlimit = MIN(backlog, SOMAXCONN); 110 splx(s); 111 return (0); 112 } 113 114 sofree(so) 115 register struct socket *so; 116 { 117 118 if (so->so_head) { 119 if (!soqremque(so, 0) && !soqremque(so, 1)) 120 panic("sofree dq"); 121 so->so_head = 0; 122 } 123 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 124 return; 125 sbrelease(&so->so_snd); 126 sorflush(so); 127 (void) m_free(dtom(so)); 128 } 129 130 /* 131 * Close a socket on last file table reference removal. 132 * Initiate disconnect if connected. 133 * Free socket when disconnect complete. 134 */ 135 soclose(so) 136 register struct socket *so; 137 { 138 int s = splnet(); /* conservative */ 139 int error; 140 141 if (so->so_options & SO_ACCEPTCONN) { 142 while (so->so_q0 != so) 143 (void) soabort(so->so_q0); 144 while (so->so_q != so) 145 (void) soabort(so->so_q); 146 } 147 if (so->so_pcb == 0) 148 goto discard; 149 if (so->so_state & SS_ISCONNECTED) { 150 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 151 error = sodisconnect(so, (struct mbuf *)0); 152 if (error) 153 goto drop; 154 } 155 if (so->so_options & SO_LINGER) { 156 if ((so->so_state & SS_ISDISCONNECTING) && 157 (so->so_state & SS_NBIO)) 158 goto drop; 159 while (so->so_state & SS_ISCONNECTED) 160 sleep((caddr_t)&so->so_timeo, PZERO+1); 161 } 162 } 163 drop: 164 if (so->so_pcb) { 165 int error2 = 166 (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 167 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 168 if (error == 0) 169 error = error2; 170 } 171 discard: 172 if (so->so_state & SS_NOFDREF) 173 panic("soclose: NOFDREF"); 174 so->so_state |= SS_NOFDREF; 175 sofree(so); 176 splx(s); 177 return (error); 178 } 179 180 /* 181 * Must be called at splnet... 182 */ 183 soabort(so) 184 struct socket *so; 185 { 186 187 return ( 188 (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 189 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 190 } 191 192 soaccept(so, nam) 193 register struct socket *so; 194 struct mbuf *nam; 195 { 196 int s = splnet(); 197 int error; 198 199 if ((so->so_state & SS_NOFDREF) == 0) 200 panic("soaccept: !NOFDREF"); 201 so->so_state &= ~SS_NOFDREF; 202 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 203 (struct mbuf *)0, nam, (struct mbuf *)0); 204 splx(s); 205 return (error); 206 } 207 208 soconnect(so, nam) 209 register struct socket *so; 210 struct mbuf *nam; 211 { 212 int s = splnet(); 213 int error; 214 215 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 216 error = EISCONN; 217 goto bad; 218 } 219 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 220 (struct mbuf *)0, nam, (struct mbuf *)0); 221 bad: 222 splx(s); 223 return (error); 224 } 225 226 soconnect2(so1, so2) 227 register struct socket *so1; 228 struct socket *so2; 229 { 230 int s = splnet(); 231 int error; 232 233 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 234 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 235 splx(s); 236 return (error); 237 } 238 239 sodisconnect(so, nam) 240 register struct socket *so; 241 struct mbuf *nam; 242 { 243 int s = splnet(); 244 int error; 245 246 if ((so->so_state & SS_ISCONNECTED) == 0) { 247 error = ENOTCONN; 248 goto bad; 249 } 250 if (so->so_state & SS_ISDISCONNECTING) { 251 error = EALREADY; 252 goto bad; 253 } 254 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 255 (struct mbuf *)0, nam, (struct mbuf *)0); 256 bad: 257 splx(s); 258 return (error); 259 } 260 261 /* 262 * Send on a socket. 263 * If send must go all at once and message is larger than 264 * send buffering, then hard error. 265 * Lock against other senders. 266 * If must go all at once and not enough room now, then 267 * inform user that this would block and do nothing. 268 * Otherwise, if nonblocking, send as much as possible. 269 */ 270 sosend(so, nam, uio, flags, rights) 271 register struct socket *so; 272 struct mbuf *nam; 273 register struct uio *uio; 274 int flags; 275 struct mbuf *rights; 276 { 277 struct mbuf *top = 0; 278 register struct mbuf *m, **mp; 279 register int space; 280 int len, error = 0, s, dontroute, first = 1; 281 282 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 283 return (EMSGSIZE); 284 dontroute = 285 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 286 (so->so_proto->pr_flags & PR_ATOMIC); 287 u.u_ru.ru_msgsnd++; 288 #define snderr(errno) { error = errno; splx(s); goto release; } 289 290 restart: 291 sblock(&so->so_snd); 292 do { 293 s = splnet(); 294 if (so->so_state & SS_CANTSENDMORE) 295 snderr(EPIPE); 296 if (so->so_error) { 297 error = so->so_error; 298 so->so_error = 0; /* ??? */ 299 splx(s); 300 goto release; 301 } 302 if ((so->so_state & SS_ISCONNECTED) == 0) { 303 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 304 snderr(ENOTCONN); 305 if (nam == 0) 306 snderr(EDESTADDRREQ); 307 } 308 if (flags & MSG_OOB) 309 space = 1024; 310 else { 311 space = sbspace(&so->so_snd); 312 if (space <= 0 || 313 (sosendallatonce(so) && space < uio->uio_resid) || 314 (uio->uio_resid >= CLBYTES && space < CLBYTES && 315 so->so_snd.sb_cc >= CLBYTES && 316 (so->so_state & SS_NBIO) == 0)) { 317 if (so->so_state & SS_NBIO) { 318 if (first) 319 error = EWOULDBLOCK; 320 splx(s); 321 goto release; 322 } 323 sbunlock(&so->so_snd); 324 sbwait(&so->so_snd); 325 splx(s); 326 goto restart; 327 } 328 } 329 splx(s); 330 mp = ⊤ 331 while (space > 0) { 332 register struct iovec *iov = uio->uio_iov; 333 334 MGET(m, M_WAIT, MT_DATA); 335 if (iov->iov_len >= NBPG && space >= CLBYTES) { 336 register struct mbuf *p; 337 MCLGET(p, 1); 338 if (p == 0) 339 goto nopages; 340 m->m_off = (int)p - (int)m; 341 len = min(CLBYTES, iov->iov_len); 342 space -= CLBYTES; 343 } else { 344 nopages: 345 len = MIN(MLEN, iov->iov_len); 346 space -= 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 if (uio->uio_resid <= 0) 355 break; 356 while (uio->uio_iov->iov_len == 0) { 357 uio->uio_iov++; 358 uio->uio_iovcnt--; 359 if (uio->uio_iovcnt <= 0) 360 panic("sosend"); 361 } 362 } 363 if (dontroute) 364 so->so_options |= SO_DONTROUTE; 365 s = splnet(); /* XXX */ 366 error = (*so->so_proto->pr_usrreq)(so, 367 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 368 top, (caddr_t)nam, rights); 369 splx(s); 370 if (dontroute) 371 so->so_options &= ~SO_DONTROUTE; 372 rights = 0; 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 || (m->m_type != MT_DATA && m->m_type != MT_HEADER)) 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 (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 - moff) { 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 struct proc *p; 747 748 if (so->so_pgrp < 0) 749 gsignal(-so->so_pgrp, SIGURG); 750 else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 751 psignal(p, SIGURG); 752 } 753