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