1 /* $NetBSD: uipc_socket.c,v 1.25 1996/08/14 05:53:18 explorer Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1988, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/proc.h> 41 #include <sys/file.h> 42 #include <sys/malloc.h> 43 #include <sys/mbuf.h> 44 #include <sys/domain.h> 45 #include <sys/kernel.h> 46 #include <sys/protosw.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/signalvar.h> 50 #include <sys/resourcevar.h> 51 52 /* 53 * Socket operation routines. 54 * These routines are called by the routines in 55 * sys_socket.c or from a system process, and 56 * implement the semantics of socket operations by 57 * switching out to the protocol specific routines. 58 */ 59 /*ARGSUSED*/ 60 int 61 socreate(dom, aso, type, proto) 62 int dom; 63 struct socket **aso; 64 register int type; 65 int proto; 66 { 67 struct proc *p = curproc; /* XXX */ 68 register struct protosw *prp; 69 register struct socket *so; 70 register int error; 71 72 if (proto) 73 prp = pffindproto(dom, proto, type); 74 else 75 prp = pffindtype(dom, type); 76 if (prp == 0 || prp->pr_usrreq == 0) 77 return (EPROTONOSUPPORT); 78 if (prp->pr_type != type) 79 return (EPROTOTYPE); 80 MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT); 81 bzero((caddr_t)so, sizeof(*so)); 82 so->so_type = type; 83 so->so_proto = prp; 84 error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, 85 (struct mbuf *)(long)proto, (struct mbuf *)0, p); 86 if (error) { 87 so->so_state |= SS_NOFDREF; 88 sofree(so); 89 return (error); 90 } 91 #ifdef COMPAT_SUNOS 92 { 93 extern struct emul emul_sunos; 94 if (p->p_emul == &emul_sunos && type == SOCK_DGRAM) 95 so->so_options |= SO_BROADCAST; 96 } 97 #endif 98 *aso = so; 99 return (0); 100 } 101 102 int 103 sobind(so, nam) 104 struct socket *so; 105 struct mbuf *nam; 106 { 107 struct proc *p = curproc; /* XXX */ 108 int s = splsoftnet(); 109 int error; 110 111 error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, 112 nam, (struct mbuf *)0, p); 113 splx(s); 114 return (error); 115 } 116 117 int 118 solisten(so, backlog) 119 register struct socket *so; 120 int backlog; 121 { 122 int s = splsoftnet(), error; 123 124 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0, 125 (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); 126 if (error) { 127 splx(s); 128 return (error); 129 } 130 if (so->so_q == 0) 131 so->so_options |= SO_ACCEPTCONN; 132 if (backlog < 0) 133 backlog = 0; 134 so->so_qlimit = min(backlog, SOMAXCONN); 135 splx(s); 136 return (0); 137 } 138 139 void 140 sofree(so) 141 register struct socket *so; 142 { 143 144 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 145 return; 146 if (so->so_head) { 147 if (!soqremque(so, 0) && !soqremque(so, 1)) 148 panic("sofree dq"); 149 so->so_head = 0; 150 } 151 sbrelease(&so->so_snd); 152 sorflush(so); 153 FREE(so, M_SOCKET); 154 } 155 156 /* 157 * Close a socket on last file table reference removal. 158 * Initiate disconnect if connected. 159 * Free socket when disconnect complete. 160 */ 161 int 162 soclose(so) 163 register struct socket *so; 164 { 165 int s = splsoftnet(); /* conservative */ 166 int error = 0; 167 168 if (so->so_options & SO_ACCEPTCONN) { 169 while (so->so_q0) 170 (void) soabort(so->so_q0); 171 while (so->so_q) 172 (void) soabort(so->so_q); 173 } 174 if (so->so_pcb == 0) 175 goto discard; 176 if (so->so_state & SS_ISCONNECTED) { 177 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 178 error = sodisconnect(so); 179 if (error) 180 goto drop; 181 } 182 if (so->so_options & SO_LINGER) { 183 if ((so->so_state & SS_ISDISCONNECTING) && 184 (so->so_state & SS_NBIO)) 185 goto drop; 186 while (so->so_state & SS_ISCONNECTED) { 187 error = tsleep((caddr_t)&so->so_timeo, 188 PSOCK | PCATCH, netcls, 189 so->so_linger); 190 if (error) 191 break; 192 } 193 } 194 } 195 drop: 196 if (so->so_pcb) { 197 int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 198 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, 199 (struct proc *)0); 200 if (error == 0) 201 error = error2; 202 } 203 discard: 204 if (so->so_state & SS_NOFDREF) 205 panic("soclose: NOFDREF"); 206 so->so_state |= SS_NOFDREF; 207 sofree(so); 208 splx(s); 209 return (error); 210 } 211 212 /* 213 * Must be called at splsoftnet... 214 */ 215 int 216 soabort(so) 217 struct socket *so; 218 { 219 220 return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0, 221 (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); 222 } 223 224 int 225 soaccept(so, nam) 226 register struct socket *so; 227 struct mbuf *nam; 228 { 229 int s = splsoftnet(); 230 int error; 231 232 if ((so->so_state & SS_NOFDREF) == 0) 233 panic("soaccept: !NOFDREF"); 234 so->so_state &= ~SS_NOFDREF; 235 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, (struct mbuf *)0, 236 nam, (struct mbuf *)0, (struct proc *)0); 237 splx(s); 238 return (error); 239 } 240 241 int 242 soconnect(so, nam) 243 register struct socket *so; 244 struct mbuf *nam; 245 { 246 struct proc *p = curproc; /* XXX */ 247 int s; 248 int error; 249 250 if (so->so_options & SO_ACCEPTCONN) 251 return (EOPNOTSUPP); 252 s = splsoftnet(); 253 /* 254 * If protocol is connection-based, can only connect once. 255 * Otherwise, if connected, try to disconnect first. 256 * This allows user to disconnect by connecting to, e.g., 257 * a null address. 258 */ 259 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && 260 ((so->so_proto->pr_flags & PR_CONNREQUIRED) || 261 (error = sodisconnect(so)))) 262 error = EISCONN; 263 else 264 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 265 (struct mbuf *)0, nam, (struct mbuf *)0, p); 266 splx(s); 267 return (error); 268 } 269 270 int 271 soconnect2(so1, so2) 272 register struct socket *so1; 273 struct socket *so2; 274 { 275 int s = splsoftnet(); 276 int error; 277 278 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 279 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0, 280 (struct proc *)0); 281 splx(s); 282 return (error); 283 } 284 285 int 286 sodisconnect(so) 287 register struct socket *so; 288 { 289 int s = splsoftnet(); 290 int error; 291 292 if ((so->so_state & SS_ISCONNECTED) == 0) { 293 error = ENOTCONN; 294 goto bad; 295 } 296 if (so->so_state & SS_ISDISCONNECTING) { 297 error = EALREADY; 298 goto bad; 299 } 300 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 301 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, 302 (struct proc *)0); 303 bad: 304 splx(s); 305 return (error); 306 } 307 308 #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) 309 /* 310 * Send on a socket. 311 * If send must go all at once and message is larger than 312 * send buffering, then hard error. 313 * Lock against other senders. 314 * If must go all at once and not enough room now, then 315 * inform user that this would block and do nothing. 316 * Otherwise, if nonblocking, send as much as possible. 317 * The data to be sent is described by "uio" if nonzero, 318 * otherwise by the mbuf chain "top" (which must be null 319 * if uio is not). Data provided in mbuf chain must be small 320 * enough to send all at once. 321 * 322 * Returns nonzero on error, timeout or signal; callers 323 * must check for short counts if EINTR/ERESTART are returned. 324 * Data and control buffers are freed on return. 325 */ 326 int 327 sosend(so, addr, uio, top, control, flags) 328 register struct socket *so; 329 struct mbuf *addr; 330 struct uio *uio; 331 struct mbuf *top; 332 struct mbuf *control; 333 int flags; 334 { 335 struct proc *p = curproc; /* XXX */ 336 struct mbuf **mp; 337 register struct mbuf *m; 338 register long space, len, resid; 339 int clen = 0, error, s, dontroute, mlen; 340 int atomic = sosendallatonce(so) || top; 341 342 if (uio) 343 resid = uio->uio_resid; 344 else 345 resid = top->m_pkthdr.len; 346 /* 347 * In theory resid should be unsigned. 348 * However, space must be signed, as it might be less than 0 349 * if we over-committed, and we must use a signed comparison 350 * of space and resid. On the other hand, a negative resid 351 * causes us to loop sending 0-length segments to the protocol. 352 */ 353 if (resid < 0) 354 return (EINVAL); 355 dontroute = 356 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 357 (so->so_proto->pr_flags & PR_ATOMIC); 358 p->p_stats->p_ru.ru_msgsnd++; 359 if (control) 360 clen = control->m_len; 361 #define snderr(errno) { error = errno; splx(s); goto release; } 362 363 restart: 364 if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) 365 goto out; 366 do { 367 s = splsoftnet(); 368 if (so->so_state & SS_CANTSENDMORE) 369 snderr(EPIPE); 370 if (so->so_error) 371 snderr(so->so_error); 372 if ((so->so_state & SS_ISCONNECTED) == 0) { 373 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 374 if ((so->so_state & SS_ISCONFIRMING) == 0 && 375 !(resid == 0 && clen != 0)) 376 snderr(ENOTCONN); 377 } else if (addr == 0) 378 snderr(EDESTADDRREQ); 379 } 380 space = sbspace(&so->so_snd); 381 if (flags & MSG_OOB) 382 space += 1024; 383 if ((atomic && resid > so->so_snd.sb_hiwat) || 384 clen > so->so_snd.sb_hiwat) 385 snderr(EMSGSIZE); 386 if (space < resid + clen && uio && 387 (atomic || space < so->so_snd.sb_lowat || space < clen)) { 388 if (so->so_state & SS_NBIO) 389 snderr(EWOULDBLOCK); 390 sbunlock(&so->so_snd); 391 error = sbwait(&so->so_snd); 392 splx(s); 393 if (error) 394 goto out; 395 goto restart; 396 } 397 splx(s); 398 mp = ⊤ 399 space -= clen; 400 do { 401 if (uio == NULL) { 402 /* 403 * Data is prepackaged in "top". 404 */ 405 resid = 0; 406 if (flags & MSG_EOR) 407 top->m_flags |= M_EOR; 408 } else do { 409 if (top == 0) { 410 MGETHDR(m, M_WAIT, MT_DATA); 411 mlen = MHLEN; 412 m->m_pkthdr.len = 0; 413 m->m_pkthdr.rcvif = (struct ifnet *)0; 414 } else { 415 MGET(m, M_WAIT, MT_DATA); 416 mlen = MLEN; 417 } 418 if (resid >= MINCLSIZE && space >= MCLBYTES) { 419 MCLGET(m, M_WAIT); 420 if ((m->m_flags & M_EXT) == 0) 421 goto nopages; 422 mlen = MCLBYTES; 423 #ifdef MAPPED_MBUFS 424 len = min(MCLBYTES, resid); 425 #else 426 if (atomic && top == 0) { 427 len = min(MCLBYTES - max_hdr, resid); 428 m->m_data += max_hdr; 429 } else 430 len = min(MCLBYTES, resid); 431 #endif 432 space -= len; 433 } else { 434 nopages: 435 len = min(min(mlen, resid), space); 436 space -= len; 437 /* 438 * For datagram protocols, leave room 439 * for protocol headers in first mbuf. 440 */ 441 if (atomic && top == 0 && len < mlen) 442 MH_ALIGN(m, len); 443 } 444 error = uiomove(mtod(m, caddr_t), (int)len, uio); 445 resid = uio->uio_resid; 446 m->m_len = len; 447 *mp = m; 448 top->m_pkthdr.len += len; 449 if (error) 450 goto release; 451 mp = &m->m_next; 452 if (resid <= 0) { 453 if (flags & MSG_EOR) 454 top->m_flags |= M_EOR; 455 break; 456 } 457 } while (space > 0 && atomic); 458 if (dontroute) 459 so->so_options |= SO_DONTROUTE; 460 s = splsoftnet(); /* XXX */ 461 error = (*so->so_proto->pr_usrreq)(so, 462 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 463 top, addr, control, p); 464 splx(s); 465 if (dontroute) 466 so->so_options &= ~SO_DONTROUTE; 467 clen = 0; 468 control = 0; 469 top = 0; 470 mp = ⊤ 471 if (error) 472 goto release; 473 } while (resid && space > 0); 474 } while (resid); 475 476 release: 477 sbunlock(&so->so_snd); 478 out: 479 if (top) 480 m_freem(top); 481 if (control) 482 m_freem(control); 483 return (error); 484 } 485 486 /* 487 * Implement receive operations on a socket. 488 * We depend on the way that records are added to the sockbuf 489 * by sbappend*. In particular, each record (mbufs linked through m_next) 490 * must begin with an address if the protocol so specifies, 491 * followed by an optional mbuf or mbufs containing ancillary data, 492 * and then zero or more mbufs of data. 493 * In order to avoid blocking network interrupts for the entire time here, 494 * we splx() while doing the actual copy to user space. 495 * Although the sockbuf is locked, new data may still be appended, 496 * and thus we must maintain consistency of the sockbuf during that time. 497 * 498 * The caller may receive the data as a single mbuf chain by supplying 499 * an mbuf **mp0 for use in returning the chain. The uio is then used 500 * only for the count in uio_resid. 501 */ 502 int 503 soreceive(so, paddr, uio, mp0, controlp, flagsp) 504 register struct socket *so; 505 struct mbuf **paddr; 506 struct uio *uio; 507 struct mbuf **mp0; 508 struct mbuf **controlp; 509 int *flagsp; 510 { 511 register struct mbuf *m, **mp; 512 register int flags, len, error, s, offset; 513 struct protosw *pr = so->so_proto; 514 struct mbuf *nextrecord; 515 int moff, type = 0; 516 int orig_resid = uio->uio_resid; 517 518 mp = mp0; 519 if (paddr) 520 *paddr = 0; 521 if (controlp) 522 *controlp = 0; 523 if (flagsp) 524 flags = *flagsp &~ MSG_EOR; 525 else 526 flags = 0; 527 if (flags & MSG_OOB) { 528 m = m_get(M_WAIT, MT_DATA); 529 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, 530 (struct mbuf *)(long)(flags & MSG_PEEK), (struct mbuf *)0, 531 (struct proc *)0); 532 if (error) 533 goto bad; 534 do { 535 error = uiomove(mtod(m, caddr_t), 536 (int) min(uio->uio_resid, m->m_len), uio); 537 m = m_free(m); 538 } while (uio->uio_resid && error == 0 && m); 539 bad: 540 if (m) 541 m_freem(m); 542 return (error); 543 } 544 if (mp) 545 *mp = (struct mbuf *)0; 546 if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) 547 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 548 (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); 549 550 restart: 551 if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) 552 return (error); 553 s = splsoftnet(); 554 555 m = so->so_rcv.sb_mb; 556 /* 557 * If we have less data than requested, block awaiting more 558 * (subject to any timeout) if: 559 * 1. the current count is less than the low water mark, 560 * 2. MSG_WAITALL is set, and it is possible to do the entire 561 * receive operation at once if we block (resid <= hiwat), or 562 * 3. MSG_DONTWAIT is not set. 563 * If MSG_WAITALL is set but resid is larger than the receive buffer, 564 * we have to do the receive in sections, and thus risk returning 565 * a short count if a timeout or signal occurs after we start. 566 */ 567 if (m == 0 || (((flags & MSG_DONTWAIT) == 0 && 568 so->so_rcv.sb_cc < uio->uio_resid) && 569 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || 570 ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && 571 m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) { 572 #ifdef DIAGNOSTIC 573 if (m == 0 && so->so_rcv.sb_cc) 574 panic("receive 1"); 575 #endif 576 if (so->so_error) { 577 if (m) 578 goto dontblock; 579 error = so->so_error; 580 if ((flags & MSG_PEEK) == 0) 581 so->so_error = 0; 582 goto release; 583 } 584 if (so->so_state & SS_CANTRCVMORE) { 585 if (m) 586 goto dontblock; 587 else 588 goto release; 589 } 590 for (; m; m = m->m_next) 591 if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { 592 m = so->so_rcv.sb_mb; 593 goto dontblock; 594 } 595 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && 596 (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 597 error = ENOTCONN; 598 goto release; 599 } 600 if (uio->uio_resid == 0) 601 goto release; 602 if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { 603 error = EWOULDBLOCK; 604 goto release; 605 } 606 sbunlock(&so->so_rcv); 607 error = sbwait(&so->so_rcv); 608 splx(s); 609 if (error) 610 return (error); 611 goto restart; 612 } 613 dontblock: 614 #ifdef notyet /* XXXX */ 615 if (uio->uio_procp) 616 uio->uio_procp->p_stats->p_ru.ru_msgrcv++; 617 #endif 618 nextrecord = m->m_nextpkt; 619 if (pr->pr_flags & PR_ADDR) { 620 #ifdef DIAGNOSTIC 621 if (m->m_type != MT_SONAME) 622 panic("receive 1a"); 623 #endif 624 orig_resid = 0; 625 if (flags & MSG_PEEK) { 626 if (paddr) 627 *paddr = m_copy(m, 0, m->m_len); 628 m = m->m_next; 629 } else { 630 sbfree(&so->so_rcv, m); 631 if (paddr) { 632 *paddr = m; 633 so->so_rcv.sb_mb = m->m_next; 634 m->m_next = 0; 635 m = so->so_rcv.sb_mb; 636 } else { 637 MFREE(m, so->so_rcv.sb_mb); 638 m = so->so_rcv.sb_mb; 639 } 640 } 641 } 642 while (m && m->m_type == MT_CONTROL && error == 0) { 643 if (flags & MSG_PEEK) { 644 if (controlp) 645 *controlp = m_copy(m, 0, m->m_len); 646 m = m->m_next; 647 } else { 648 sbfree(&so->so_rcv, m); 649 if (controlp) { 650 if (pr->pr_domain->dom_externalize && 651 mtod(m, struct cmsghdr *)->cmsg_type == 652 SCM_RIGHTS) 653 error = (*pr->pr_domain->dom_externalize)(m); 654 *controlp = m; 655 so->so_rcv.sb_mb = m->m_next; 656 m->m_next = 0; 657 m = so->so_rcv.sb_mb; 658 } else { 659 MFREE(m, so->so_rcv.sb_mb); 660 m = so->so_rcv.sb_mb; 661 } 662 } 663 if (controlp) { 664 orig_resid = 0; 665 controlp = &(*controlp)->m_next; 666 } 667 } 668 if (m) { 669 if ((flags & MSG_PEEK) == 0) 670 m->m_nextpkt = nextrecord; 671 type = m->m_type; 672 if (type == MT_OOBDATA) 673 flags |= MSG_OOB; 674 } 675 moff = 0; 676 offset = 0; 677 while (m && uio->uio_resid > 0 && error == 0) { 678 if (m->m_type == MT_OOBDATA) { 679 if (type != MT_OOBDATA) 680 break; 681 } else if (type == MT_OOBDATA) 682 break; 683 #ifdef DIAGNOSTIC 684 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 685 panic("receive 3"); 686 #endif 687 so->so_state &= ~SS_RCVATMARK; 688 len = uio->uio_resid; 689 if (so->so_oobmark && len > so->so_oobmark - offset) 690 len = so->so_oobmark - offset; 691 if (len > m->m_len - moff) 692 len = m->m_len - moff; 693 /* 694 * If mp is set, just pass back the mbufs. 695 * Otherwise copy them out via the uio, then free. 696 * Sockbuf must be consistent here (points to current mbuf, 697 * it points to next record) when we drop priority; 698 * we must note any additions to the sockbuf when we 699 * block interrupts again. 700 */ 701 if (mp == 0) { 702 splx(s); 703 error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); 704 s = splsoftnet(); 705 } else 706 uio->uio_resid -= len; 707 if (len == m->m_len - moff) { 708 if (m->m_flags & M_EOR) 709 flags |= MSG_EOR; 710 if (flags & MSG_PEEK) { 711 m = m->m_next; 712 moff = 0; 713 } else { 714 nextrecord = m->m_nextpkt; 715 sbfree(&so->so_rcv, m); 716 if (mp) { 717 *mp = m; 718 mp = &m->m_next; 719 so->so_rcv.sb_mb = m = m->m_next; 720 *mp = (struct mbuf *)0; 721 } else { 722 MFREE(m, so->so_rcv.sb_mb); 723 m = so->so_rcv.sb_mb; 724 } 725 if (m) 726 m->m_nextpkt = nextrecord; 727 } 728 } else { 729 if (flags & MSG_PEEK) 730 moff += len; 731 else { 732 if (mp) 733 *mp = m_copym(m, 0, len, M_WAIT); 734 m->m_data += len; 735 m->m_len -= len; 736 so->so_rcv.sb_cc -= len; 737 } 738 } 739 if (so->so_oobmark) { 740 if ((flags & MSG_PEEK) == 0) { 741 so->so_oobmark -= len; 742 if (so->so_oobmark == 0) { 743 so->so_state |= SS_RCVATMARK; 744 break; 745 } 746 } else { 747 offset += len; 748 if (offset == so->so_oobmark) 749 break; 750 } 751 } 752 if (flags & MSG_EOR) 753 break; 754 /* 755 * If the MSG_WAITALL flag is set (for non-atomic socket), 756 * we must not quit until "uio->uio_resid == 0" or an error 757 * termination. If a signal/timeout occurs, return 758 * with a short count but without error. 759 * Keep sockbuf locked against other readers. 760 */ 761 while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 && 762 !sosendallatonce(so) && !nextrecord) { 763 if (so->so_error || so->so_state & SS_CANTRCVMORE) 764 break; 765 error = sbwait(&so->so_rcv); 766 if (error) { 767 sbunlock(&so->so_rcv); 768 splx(s); 769 return (0); 770 } 771 if ((m = so->so_rcv.sb_mb) != NULL) 772 nextrecord = m->m_nextpkt; 773 } 774 } 775 776 if (m && pr->pr_flags & PR_ATOMIC) { 777 flags |= MSG_TRUNC; 778 if ((flags & MSG_PEEK) == 0) 779 (void) sbdroprecord(&so->so_rcv); 780 } 781 if ((flags & MSG_PEEK) == 0) { 782 if (m == 0) 783 so->so_rcv.sb_mb = nextrecord; 784 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 785 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 786 (struct mbuf *)(long)flags, (struct mbuf *)0, 787 (struct proc *)0); 788 } 789 if (orig_resid == uio->uio_resid && orig_resid && 790 (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { 791 sbunlock(&so->so_rcv); 792 splx(s); 793 goto restart; 794 } 795 796 if (flagsp) 797 *flagsp |= flags; 798 release: 799 sbunlock(&so->so_rcv); 800 splx(s); 801 return (error); 802 } 803 804 int 805 soshutdown(so, how) 806 register struct socket *so; 807 register int how; 808 { 809 register struct protosw *pr = so->so_proto; 810 811 how++; 812 if (how & FREAD) 813 sorflush(so); 814 if (how & FWRITE) 815 return (*pr->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 816 (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); 817 return (0); 818 } 819 820 void 821 sorflush(so) 822 register struct socket *so; 823 { 824 register struct sockbuf *sb = &so->so_rcv; 825 register struct protosw *pr = so->so_proto; 826 register int s; 827 struct sockbuf asb; 828 829 sb->sb_flags |= SB_NOINTR; 830 (void) sblock(sb, M_WAITOK); 831 s = splimp(); 832 socantrcvmore(so); 833 sbunlock(sb); 834 asb = *sb; 835 bzero((caddr_t)sb, sizeof (*sb)); 836 splx(s); 837 if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 838 (*pr->pr_domain->dom_dispose)(asb.sb_mb); 839 sbrelease(&asb); 840 } 841 842 int 843 sosetopt(so, level, optname, m0) 844 register struct socket *so; 845 int level, optname; 846 struct mbuf *m0; 847 { 848 int error = 0; 849 register struct mbuf *m = m0; 850 851 if (level != SOL_SOCKET) { 852 if (so->so_proto && so->so_proto->pr_ctloutput) 853 return ((*so->so_proto->pr_ctloutput) 854 (PRCO_SETOPT, so, level, optname, &m0)); 855 error = ENOPROTOOPT; 856 } else { 857 switch (optname) { 858 859 case SO_LINGER: 860 if (m == NULL || m->m_len != sizeof (struct linger)) { 861 error = EINVAL; 862 goto bad; 863 } 864 so->so_linger = mtod(m, struct linger *)->l_linger; 865 /* fall thru... */ 866 867 case SO_DEBUG: 868 case SO_KEEPALIVE: 869 case SO_DONTROUTE: 870 case SO_USELOOPBACK: 871 case SO_BROADCAST: 872 case SO_REUSEADDR: 873 case SO_REUSEPORT: 874 case SO_OOBINLINE: 875 if (m == NULL || m->m_len < sizeof (int)) { 876 error = EINVAL; 877 goto bad; 878 } 879 if (*mtod(m, int *)) 880 so->so_options |= optname; 881 else 882 so->so_options &= ~optname; 883 break; 884 885 case SO_SNDBUF: 886 case SO_RCVBUF: 887 case SO_SNDLOWAT: 888 case SO_RCVLOWAT: 889 if (m == NULL || m->m_len < sizeof (int)) { 890 error = EINVAL; 891 goto bad; 892 } 893 switch (optname) { 894 895 case SO_SNDBUF: 896 case SO_RCVBUF: 897 if (sbreserve(optname == SO_SNDBUF ? 898 &so->so_snd : &so->so_rcv, 899 (u_long) *mtod(m, int *)) == 0) { 900 error = ENOBUFS; 901 goto bad; 902 } 903 break; 904 905 case SO_SNDLOWAT: 906 so->so_snd.sb_lowat = *mtod(m, int *); 907 break; 908 case SO_RCVLOWAT: 909 so->so_rcv.sb_lowat = *mtod(m, int *); 910 break; 911 } 912 break; 913 914 case SO_SNDTIMEO: 915 case SO_RCVTIMEO: 916 { 917 struct timeval *tv; 918 short val; 919 920 if (m == NULL || m->m_len < sizeof (*tv)) { 921 error = EINVAL; 922 goto bad; 923 } 924 tv = mtod(m, struct timeval *); 925 if (tv->tv_sec * hz + tv->tv_usec / tick > SHRT_MAX) { 926 error = EDOM; 927 goto bad; 928 } 929 val = tv->tv_sec * hz + tv->tv_usec / tick; 930 931 switch (optname) { 932 933 case SO_SNDTIMEO: 934 so->so_snd.sb_timeo = val; 935 break; 936 case SO_RCVTIMEO: 937 so->so_rcv.sb_timeo = val; 938 break; 939 } 940 break; 941 } 942 943 default: 944 error = ENOPROTOOPT; 945 break; 946 } 947 if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) { 948 (void) ((*so->so_proto->pr_ctloutput) 949 (PRCO_SETOPT, so, level, optname, &m0)); 950 m = NULL; /* freed by protocol */ 951 } 952 } 953 bad: 954 if (m) 955 (void) m_free(m); 956 return (error); 957 } 958 959 int 960 sogetopt(so, level, optname, mp) 961 register struct socket *so; 962 int level, optname; 963 struct mbuf **mp; 964 { 965 register struct mbuf *m; 966 967 if (level != SOL_SOCKET) { 968 if (so->so_proto && so->so_proto->pr_ctloutput) { 969 return ((*so->so_proto->pr_ctloutput) 970 (PRCO_GETOPT, so, level, optname, mp)); 971 } else 972 return (ENOPROTOOPT); 973 } else { 974 m = m_get(M_WAIT, MT_SOOPTS); 975 m->m_len = sizeof (int); 976 977 switch (optname) { 978 979 case SO_LINGER: 980 m->m_len = sizeof (struct linger); 981 mtod(m, struct linger *)->l_onoff = 982 so->so_options & SO_LINGER; 983 mtod(m, struct linger *)->l_linger = so->so_linger; 984 break; 985 986 case SO_USELOOPBACK: 987 case SO_DONTROUTE: 988 case SO_DEBUG: 989 case SO_KEEPALIVE: 990 case SO_REUSEADDR: 991 case SO_REUSEPORT: 992 case SO_BROADCAST: 993 case SO_OOBINLINE: 994 *mtod(m, int *) = so->so_options & optname; 995 break; 996 997 case SO_TYPE: 998 *mtod(m, int *) = so->so_type; 999 break; 1000 1001 case SO_ERROR: 1002 *mtod(m, int *) = so->so_error; 1003 so->so_error = 0; 1004 break; 1005 1006 case SO_SNDBUF: 1007 *mtod(m, int *) = so->so_snd.sb_hiwat; 1008 break; 1009 1010 case SO_RCVBUF: 1011 *mtod(m, int *) = so->so_rcv.sb_hiwat; 1012 break; 1013 1014 case SO_SNDLOWAT: 1015 *mtod(m, int *) = so->so_snd.sb_lowat; 1016 break; 1017 1018 case SO_RCVLOWAT: 1019 *mtod(m, int *) = so->so_rcv.sb_lowat; 1020 break; 1021 1022 case SO_SNDTIMEO: 1023 case SO_RCVTIMEO: 1024 { 1025 int val = (optname == SO_SNDTIMEO ? 1026 so->so_snd.sb_timeo : so->so_rcv.sb_timeo); 1027 1028 m->m_len = sizeof(struct timeval); 1029 mtod(m, struct timeval *)->tv_sec = val / hz; 1030 mtod(m, struct timeval *)->tv_usec = 1031 (val % hz) / tick; 1032 break; 1033 } 1034 1035 default: 1036 (void)m_free(m); 1037 return (ENOPROTOOPT); 1038 } 1039 *mp = m; 1040 return (0); 1041 } 1042 } 1043 1044 void 1045 sohasoutofband(so) 1046 register struct socket *so; 1047 { 1048 struct proc *p; 1049 1050 if (so->so_pgid < 0) 1051 gsignal(-so->so_pgid, SIGURG); 1052 else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) 1053 psignal(p, SIGURG); 1054 selwakeup(&so->so_rcv.sb_sel); 1055 } 1056