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.17 (Berkeley) 09/16/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 /* 222 * If protocol is connection-based, can only connect once. 223 * Otherwise, if connected, try to disconnect first. 224 * This allows user to disconnect by connecting to, e.g., 225 * a null address. 226 */ 227 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && 228 ((so->so_proto->pr_flags & PR_CONNREQUIRED) || 229 (error = sodisconnect(so)))) 230 error = EISCONN; 231 else 232 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 233 (struct mbuf *)0, nam, (struct mbuf *)0); 234 splx(s); 235 return (error); 236 } 237 238 soconnect2(so1, so2) 239 register struct socket *so1; 240 struct socket *so2; 241 { 242 int s = splnet(); 243 int error; 244 245 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 246 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 247 splx(s); 248 return (error); 249 } 250 251 sodisconnect(so, nam) 252 register struct socket *so; 253 struct mbuf *nam; 254 { 255 int s = splnet(); 256 int error; 257 258 if ((so->so_state & SS_ISCONNECTED) == 0) { 259 error = ENOTCONN; 260 goto bad; 261 } 262 if (so->so_state & SS_ISDISCONNECTING) { 263 error = EALREADY; 264 goto bad; 265 } 266 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 267 (struct mbuf *)0, nam, (struct mbuf *)0); 268 bad: 269 splx(s); 270 return (error); 271 } 272 273 /* 274 * Send on a socket. 275 * If send must go all at once and message is larger than 276 * send buffering, then hard error. 277 * Lock against other senders. 278 * If must go all at once and not enough room now, then 279 * inform user that this would block and do nothing. 280 * Otherwise, if nonblocking, send as much as possible. 281 */ 282 sosend(so, nam, uio, flags, rights) 283 register struct socket *so; 284 struct mbuf *nam; 285 register struct uio *uio; 286 int flags; 287 struct mbuf *rights; 288 { 289 struct mbuf *top = 0; 290 register struct mbuf *m, **mp; 291 register int space; 292 int len, error = 0, s, dontroute, first = 1; 293 294 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 295 return (EMSGSIZE); 296 dontroute = 297 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 298 (so->so_proto->pr_flags & PR_ATOMIC); 299 u.u_ru.ru_msgsnd++; 300 #define snderr(errno) { error = errno; splx(s); goto release; } 301 302 restart: 303 sblock(&so->so_snd); 304 do { 305 s = splnet(); 306 if (so->so_state & SS_CANTSENDMORE) 307 snderr(EPIPE); 308 if (so->so_error) { 309 error = so->so_error; 310 so->so_error = 0; /* ??? */ 311 splx(s); 312 goto release; 313 } 314 if ((so->so_state & SS_ISCONNECTED) == 0) { 315 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 316 snderr(ENOTCONN); 317 if (nam == 0) 318 snderr(EDESTADDRREQ); 319 } 320 if (flags & MSG_OOB) 321 space = 1024; 322 else { 323 space = sbspace(&so->so_snd); 324 if (space <= 0 || 325 (sosendallatonce(so) && space < uio->uio_resid) || 326 (uio->uio_resid >= CLBYTES && space < CLBYTES && 327 so->so_snd.sb_cc >= CLBYTES && 328 (so->so_state & SS_NBIO) == 0)) { 329 if (so->so_state & SS_NBIO) { 330 if (first) 331 error = EWOULDBLOCK; 332 splx(s); 333 goto release; 334 } 335 sbunlock(&so->so_snd); 336 sbwait(&so->so_snd); 337 splx(s); 338 goto restart; 339 } 340 } 341 splx(s); 342 mp = ⊤ 343 while (space > 0) { 344 register struct iovec *iov = uio->uio_iov; 345 346 MGET(m, M_WAIT, MT_DATA); 347 if (iov->iov_len >= NBPG && space >= CLBYTES) { 348 register struct mbuf *p; 349 MCLGET(p, 1); 350 if (p == 0) 351 goto nopages; 352 m->m_off = (int)p - (int)m; 353 len = MIN(CLBYTES, iov->iov_len); 354 space -= CLBYTES; 355 } else { 356 nopages: 357 len = MIN(MLEN, iov->iov_len); 358 space -= len; 359 } 360 error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 361 m->m_len = len; 362 *mp = m; 363 if (error) 364 goto release; 365 mp = &m->m_next; 366 if (uio->uio_resid <= 0) 367 break; 368 while (uio->uio_iov->iov_len == 0) { 369 uio->uio_iov++; 370 uio->uio_iovcnt--; 371 if (uio->uio_iovcnt <= 0) 372 panic("sosend"); 373 } 374 } 375 if (dontroute) 376 so->so_options |= SO_DONTROUTE; 377 s = splnet(); /* XXX */ 378 error = (*so->so_proto->pr_usrreq)(so, 379 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 380 top, (caddr_t)nam, rights); 381 splx(s); 382 if (dontroute) 383 so->so_options &= ~SO_DONTROUTE; 384 rights = 0; 385 top = 0; 386 first = 0; 387 if (error) 388 break; 389 } while (uio->uio_resid); 390 391 release: 392 sbunlock(&so->so_snd); 393 if (top) 394 m_freem(top); 395 if (error == EPIPE) 396 psignal(u.u_procp, SIGPIPE); 397 return (error); 398 } 399 400 soreceive(so, aname, uio, flags, rightsp) 401 register struct socket *so; 402 struct mbuf **aname; 403 register struct uio *uio; 404 int flags; 405 struct mbuf **rightsp; 406 { 407 register struct mbuf *m, *n; 408 register int len, error = 0, s, tomark; 409 struct protosw *pr = so->so_proto; 410 struct mbuf *nextrecord; 411 int moff; 412 413 if (rightsp) 414 *rightsp = 0; 415 if (aname) 416 *aname = 0; 417 if (flags & MSG_OOB) { 418 m = m_get(M_WAIT, MT_DATA); 419 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 420 m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); 421 if (error) 422 goto bad; 423 do { 424 len = uio->uio_resid; 425 if (len > m->m_len) 426 len = m->m_len; 427 error = 428 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 429 m = m_free(m); 430 } while (uio->uio_resid && error == 0 && m); 431 bad: 432 if (m) 433 m_freem(m); 434 return (error); 435 } 436 437 restart: 438 sblock(&so->so_rcv); 439 s = splnet(); 440 441 #define rcverr(errno) { error = errno; splx(s); goto release; } 442 if (so->so_rcv.sb_cc == 0) { 443 if (so->so_error) { 444 error = so->so_error; 445 so->so_error = 0; 446 splx(s); 447 goto release; 448 } 449 if (so->so_state & SS_CANTRCVMORE) { 450 splx(s); 451 goto release; 452 } 453 if ((so->so_state & SS_ISCONNECTED) == 0 && 454 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 455 rcverr(ENOTCONN); 456 if (so->so_state & SS_NBIO) 457 rcverr(EWOULDBLOCK); 458 sbunlock(&so->so_rcv); 459 sbwait(&so->so_rcv); 460 splx(s); 461 goto restart; 462 } 463 u.u_ru.ru_msgrcv++; 464 m = so->so_rcv.sb_mb; 465 if (pr->pr_flags & PR_ADDR) { 466 if (m == 0 || m->m_type != MT_SONAME) 467 panic("receive 1a"); 468 if (flags & MSG_PEEK) { 469 if (aname) 470 *aname = m_copy(m, 0, m->m_len); 471 else 472 m = m->m_act; 473 } else { 474 if (aname) { 475 *aname = m; 476 sbfree(&so->so_rcv, m); 477 if(m->m_next) panic("receive 1b"); 478 so->so_rcv.sb_mb = m = m->m_act; 479 } else 480 m = sbdroprecord(&so->so_rcv); 481 } 482 } 483 if (m && m->m_type == MT_RIGHTS) { 484 if ((pr->pr_flags & PR_RIGHTS) == 0) 485 panic("receive 2a"); 486 if (flags & MSG_PEEK) { 487 if (rightsp) 488 *rightsp = m_copy(m, 0, m->m_len); 489 else 490 m = m->m_act; 491 } else { 492 if (rightsp) { 493 *rightsp = m; 494 sbfree(&so->so_rcv, m); 495 if(m->m_next) panic("receive 2b"); 496 so->so_rcv.sb_mb = m = m->m_act; 497 } else 498 m = sbdroprecord(&so->so_rcv); 499 } 500 } 501 if (m == 0 || (m->m_type != MT_DATA && m->m_type != MT_HEADER)) 502 panic("receive 3"); 503 moff = 0; 504 tomark = so->so_oobmark; 505 while (m && uio->uio_resid > 0 && error == 0) { 506 len = uio->uio_resid; 507 so->so_state &= ~SS_RCVATMARK; 508 if (tomark && len > tomark) 509 len = tomark; 510 if (len > m->m_len - moff) 511 len = m->m_len - moff; 512 splx(s); 513 error = 514 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 515 s = splnet(); 516 if (len == m->m_len - moff) { 517 if ((flags & MSG_PEEK) == 0) { 518 nextrecord = m->m_act; 519 sbfree(&so->so_rcv, m); 520 MFREE(m, n); 521 if (m = n) 522 m->m_act = nextrecord; 523 so->so_rcv.sb_mb = m; 524 } else 525 m = m->m_next; 526 moff = 0; 527 } else { 528 if (flags & MSG_PEEK) 529 moff += len; 530 else { 531 m->m_off += len; 532 m->m_len -= len; 533 so->so_rcv.sb_cc -= len; 534 } 535 } 536 if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 537 so->so_oobmark -= len; 538 if (so->so_oobmark == 0) { 539 so->so_state |= SS_RCVATMARK; 540 break; 541 } 542 } 543 if (tomark) { 544 tomark -= len; 545 if (tomark == 0) 546 break; 547 } 548 } 549 if ((flags & MSG_PEEK) == 0) { 550 if (m == 0) 551 so->so_rcv.sb_mb = nextrecord; 552 else if (pr->pr_flags & PR_ATOMIC) 553 (void) sbdroprecord(&so->so_rcv); 554 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 555 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 556 (struct mbuf *)0, (struct mbuf *)0); 557 } 558 release: 559 sbunlock(&so->so_rcv); 560 if (error == 0 && rightsp && *rightsp && pr->pr_domain->dom_externalize) 561 error = (*pr->pr_domain->dom_externalize)(*rightsp); 562 splx(s); 563 return (error); 564 } 565 566 soshutdown(so, how) 567 register struct socket *so; 568 register int how; 569 { 570 register struct protosw *pr = so->so_proto; 571 572 how++; 573 if (how & FREAD) 574 sorflush(so); 575 if (how & FWRITE) 576 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 577 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 578 return (0); 579 } 580 581 sorflush(so) 582 register struct socket *so; 583 { 584 register struct sockbuf *sb = &so->so_rcv; 585 register struct protosw *pr = so->so_proto; 586 register int s; 587 struct sockbuf asb; 588 589 sblock(sb); 590 s = splimp(); 591 socantrcvmore(so); 592 sbunlock(sb); 593 asb = *sb; 594 bzero((caddr_t)sb, sizeof (*sb)); 595 splx(s); 596 if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 597 (*pr->pr_domain->dom_dispose)(asb.sb_mb); 598 sbrelease(&asb); 599 } 600 601 sosetopt(so, level, optname, m0) 602 register struct socket *so; 603 int level, optname; 604 struct mbuf *m0; 605 { 606 int error = 0; 607 register struct mbuf *m = m0; 608 609 if (level != SOL_SOCKET) { 610 if (so->so_proto && so->so_proto->pr_ctloutput) 611 return ((*so->so_proto->pr_ctloutput) 612 (PRCO_SETOPT, so, level, optname, &m0)); 613 error = ENOPROTOOPT; 614 } else { 615 switch (optname) { 616 617 case SO_LINGER: 618 if (m == NULL || m->m_len != sizeof (struct linger)) { 619 error = EINVAL; 620 goto bad; 621 } 622 so->so_linger = mtod(m, struct linger *)->l_linger; 623 /* fall thru... */ 624 625 case SO_DEBUG: 626 case SO_KEEPALIVE: 627 case SO_DONTROUTE: 628 case SO_USELOOPBACK: 629 case SO_BROADCAST: 630 case SO_REUSEADDR: 631 if (m == NULL || m->m_len < sizeof (int)) { 632 error = EINVAL; 633 goto bad; 634 } 635 if (*mtod(m, int *)) 636 so->so_options |= optname; 637 else 638 so->so_options &= ~optname; 639 break; 640 641 case SO_SNDBUF: 642 case SO_RCVBUF: 643 case SO_SNDLOWAT: 644 case SO_RCVLOWAT: 645 case SO_SNDTIMEO: 646 case SO_RCVTIMEO: 647 if (m == NULL || m->m_len < sizeof (int)) { 648 error = EINVAL; 649 goto bad; 650 } 651 switch (optname) { 652 653 case SO_SNDBUF: 654 case SO_RCVBUF: 655 if (sbreserve(optname == SO_SNDBUF ? &so->so_snd : 656 &so->so_rcv, *mtod(m, int *)) == 0) { 657 error = ENOBUFS; 658 goto bad; 659 } 660 break; 661 662 case SO_SNDLOWAT: 663 so->so_snd.sb_lowat = *mtod(m, int *); 664 break; 665 case SO_RCVLOWAT: 666 so->so_rcv.sb_lowat = *mtod(m, int *); 667 break; 668 case SO_SNDTIMEO: 669 so->so_snd.sb_timeo = *mtod(m, int *); 670 break; 671 case SO_RCVTIMEO: 672 so->so_rcv.sb_timeo = *mtod(m, int *); 673 break; 674 } 675 break; 676 677 default: 678 error = ENOPROTOOPT; 679 break; 680 } 681 } 682 bad: 683 if (m) 684 (void) m_free(m); 685 return (error); 686 } 687 688 sogetopt(so, level, optname, mp) 689 register struct socket *so; 690 int level, optname; 691 struct mbuf **mp; 692 { 693 register struct mbuf *m; 694 695 if (level != SOL_SOCKET) { 696 if (so->so_proto && so->so_proto->pr_ctloutput) { 697 return ((*so->so_proto->pr_ctloutput) 698 (PRCO_GETOPT, so, level, optname, mp)); 699 } else 700 return (ENOPROTOOPT); 701 } else { 702 m = m_get(M_WAIT, MT_SOOPTS); 703 switch (optname) { 704 705 case SO_LINGER: 706 m->m_len = sizeof (struct linger); 707 mtod(m, struct linger *)->l_onoff = 708 so->so_options & SO_LINGER; 709 mtod(m, struct linger *)->l_linger = so->so_linger; 710 break; 711 712 case SO_USELOOPBACK: 713 case SO_DONTROUTE: 714 case SO_DEBUG: 715 case SO_KEEPALIVE: 716 case SO_REUSEADDR: 717 case SO_BROADCAST: 718 m->m_len = sizeof (int); 719 *mtod(m, int *) = so->so_options & optname; 720 break; 721 722 case SO_ERROR: 723 *mtod(m, int *) = so->so_error; 724 so->so_error = 0; 725 break; 726 727 case SO_SNDBUF: 728 *mtod(m, int *) = so->so_snd.sb_hiwat; 729 break; 730 731 case SO_RCVBUF: 732 *mtod(m, int *) = so->so_rcv.sb_hiwat; 733 break; 734 735 case SO_SNDLOWAT: 736 *mtod(m, int *) = so->so_snd.sb_lowat; 737 break; 738 739 case SO_RCVLOWAT: 740 *mtod(m, int *) = so->so_rcv.sb_lowat; 741 break; 742 743 case SO_SNDTIMEO: 744 *mtod(m, int *) = so->so_snd.sb_timeo; 745 break; 746 747 case SO_RCVTIMEO: 748 *mtod(m, int *) = so->so_rcv.sb_timeo; 749 break; 750 751 default: 752 m_free(m); 753 return (ENOPROTOOPT); 754 } 755 *mp = m; 756 return (0); 757 } 758 } 759 760 sohasoutofband(so) 761 register struct socket *so; 762 { 763 struct proc *p; 764 765 if (so->so_pgrp < 0) 766 gsignal(-so->so_pgrp, SIGURG); 767 else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 768 psignal(p, SIGURG); 769 if (so->so_rcv.sb_sel) { 770 selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL); 771 so->so_rcv.sb_sel = 0; 772 so->so_rcv.sb_flags &= ~SB_COLL; 773 } 774 } 775