1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: * 12: * @(#)uipc_socket.c 7.8.1 (2.11BSD GTE) 11/26/94 13: */ 14: 15: #include "param.h" 16: #ifdef INET 17: #include "user.h" 18: #include "proc.h" 19: #include "file.h" 20: #include "mbuf.h" 21: #include "domain.h" 22: #include "protosw.h" 23: #include "socket.h" 24: #include "socketvar.h" 25: #include "uio.h" 26: 27: /* 28: * Socket operation routines. 29: * These routines are called by the routines in 30: * sys_socket.c or from a system process, and 31: * implement the semantics of socket operations by 32: * switching out to the protocol specific routines. 33: * 34: * TODO: 35: * test socketpair 36: * clean up async 37: * out-of-band is a kludge 38: */ 39: /*ARGSUSED*/ 40: socreate(dom, aso, type, proto) 41: struct socket **aso; 42: register int type; 43: int proto; 44: { 45: register struct protosw *prp; 46: register struct socket *so; 47: register struct mbuf *m; 48: register int error; 49: 50: if (proto) 51: prp = pffindproto(dom, proto, type); 52: else 53: prp = pffindtype(dom, type); 54: if (prp == 0) 55: return (EPROTONOSUPPORT); 56: if (prp->pr_type != type) 57: return (EPROTOTYPE); 58: m = m_getclr(M_WAIT, MT_SOCKET); 59: so = mtod(m, struct socket *); 60: so->so_options = 0; 61: so->so_state = 0; 62: so->so_type = type; 63: if (u.u_uid == 0) 64: so->so_state = SS_PRIV; 65: so->so_proto = prp; 66: error = 67: (*prp->pr_usrreq)(so, PRU_ATTACH, 68: (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0); 69: if (error) { 70: so->so_state |= SS_NOFDREF; 71: sofree(so); 72: return (error); 73: } 74: *aso = so; 75: return (0); 76: } 77: 78: sobind(so, nam) 79: struct socket *so; 80: struct mbuf *nam; 81: { 82: int s = splnet(); 83: int error; 84: 85: error = 86: (*so->so_proto->pr_usrreq)(so, PRU_BIND, 87: (struct mbuf *)0, nam, (struct mbuf *)0); 88: splx(s); 89: return (error); 90: } 91: 92: solisten(so, backlog) 93: register struct socket *so; 94: int backlog; 95: { 96: int s = splnet(), error; 97: 98: error = 99: (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 100: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 101: if (error) { 102: splx(s); 103: return (error); 104: } 105: if (so->so_q == 0) { 106: so->so_q = so; 107: so->so_q0 = so; 108: so->so_options |= SO_ACCEPTCONN; 109: } 110: if (backlog < 0) 111: backlog = 0; 112: so->so_qlimit = MIN(backlog, SOMAXCONN); 113: splx(s); 114: return (0); 115: } 116: 117: sofree(so) 118: register struct socket *so; 119: { 120: 121: if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 122: return; 123: if (so->so_head) { 124: if (!soqremque(so, 0) && !soqremque(so, 1)) 125: panic("sofree dq"); 126: so->so_head = 0; 127: } 128: sbrelease(&so->so_snd); 129: sorflush(so); 130: (void) m_free(dtom(so)); 131: } 132: 133: /* 134: * Close a socket on last file table reference removal. 135: * Initiate disconnect if connected. 136: * Free socket when disconnect complete. 137: */ 138: soclose(so) 139: register struct socket *so; 140: { 141: int s = splnet(); /* conservative */ 142: int error = 0; 143: 144: if (so->so_options & SO_ACCEPTCONN) { 145: while (so->so_q0 != so) 146: (void) soabort(so->so_q0); 147: while (so->so_q != so) 148: (void) soabort(so->so_q); 149: } 150: if (so->so_pcb == 0) 151: goto discard; 152: if (so->so_state & SS_ISCONNECTED) { 153: if ((so->so_state & SS_ISDISCONNECTING) == 0) { 154: error = sodisconnect(so); 155: if (error) 156: goto drop; 157: } 158: if (so->so_options & SO_LINGER) { 159: if ((so->so_state & SS_ISDISCONNECTING) && 160: (so->so_state & SS_NBIO)) 161: goto drop; 162: while (so->so_state & SS_ISCONNECTED) 163: SLEEP((caddr_t)&so->so_timeo, PZERO+1); 164: } 165: } 166: drop: 167: if (so->so_pcb) { 168: int error2 = 169: (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 170: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 171: if (error == 0) 172: error = error2; 173: } 174: discard: 175: if (so->so_state & SS_NOFDREF) 176: panic("soclose: NOFDREF"); 177: so->so_state |= SS_NOFDREF; 178: sofree(so); 179: splx(s); 180: return(error); 181: } 182: 183: /* 184: * Must be called at splnet... 185: */ 186: soabort(so) 187: struct socket *so; 188: { 189: 190: return ( 191: (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 192: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 193: } 194: 195: soaccept(so, nam) 196: register struct socket *so; 197: struct mbuf *nam; 198: { 199: int s = splnet(); 200: int error; 201: 202: if ((so->so_state & SS_NOFDREF) == 0) 203: panic("soaccept: !NOFDREF"); 204: so->so_state &= ~SS_NOFDREF; 205: error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 206: (struct mbuf *)0, nam, (struct mbuf *)0); 207: splx(s); 208: return (error); 209: } 210: 211: soconnect(so, nam) 212: register struct socket *so; 213: struct mbuf *nam; 214: { 215: int s; 216: int error; 217: 218: /* 219: * this is done here in supervisor mode since the kernel can't access the 220: * socket or its options. 221: */ 222: if (so->so_options & SO_ACCEPTCONN) 223: return (EOPNOTSUPP); 224: if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 225: return(EALREADY); 226: s = splnet(); 227: /* 228: * If protocol is connection-based, can only connect once. 229: * Otherwise, if connected, try to disconnect first. 230: * This allows user to disconnect by connecting to, e.g., 231: * a null address. 232: */ 233: if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && 234: ((so->so_proto->pr_flags & PR_CONNREQUIRED) || 235: (error = sodisconnect(so)))) 236: error = EISCONN; 237: else 238: error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 239: (struct mbuf *)0, nam, (struct mbuf *)0); 240: /* 241: * this is done here because the kernel mode can't get at this info without 242: * a lot of trouble. 243: */ 244: if (!error) 245: { 246: if ((so->so_state & SS_NBIO) && 247: (so->so_state & SS_ISCONNECTING)) 248: error = EINPROGRESS; 249: } 250: else 251: so->so_state &= ~SS_ISCONNECTING; 252: splx(s); 253: return (error); 254: } 255: 256: soconnect2(so1, so2) 257: register struct socket *so1; 258: struct socket *so2; 259: { 260: int s = splnet(); 261: int error; 262: 263: error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 264: (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 265: splx(s); 266: return (error); 267: } 268: 269: sodisconnect(so) 270: register struct socket *so; 271: { 272: int s = splnet(); 273: int error; 274: 275: if ((so->so_state & SS_ISCONNECTED) == 0) { 276: error = ENOTCONN; 277: goto bad; 278: } 279: if (so->so_state & SS_ISDISCONNECTING) { 280: error = EALREADY; 281: goto bad; 282: } 283: error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 284: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 285: bad: 286: splx(s); 287: return (error); 288: } 289: 290: /* 291: * Send on a socket. 292: * If send must go all at once and message is larger than 293: * send buffering, then hard error. 294: * Lock against other senders. 295: * If must go all at once and not enough room now, then 296: * inform user that this would block and do nothing. 297: * Otherwise, if nonblocking, send as much as possible. 298: */ 299: sosend(so, nam, uio, flags, rights) 300: register struct socket *so; 301: struct mbuf *nam; 302: register struct uio *uio; 303: int flags; 304: struct mbuf *rights; 305: { 306: struct mbuf *top = 0; 307: register struct mbuf *m, **mp; 308: register int space; 309: int len, rlen = 0, error = 0, s, dontroute, first = 1; 310: 311: if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 312: return (EMSGSIZE); 313: dontroute = 314: (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 315: (so->so_proto->pr_flags & PR_ATOMIC); 316: u.u_ru.ru_msgsnd++; 317: if (rights) 318: rlen = rights->m_len; 319: #define snderr(errno) { error = errno; splx(s); goto release; } 320: 321: restart: 322: sblock(&so->so_snd); 323: do { 324: s = splnet(); 325: if (so->so_state & SS_CANTSENDMORE) 326: snderr(EPIPE); 327: if (so->so_error) { 328: error = so->so_error; 329: so->so_error = 0; /* ??? */ 330: splx(s); 331: goto release; 332: } 333: if ((so->so_state & SS_ISCONNECTED) == 0) { 334: if (so->so_proto->pr_flags & PR_CONNREQUIRED) 335: snderr(ENOTCONN); 336: if (nam == 0) 337: snderr(EDESTADDRREQ); 338: } 339: if (flags & MSG_OOB) 340: space = 1024; 341: else { 342: space = sbspace(&so->so_snd); 343: if (space <= rlen || 344: (sosendallatonce(so) && 345: space < uio->uio_resid + rlen) || 346: (uio->uio_resid >= CLBYTES && space < CLBYTES && 347: so->so_snd.sb_cc >= CLBYTES && 348: (so->so_state & SS_NBIO) == 0)) { 349: if (so->so_state & SS_NBIO) { 350: if (first) 351: error = EWOULDBLOCK; 352: splx(s); 353: goto release; 354: } 355: sbunlock(&so->so_snd); 356: sbwait(&so->so_snd); 357: splx(s); 358: goto restart; 359: } 360: } 361: splx(s); 362: mp = ⊤ 363: space -= rlen; 364: while (space > 0) { 365: MGET(m, M_WAIT, MT_DATA); 366: if (uio->uio_resid >= CLBYTES / 2 && space >= CLBYTES) { 367: MCLGET(m); 368: if (m->m_len != CLBYTES) 369: goto nopages; 370: len = MIN(CLBYTES, uio->uio_resid); 371: space -= CLBYTES; 372: } else { 373: nopages: 374: len = MIN(MIN(MLEN, uio->uio_resid), space); 375: space -= len; 376: } 377: error = uiomove(mtod(m, caddr_t), len, uio); 378: m->m_len = len; 379: *mp = m; 380: if (error) 381: goto release; 382: mp = &m->m_next; 383: if (uio->uio_resid == 0) 384: break; 385: } 386: if (dontroute) 387: so->so_options |= SO_DONTROUTE; 388: s = splnet(); /* XXX */ 389: error = (*so->so_proto->pr_usrreq)(so, 390: (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 391: top, (caddr_t)nam, rights); 392: splx(s); 393: if (dontroute) 394: so->so_options &= ~SO_DONTROUTE; 395: rights = 0; 396: rlen = 0; 397: top = 0; 398: first = 0; 399: if (error) 400: break; 401: } while (uio->uio_resid); 402: 403: release: 404: sbunlock(&so->so_snd); 405: if (top) 406: m_freem(top); 407: if (error == EPIPE) 408: NETPSIGNAL(u.u_procp, SIGPIPE); 409: return (error); 410: } 411: 412: /* 413: * Implement receive operations on a socket. 414: * We depend on the way that records are added to the sockbuf 415: * by sbappend*. In particular, each record (mbufs linked through m_next) 416: * must begin with an address if the protocol so specifies, 417: * followed by an optional mbuf containing access rights if supported 418: * by the protocol, and then zero or more mbufs of data. 419: * In order to avoid blocking network interrupts for the entire time here, 420: * we splx() while doing the actual copy to user space. 421: * Although the sockbuf is locked, new data may still be appended, 422: * and thus we must maintain consistency of the sockbuf during that time. 423: */ 424: soreceive(so, aname, uio, flags, rightsp) 425: register struct socket *so; 426: struct mbuf **aname; 427: register struct uio *uio; 428: int flags; 429: struct mbuf **rightsp; 430: { 431: register struct mbuf *m; 432: register int len, error = 0, s, offset; 433: struct protosw *pr = so->so_proto; 434: struct mbuf *nextrecord; 435: int moff; 436: 437: if (rightsp) 438: *rightsp = 0; 439: if (aname) 440: *aname = 0; 441: if (flags & MSG_OOB) { 442: m = m_get(M_WAIT, MT_DATA); 443: error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 444: m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); 445: if (error) 446: goto bad; 447: do { 448: len = uio->uio_resid; 449: if (len > m->m_len) 450: len = m->m_len; 451: error = 452: uiomove(mtod(m, caddr_t), (int)len, uio); 453: m = m_free(m); 454: } while (uio->uio_resid && error == 0 && m); 455: bad: 456: if (m) 457: m_freem(m); 458: return (error); 459: } 460: 461: restart: 462: sblock(&so->so_rcv); 463: s = splnet(); 464: 465: if (so->so_rcv.sb_cc == 0) { 466: if (so->so_error) { 467: error = so->so_error; 468: so->so_error = 0; 469: goto release; 470: } 471: if (so->so_state & SS_CANTRCVMORE) 472: goto release; 473: if ((so->so_state & SS_ISCONNECTED) == 0 && 474: (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 475: error = ENOTCONN; 476: goto release; 477: } 478: if (uio->uio_resid == 0) 479: goto release; 480: if (so->so_state & SS_NBIO) { 481: error = EWOULDBLOCK; 482: goto release; 483: } 484: sbunlock(&so->so_rcv); 485: sbwait(&so->so_rcv); 486: splx(s); 487: goto restart; 488: } 489: u.u_ru.ru_msgrcv++; 490: m = so->so_rcv.sb_mb; 491: if (m == 0) 492: panic("receive 1"); 493: nextrecord = m->m_act; 494: if (pr->pr_flags & PR_ADDR) { 495: if (m->m_type != MT_SONAME) 496: panic("receive 1a"); 497: if (flags & MSG_PEEK) { 498: if (aname) 499: *aname = m_copy(m, 0, m->m_len); 500: m = m->m_next; 501: } else { 502: sbfree(&so->so_rcv, m); 503: if (aname) { 504: *aname = m; 505: m = m->m_next; 506: (*aname)->m_next = 0; 507: so->so_rcv.sb_mb = m; 508: } else { 509: MFREE(m, so->so_rcv.sb_mb); 510: m = so->so_rcv.sb_mb; 511: } 512: if (m) 513: m->m_act = nextrecord; 514: } 515: } 516: if (m && m->m_type == MT_RIGHTS) { 517: if ((pr->pr_flags & PR_RIGHTS) == 0) 518: panic("receive 2"); 519: if (flags & MSG_PEEK) { 520: if (rightsp) 521: *rightsp = m_copy(m, 0, m->m_len); 522: m = m->m_next; 523: } else { 524: sbfree(&so->so_rcv, m); 525: if (rightsp) { 526: *rightsp = m; 527: so->so_rcv.sb_mb = m->m_next; 528: m->m_next = 0; 529: m = so->so_rcv.sb_mb; 530: } else { 531: MFREE(m, so->so_rcv.sb_mb); 532: m = so->so_rcv.sb_mb; 533: } 534: if (m) 535: m->m_act = nextrecord; 536: } 537: } 538: moff = 0; 539: offset = 0; 540: while (m && uio->uio_resid && error == 0) { 541: if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 542: panic("receive 3"); 543: len = uio->uio_resid; 544: so->so_state &= ~SS_RCVATMARK; 545: if (so->so_oobmark && len > so->so_oobmark - offset) 546: len = so->so_oobmark - offset; 547: if (len > m->m_len - moff) 548: len = m->m_len - moff; 549: splx(s); 550: error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); 551: s = splnet(); 552: if (len == m->m_len - moff) { 553: if (flags & MSG_PEEK) { 554: m = m->m_next; 555: moff = 0; 556: } else { 557: nextrecord = m->m_act; 558: sbfree(&so->so_rcv, m); 559: MFREE(m, so->so_rcv.sb_mb); 560: m = so->so_rcv.sb_mb; 561: if (m) 562: m->m_act = nextrecord; 563: } 564: } else { 565: if (flags & MSG_PEEK) 566: moff += len; 567: else { 568: m->m_off += len; 569: m->m_len -= len; 570: so->so_rcv.sb_cc -= len; 571: } 572: } 573: if (so->so_oobmark) { 574: if ((flags & MSG_PEEK) == 0) { 575: so->so_oobmark -= len; 576: if (so->so_oobmark == 0) { 577: so->so_state |= SS_RCVATMARK; 578: break; 579: } 580: } else 581: offset += len; 582: } 583: } 584: if ((flags & MSG_PEEK) == 0) { 585: if (m == 0) 586: so->so_rcv.sb_mb = nextrecord; 587: else if (pr->pr_flags & PR_ATOMIC) 588: (void) sbdroprecord(&so->so_rcv); 589: if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 590: (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 591: (struct mbuf *)0, (struct mbuf *)0); 592: if (error == 0 && rightsp && *rightsp && 593: pr->pr_domain->dom_externalize) 594: error = (*pr->pr_domain->dom_externalize)(*rightsp); 595: } 596: release: 597: sbunlock(&so->so_rcv); 598: splx(s); 599: return (error); 600: } 601: 602: soshutdown(so, how) 603: register struct socket *so; 604: register int how; 605: { 606: register struct protosw *pr = so->so_proto; 607: 608: how++; 609: if (how & FREAD) 610: sorflush(so); 611: if (how & FWRITE) 612: return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 613: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 614: return (0); 615: } 616: 617: sorflush(so) 618: register struct socket *so; 619: { 620: register struct sockbuf *sb = &so->so_rcv; 621: register struct protosw *pr = so->so_proto; 622: register int s; 623: struct sockbuf asb; 624: 625: sblock(sb); 626: s = splimp(); 627: socantrcvmore(so); 628: sbunlock(sb); 629: asb = *sb; 630: bzero((caddr_t)sb, sizeof (*sb)); 631: splx(s); 632: if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 633: (*pr->pr_domain->dom_dispose)(asb.sb_mb); 634: sbrelease(&asb); 635: } 636: 637: sosetopt(so, level, optname, m0) 638: register struct socket *so; 639: int level, optname; 640: struct mbuf *m0; 641: { 642: int error = 0; 643: register struct mbuf *m = m0; 644: 645: /* we make a copy because the kernel is faking the m0 mbuf and we have to 646: * have something for the m_free's to work with 647: */ 648: if (m0) 649: m = m0 = m_copy(m0, 0, M_COPYALL); 650: if (level != SOL_SOCKET) { 651: if (so->so_proto && so->so_proto->pr_ctloutput) 652: return ((*so->so_proto->pr_ctloutput) 653: (PRCO_SETOPT, so, level, optname, &m0)); 654: error = ENOPROTOOPT; 655: } else { 656: switch (optname) { 657: 658: case SO_LINGER: 659: if (m == NULL || m->m_len != sizeof (struct linger)) { 660: error = EINVAL; 661: goto bad; 662: } 663: so->so_linger = mtod(m, struct linger *)->l_linger; 664: /* fall thru... */ 665: 666: case SO_DEBUG: 667: case SO_KEEPALIVE: 668: case SO_DONTROUTE: 669: case SO_USELOOPBACK: 670: case SO_BROADCAST: 671: case SO_REUSEADDR: 672: case SO_OOBINLINE: 673: if (m == NULL || m->m_len < sizeof (int)) { 674: error = EINVAL; 675: goto bad; 676: } 677: if (*mtod(m, int *)) 678: so->so_options |= optname; 679: else 680: so->so_options &= ~optname; 681: break; 682: 683: case SO_SNDBUF: 684: case SO_RCVBUF: 685: case SO_SNDLOWAT: 686: case SO_RCVLOWAT: 687: case SO_SNDTIMEO: 688: case SO_RCVTIMEO: 689: if (m == NULL || m->m_len < sizeof (int)) { 690: error = EINVAL; 691: goto bad; 692: } 693: switch (optname) { 694: 695: case SO_SNDBUF: 696: case SO_RCVBUF: 697: if (sbreserve(optname == SO_SNDBUF ? &so->so_snd : 698: &so->so_rcv, *mtod(m, int *)) == 0) { 699: error = ENOBUFS; 700: goto bad; 701: } 702: break; 703: 704: case SO_SNDLOWAT: 705: so->so_snd.sb_lowat = *mtod(m, int *); 706: break; 707: case SO_RCVLOWAT: 708: so->so_rcv.sb_lowat = *mtod(m, int *); 709: break; 710: case SO_SNDTIMEO: 711: so->so_snd.sb_timeo = *mtod(m, int *); 712: break; 713: case SO_RCVTIMEO: 714: so->so_rcv.sb_timeo = *mtod(m, int *); 715: break; 716: } 717: break; 718: 719: default: 720: error = ENOPROTOOPT; 721: break; 722: } 723: } 724: bad: 725: if (m) 726: (void) m_free(m); 727: return (error); 728: } 729: 730: sogetopt(so, level, optname, mp) 731: register struct socket *so; 732: int level, optname; 733: struct mbuf **mp; 734: { 735: register struct mbuf *m; 736: 737: if (level != SOL_SOCKET) { 738: if (so->so_proto && so->so_proto->pr_ctloutput) { 739: return ((*so->so_proto->pr_ctloutput) 740: (PRCO_GETOPT, so, level, optname, mp)); 741: } else 742: return (ENOPROTOOPT); 743: } else { 744: m = m_get(M_WAIT, MT_SOOPTS); 745: m->m_len = sizeof (int); 746: 747: switch (optname) { 748: 749: case SO_LINGER: 750: m->m_len = sizeof (struct linger); 751: mtod(m, struct linger *)->l_onoff = 752: so->so_options & SO_LINGER; 753: mtod(m, struct linger *)->l_linger = so->so_linger; 754: break; 755: 756: case SO_USELOOPBACK: 757: case SO_DONTROUTE: 758: case SO_DEBUG: 759: case SO_KEEPALIVE: 760: case SO_REUSEADDR: 761: case SO_BROADCAST: 762: case SO_OOBINLINE: 763: *mtod(m, int *) = so->so_options & optname; 764: break; 765: 766: case SO_TYPE: 767: *mtod(m, int *) = so->so_type; 768: break; 769: 770: case SO_ERROR: 771: *mtod(m, int *) = so->so_error; 772: so->so_error = 0; 773: break; 774: 775: case SO_SNDBUF: 776: *mtod(m, int *) = so->so_snd.sb_hiwat; 777: break; 778: 779: case SO_RCVBUF: 780: *mtod(m, int *) = so->so_rcv.sb_hiwat; 781: break; 782: 783: case SO_SNDLOWAT: 784: *mtod(m, int *) = so->so_snd.sb_lowat; 785: break; 786: 787: case SO_RCVLOWAT: 788: *mtod(m, int *) = so->so_rcv.sb_lowat; 789: break; 790: 791: case SO_SNDTIMEO: 792: *mtod(m, int *) = so->so_snd.sb_timeo; 793: break; 794: 795: case SO_RCVTIMEO: 796: *mtod(m, int *) = so->so_rcv.sb_timeo; 797: break; 798: 799: default: 800: (void)m_free(m); 801: return (ENOPROTOOPT); 802: } 803: *mp = m; 804: return (0); 805: } 806: } 807: 808: sohasoutofband(so) 809: register struct socket *so; 810: { 811: register struct proc *p; 812: 813: if (so->so_pgrp < 0) 814: GSIGNAL(-so->so_pgrp, SIGURG); 815: else if (so->so_pgrp > 0 && 816: (p = (struct proc *)NETPFIND(so->so_pgrp)) != 0) 817: NETPSIGNAL(p, SIGURG); 818: if (so->so_rcv.sb_sel) { 819: SELWAKEUP(so->so_rcv.sb_sel, 820: (long)(so->so_rcv.sb_flags & SB_COLL)); 821: so->so_rcv.sb_sel = 0; 822: so->so_rcv.sb_flags &= ~SB_COLL; 823: } 824: } 825: 826: /* 827: * this routine was extracted from the accept() call in uipc_sys.c to 828: * do the initial accept processing in the supervisor rather than copying 829: * the socket struct back and forth. 830: */ 831: 832: soacc1(so) 833: register struct socket *so; 834: { 835: 836: if ((so->so_options & SO_ACCEPTCONN) == 0) 837: return(u.u_error = EINVAL); 838: if ((so->so_state & SS_NBIO) && so->so_qlen == 0) 839: return(u.u_error = EWOULDBLOCK); 840: while (so->so_qlen == 0 && so->so_error == 0) 841: { 842: if (so->so_state & SS_CANTRCVMORE) 843: { 844: so->so_error = ECONNABORTED; 845: break; 846: } 847: SLEEP(&so->so_timeo, PZERO+1); 848: } 849: if (so->so_error) 850: { 851: u.u_error = so->so_error; 852: so->so_error = 0; 853: return(u.u_error); 854: } 855: return(0); 856: } 857: 858: /* 859: * used to dequeue a connection request. the panic on nothing left is 860: * done in the kernel when we return 0. 861: */ 862: 863: struct socket * 864: asoqremque(so, n) 865: struct socket *so; 866: int n; 867: { 868: register struct socket *aso; 869: 870: aso = so->so_q; 871: if (soqremque(aso, n) == 0) 872: return(0); 873: return(aso); 874: } 875: 876: /* 877: * this is the while loop from connect(), the setjmp has been done in 878: * kernel, so we just wait for isconnecting to go away. 879: */ 880: 881: connwhile(so) 882: register struct socket *so; 883: { 884: 885: while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 886: SLEEP(&so->so_timeo, PZERO+1); 887: u.u_error = so->so_error; 888: so->so_error = 0; 889: so->so_state &= ~SS_ISCONNECTING; 890: return(u.u_error); 891: } 892: 893: sogetnam(so, m) 894: register struct socket *so; 895: struct mbuf *m; 896: { 897: return(u.u_error=(*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0)); 898: } 899: 900: sogetpeer(so, m) 901: register struct socket *so; 902: struct mbuf *m; 903: { 904: 905: if ((so->so_state & SS_ISCONNECTED) == 0) 906: return(u.u_error = ENOTCONN); 907: return(u.u_error=(*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0)); 908: } 909: #endif