1*16993Skarels /* uipc_socket.c 6.6 84/08/21 */ 24786Swnj 34786Swnj #include "../h/param.h" 44829Swnj #include "../h/systm.h" 54786Swnj #include "../h/dir.h" 64786Swnj #include "../h/user.h" 74829Swnj #include "../h/proc.h" 84829Swnj #include "../h/file.h" 94786Swnj #include "../h/inode.h" 104829Swnj #include "../h/buf.h" 114786Swnj #include "../h/mbuf.h" 1212757Ssam #include "../h/un.h" 13*16993Skarels #include "../h/domain.h" 144829Swnj #include "../h/protosw.h" 154829Swnj #include "../h/socket.h" 164829Swnj #include "../h/socketvar.h" 174916Swnj #include "../h/stat.h" 185281Sroot #include "../h/ioctl.h" 198391Swnj #include "../h/uio.h" 206355Ssam #include "../net/route.h" 2112757Ssam #include "../netinet/in.h" 2211571Ssam #include "../net/if.h" 234786Swnj 244786Swnj /* 258300Sroot * Socket operation routines. 268300Sroot * These routines are called by the routines in 278300Sroot * sys_socket.c or from a system process, and 288300Sroot * implement the semantics of socket operations by 298300Sroot * switching out to the protocol specific routines. 3012757Ssam * 3112757Ssam * TODO: 3212757Ssam * sostat 3312757Ssam * test socketpair 3412757Ssam * PR_RIGHTS 3512757Ssam * clean up select, async 3612757Ssam * out-of-band is a kludge 374786Swnj */ 388594Sroot /*ARGSUSED*/ 3910267Ssam socreate(dom, aso, type, proto) 404786Swnj struct socket **aso; 4112757Ssam register int type; 4212757Ssam int proto; 434786Swnj { 444786Swnj register struct protosw *prp; 454786Swnj register struct socket *so; 4612757Ssam register struct mbuf *m; 4712757Ssam register int error; 484786Swnj 494890Swnj if (proto) 509168Ssam prp = pffindproto(dom, proto); 514890Swnj else 529168Ssam prp = pffindtype(dom, type); 534890Swnj if (prp == 0) 544890Swnj return (EPROTONOSUPPORT); 558300Sroot if (prp->pr_type != type) 568300Sroot return (EPROTOTYPE); 579635Ssam m = m_getclr(M_WAIT, MT_SOCKET); 584786Swnj if (m == 0) 594786Swnj return (ENOBUFS); 604786Swnj so = mtod(m, struct socket *); 6112757Ssam so->so_options = 0; 626214Swnj so->so_state = 0; 639168Ssam so->so_type = type; 646214Swnj if (u.u_uid == 0) 656214Swnj so->so_state = SS_PRIV; 664786Swnj so->so_proto = prp; 6712757Ssam error = 6812757Ssam (*prp->pr_usrreq)(so, PRU_ATTACH, 6912757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 704979Swnj if (error) { 717507Sroot so->so_state |= SS_NOFDREF; 727180Swnj sofree(so); 734890Swnj return (error); 744786Swnj } 754786Swnj *aso = so; 764786Swnj return (0); 774786Swnj } 784786Swnj 7910267Ssam sobind(so, nam) 808300Sroot struct socket *so; 818300Sroot struct mbuf *nam; 828300Sroot { 838300Sroot int s = splnet(); 848300Sroot int error; 858300Sroot 868300Sroot error = 8712757Ssam (*so->so_proto->pr_usrreq)(so, PRU_BIND, 8812757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 898300Sroot splx(s); 908300Sroot return (error); 918300Sroot } 928300Sroot 938300Sroot solisten(so, backlog) 9412757Ssam register struct socket *so; 958300Sroot int backlog; 968300Sroot { 9712757Ssam int s = splnet(), error; 988300Sroot 9912757Ssam error = 10012757Ssam (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 10112757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 1028300Sroot if (error) { 1038300Sroot splx(s); 1048300Sroot return (error); 1058300Sroot } 1068300Sroot if (so->so_q == 0) { 1078300Sroot so->so_q = so; 1088300Sroot so->so_q0 = so; 1098300Sroot so->so_options |= SO_ACCEPTCONN; 1108300Sroot } 1118300Sroot if (backlog < 0) 1128300Sroot backlog = 0; 11310137Ssam so->so_qlimit = MIN(backlog, SOMAXCONN); 11412493Ssam splx(s); 1158300Sroot return (0); 1168300Sroot } 1178300Sroot 1184916Swnj sofree(so) 11912757Ssam register struct socket *so; 1204916Swnj { 1214916Swnj 1227507Sroot if (so->so_head) { 1237507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1247507Sroot panic("sofree dq"); 1257507Sroot so->so_head = 0; 1267507Sroot } 1277507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1284950Swnj return; 1294950Swnj sbrelease(&so->so_snd); 13012757Ssam sorflush(so); 1314971Swnj (void) m_free(dtom(so)); 1324916Swnj } 1334916Swnj 1344786Swnj /* 1354890Swnj * Close a socket on last file table reference removal. 1364890Swnj * Initiate disconnect if connected. 1374890Swnj * Free socket when disconnect complete. 1384829Swnj */ 13912757Ssam soclose(so) 1404829Swnj register struct socket *so; 1414829Swnj { 1424890Swnj int s = splnet(); /* conservative */ 1438713Sroot int error; 1444829Swnj 1457507Sroot if (so->so_options & SO_ACCEPTCONN) { 1467507Sroot while (so->so_q0 != so) 14710399Ssam (void) soabort(so->so_q0); 1487507Sroot while (so->so_q != so) 14910399Ssam (void) soabort(so->so_q); 1507507Sroot } 1514890Swnj if (so->so_pcb == 0) 1524890Swnj goto discard; 1534890Swnj if (so->so_state & SS_ISCONNECTED) { 1544890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1558725Sroot error = sodisconnect(so, (struct mbuf *)0); 15612757Ssam if (error) 15712757Ssam goto drop; 1584890Swnj } 15910267Ssam if (so->so_options & SO_LINGER) { 1605281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 16112757Ssam (so->so_state & SS_NBIO)) 16212757Ssam goto drop; 1635281Sroot while (so->so_state & SS_ISCONNECTED) 1645281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1654890Swnj } 1664890Swnj } 1675580Sroot drop: 1686880Ssam if (so->so_pcb) { 16912757Ssam int error2 = 17012757Ssam (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 17112757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 17212757Ssam if (error == 0) 17312757Ssam error = error2; 1746880Ssam } 1754890Swnj discard: 17610399Ssam if (so->so_state & SS_NOFDREF) 17710399Ssam panic("soclose: NOFDREF"); 1787507Sroot so->so_state |= SS_NOFDREF; 1794950Swnj sofree(so); 1804890Swnj splx(s); 18112757Ssam return (error); 1824829Swnj } 1834829Swnj 18410399Ssam /* 18510399Ssam * Must be called at splnet... 18610399Ssam */ 18710399Ssam soabort(so) 18810399Ssam struct socket *so; 18910399Ssam { 19010399Ssam 19112757Ssam return ( 19212757Ssam (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 19312757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 19410399Ssam } 19510399Ssam 19610267Ssam soaccept(so, nam) 19712757Ssam register struct socket *so; 1988300Sroot struct mbuf *nam; 1994927Swnj { 2004927Swnj int s = splnet(); 2014927Swnj int error; 2024927Swnj 20310399Ssam if ((so->so_state & SS_NOFDREF) == 0) 20410399Ssam panic("soaccept: !NOFDREF"); 20510267Ssam so->so_state &= ~SS_NOFDREF; 2068300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 20712757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2084927Swnj splx(s); 2094927Swnj return (error); 2104927Swnj } 2114927Swnj 21210267Ssam soconnect(so, nam) 21312757Ssam register struct socket *so; 2148300Sroot struct mbuf *nam; 2154786Swnj { 2164890Swnj int s = splnet(); 2174890Swnj int error; 2184786Swnj 2194890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2204890Swnj error = EISCONN; 2214890Swnj goto bad; 2224890Swnj } 2238300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 22412757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2254890Swnj bad: 2264890Swnj splx(s); 2274890Swnj return (error); 2284786Swnj } 2294786Swnj 23012757Ssam soconnect2(so1, so2) 23112757Ssam register struct socket *so1; 23212757Ssam struct socket *so2; 23312757Ssam { 23412757Ssam int s = splnet(); 23512757Ssam int error; 23612757Ssam 23713113Ssam error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 23813113Ssam (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 23912757Ssam splx(s); 24012757Ssam return (error); 24112757Ssam } 24212757Ssam 2438300Sroot sodisconnect(so, nam) 24412757Ssam register struct socket *so; 2458300Sroot struct mbuf *nam; 2464786Swnj { 2474890Swnj int s = splnet(); 2484890Swnj int error; 2494786Swnj 2504890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2514890Swnj error = ENOTCONN; 2524890Swnj goto bad; 2534890Swnj } 2544890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2554890Swnj error = EALREADY; 2564890Swnj goto bad; 2574890Swnj } 2588300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 25912757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2604890Swnj bad: 2614890Swnj splx(s); 2624890Swnj return (error); 2634786Swnj } 2644786Swnj 2654786Swnj /* 2664890Swnj * Send on a socket. 2674890Swnj * If send must go all at once and message is larger than 2684890Swnj * send buffering, then hard error. 2694890Swnj * Lock against other senders. 2704890Swnj * If must go all at once and not enough room now, then 2714890Swnj * inform user that this would block and do nothing. 27216412Skarels * Otherwise, if nonblocking, send as much as possible. 2734786Swnj */ 27412757Ssam sosend(so, nam, uio, flags, rights) 2754786Swnj register struct socket *so; 2768300Sroot struct mbuf *nam; 27712757Ssam register struct uio *uio; 2788319Sroot int flags; 27912757Ssam struct mbuf *rights; 2804786Swnj { 2814890Swnj struct mbuf *top = 0; 28216412Skarels register struct mbuf *m, **mp; 28312757Ssam register int space; 28416412Skarels int len, error = 0, s, dontroute, first = 1; 2854786Swnj 2867827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2874890Swnj return (EMSGSIZE); 28812757Ssam dontroute = 28912757Ssam (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 29012757Ssam (so->so_proto->pr_flags & PR_ATOMIC); 29116412Skarels u.u_ru.ru_msgsnd++; 29216412Skarels #define snderr(errno) { error = errno; splx(s); goto release; } 29316412Skarels 2946419Sroot restart: 2954890Swnj sblock(&so->so_snd); 29616412Skarels do { 29716412Skarels s = splnet(); 29816412Skarels if (so->so_state & SS_CANTSENDMORE) { 29916412Skarels psignal(u.u_procp, SIGPIPE); 30016412Skarels snderr(EPIPE); 30116412Skarels } 30216412Skarels if (so->so_error) { 30316412Skarels error = so->so_error; 30416412Skarels so->so_error = 0; /* ??? */ 30516412Skarels splx(s); 30616412Skarels goto release; 30716412Skarels } 30816412Skarels if ((so->so_state & SS_ISCONNECTED) == 0) { 30916412Skarels if (so->so_proto->pr_flags & PR_CONNREQUIRED) 31016412Skarels snderr(ENOTCONN); 31116412Skarels if (nam == 0) 31216412Skarels snderr(EDESTADDRREQ); 31316412Skarels } 31416412Skarels if (flags & MSG_OOB) 31516412Skarels space = 1024; 31616412Skarels else { 31716412Skarels space = sbspace(&so->so_snd); 31816412Skarels if (space <= 0 || 31916992Skarels (sosendallatonce(so) && space < uio->uio_resid) || 32016992Skarels (uio->uio_resid >= CLBYTES && space < CLBYTES && 32116992Skarels so->so_snd.sb_cc >= CLBYTES && 32216992Skarels (so->so_state & SS_NBIO) == 0)) { 32316412Skarels if (so->so_state & SS_NBIO) { 32416412Skarels if (first) 32516412Skarels error = EWOULDBLOCK; 32616412Skarels splx(s); 32716412Skarels goto release; 32816412Skarels } 32916412Skarels sbunlock(&so->so_snd); 33016412Skarels sbwait(&so->so_snd); 33116412Skarels splx(s); 33216412Skarels goto restart; 33316412Skarels } 33416412Skarels } 33516412Skarels splx(s); 33616412Skarels mp = ⊤ 33716412Skarels while (uio->uio_resid > 0 && space > 0) { 33816412Skarels register struct iovec *iov = uio->uio_iov; 3394890Swnj 34016412Skarels if (iov->iov_len == 0) { 34116412Skarels uio->uio_iov++; 34216412Skarels uio->uio_iovcnt--; 34316412Skarels if (uio->uio_iovcnt < 0) 34416412Skarels panic("sosend"); 34516412Skarels continue; 34616412Skarels } 34716412Skarels MGET(m, M_WAIT, MT_DATA); 34816412Skarels if (m == NULL) { 34916412Skarels error = ENOBUFS; /* SIGPIPE? */ 35016412Skarels goto release; 35116412Skarels } 35216412Skarels if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 35316412Skarels register struct mbuf *p; 35416412Skarels MCLGET(p, 1); 35516412Skarels if (p == 0) 35616412Skarels goto nopages; 35716412Skarels m->m_off = (int)p - (int)m; 35816412Skarels len = CLBYTES; 35916412Skarels } else { 36016412Skarels nopages: 36116412Skarels len = MIN(MLEN, iov->iov_len); 36216412Skarels } 36316412Skarels error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 36416412Skarels m->m_len = len; 36516412Skarels *mp = m; 36616412Skarels if (error) 36716412Skarels goto release; 36816412Skarels mp = &m->m_next; 36916412Skarels space -= len; 37016412Skarels } 37116992Skarels if (top) { 37216992Skarels if (dontroute) 37316992Skarels so->so_options |= SO_DONTROUTE; 37416992Skarels s = splnet(); 37516992Skarels error = (*so->so_proto->pr_usrreq)(so, 37616992Skarels (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 37716992Skarels top, (caddr_t)nam, rights); 37816992Skarels splx(s); 37916992Skarels if (dontroute) 38016992Skarels so->so_options &= ~SO_DONTROUTE; 38116992Skarels } 3826419Sroot top = 0; 38316412Skarels first = 0; 38414781Ssam if (error) 38516412Skarels break; 38616412Skarels } while (uio->uio_resid); 3874890Swnj 3884786Swnj release: 3894890Swnj sbunlock(&so->so_snd); 3906419Sroot if (top) 3916419Sroot m_freem(top); 3924786Swnj return (error); 3934786Swnj } 3944786Swnj 39512757Ssam soreceive(so, aname, uio, flags, rightsp) 3964786Swnj register struct socket *so; 3978300Sroot struct mbuf **aname; 39812757Ssam register struct uio *uio; 3998319Sroot int flags; 40012757Ssam struct mbuf **rightsp; 4014786Swnj { 4024786Swnj register struct mbuf *m, *n; 403*16993Skarels register int len, error = 0, s, tomark; 40412757Ssam struct protosw *pr = so->so_proto; 405*16993Skarels struct mbuf *nextrecord; 40612757Ssam int moff; 4074786Swnj 40812757Ssam if (rightsp) 40912757Ssam *rightsp = 0; 41012757Ssam if (aname) 41112757Ssam *aname = 0; 41212757Ssam if (flags & MSG_OOB) { 4139635Ssam m = m_get(M_WAIT, MT_DATA); 41412757Ssam if (m == 0) 41510137Ssam return (ENOBUFS); 41612757Ssam error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 41712757Ssam m, (struct mbuf *)0, (struct mbuf *)0); 4188594Sroot if (error) 41910137Ssam goto bad; 4208319Sroot do { 42110137Ssam len = uio->uio_resid; 4228319Sroot if (len > m->m_len) 4238319Sroot len = m->m_len; 4248594Sroot error = 4258793Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 4268319Sroot m = m_free(m); 4278594Sroot } while (uio->uio_resid && error == 0 && m); 42810137Ssam bad: 4298319Sroot if (m) 4308771Sroot m_freem(m); 4318594Sroot return (error); 4328319Sroot } 4338319Sroot 4344890Swnj restart: 4354890Swnj sblock(&so->so_rcv); 4368835Sroot s = splnet(); 4374890Swnj 4384890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4394786Swnj if (so->so_rcv.sb_cc == 0) { 4405168Swnj if (so->so_error) { 4415168Swnj error = so->so_error; 4425168Swnj so->so_error = 0; 4435168Swnj splx(s); 4445168Swnj goto release; 4455168Swnj } 4464890Swnj if (so->so_state & SS_CANTRCVMORE) { 4474890Swnj splx(s); 4484890Swnj goto release; 4494890Swnj } 4505015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4515015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4525015Sroot rcverr(ENOTCONN); 4536214Swnj if (so->so_state & SS_NBIO) 4545168Swnj rcverr(EWOULDBLOCK); 4554890Swnj sbunlock(&so->so_rcv); 4564971Swnj sbwait(&so->so_rcv); 4575012Swnj splx(s); 4584890Swnj goto restart; 4594786Swnj } 4608041Sroot u.u_ru.ru_msgrcv++; 4614829Swnj m = so->so_rcv.sb_mb; 46212757Ssam if (pr->pr_flags & PR_ADDR) { 463*16993Skarels if (m == 0 || m->m_type != MT_SONAME) 464*16993Skarels panic("receive 1a"); 465*16993Skarels if (flags & MSG_PEEK) { 466*16993Skarels if (aname) 4678319Sroot *aname = m_copy(m, 0, m->m_len); 468*16993Skarels else 469*16993Skarels m = m->m_act; 470*16993Skarels } else { 471*16993Skarels if (aname) { 472*16993Skarels *aname = m; 473*16993Skarels sbfree(&so->so_rcv, m); 474*16993Skarels if(m->m_next) panic("receive 1b"); 475*16993Skarels so->so_rcv.sb_mb = m = m->m_act; 47610137Ssam } else 477*16993Skarels m = sbdroprecord(&so->so_rcv); 478*16993Skarels } 479*16993Skarels } 480*16993Skarels if (m && m->m_type == MT_RIGHTS) { 481*16993Skarels if ((pr->pr_flags & PR_RIGHTS) == 0) 48212757Ssam panic("receive 2a"); 483*16993Skarels if (flags & MSG_PEEK) { 484*16993Skarels if (rightsp) 48512757Ssam *rightsp = m_copy(m, 0, m->m_len); 486*16993Skarels else 487*16993Skarels m = m->m_act; 488*16993Skarels } else { 489*16993Skarels if (rightsp) { 490*16993Skarels *rightsp = m; 491*16993Skarels sbfree(&so->so_rcv, m); 492*16993Skarels if(m->m_next) panic("receive 2b"); 493*16993Skarels so->so_rcv.sb_mb = m = m->m_act; 494*16993Skarels } else 495*16993Skarels m = sbdroprecord(&so->so_rcv); 49612757Ssam } 4974890Swnj } 498*16993Skarels if (m == 0) 499*16993Skarels panic("receive 3"); 5008319Sroot moff = 0; 5018319Sroot tomark = so->so_oobmark; 502*16993Skarels while (m && uio->uio_resid > 0 && error == 0) { 5037827Sroot len = uio->uio_resid; 5047747Sroot so->so_state &= ~SS_RCVATMARK; 5058319Sroot if (tomark && len > tomark) 5068319Sroot len = tomark; 5078548Sroot if (moff+len > m->m_len - moff) 5088319Sroot len = m->m_len - moff; 5094786Swnj splx(s); 5108594Sroot error = 5118793Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 5124786Swnj s = splnet(); 5134786Swnj if (len == m->m_len) { 514*16993Skarels if ((flags & MSG_PEEK) == 0) { 515*16993Skarels nextrecord = m->m_act; 5168319Sroot sbfree(&so->so_rcv, m); 5178319Sroot MFREE(m, n); 518*16993Skarels if (m = n) 519*16993Skarels m->m_act = nextrecord; 5208548Sroot so->so_rcv.sb_mb = m; 521*16993Skarels } else 522*16993Skarels m = m->m_next; 5238319Sroot moff = 0; 5244786Swnj } else { 52512757Ssam if (flags & MSG_PEEK) 5268319Sroot moff += len; 5278319Sroot else { 5288319Sroot m->m_off += len; 5298319Sroot m->m_len -= len; 5308319Sroot so->so_rcv.sb_cc -= len; 5318319Sroot } 5324786Swnj } 53312757Ssam if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 5347747Sroot so->so_oobmark -= len; 5357747Sroot if (so->so_oobmark == 0) { 5367747Sroot so->so_state |= SS_RCVATMARK; 5377747Sroot break; 5387747Sroot } 5397747Sroot } 5408319Sroot if (tomark) { 5418319Sroot tomark -= len; 5428319Sroot if (tomark == 0) 5438319Sroot break; 5448319Sroot } 545*16993Skarels } 546*16993Skarels if ((flags & MSG_PEEK) == 0) { 547*16993Skarels if (m == 0) 548*16993Skarels so->so_rcv.sb_mb = nextrecord; 549*16993Skarels else if (pr->pr_flags & PR_ATOMIC) 550*16993Skarels (void) sbdroprecord(&so->so_rcv); 551*16993Skarels if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 552*16993Skarels (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 553*16993Skarels (struct mbuf *)0, (struct mbuf *)0); 554*16993Skarels } 5554890Swnj release: 5564916Swnj sbunlock(&so->so_rcv); 557*16993Skarels if (error == 0 && rightsp && *rightsp && pr->pr_domain->dom_externalize) 558*16993Skarels error = (*pr->pr_domain->dom_externalize)(*rightsp); 5594890Swnj splx(s); 5604916Swnj return (error); 5614786Swnj } 5624786Swnj 56310267Ssam soshutdown(so, how) 56412757Ssam register struct socket *so; 56512757Ssam register int how; 56610267Ssam { 56712757Ssam register struct protosw *pr = so->so_proto; 56810267Ssam 56910267Ssam how++; 57012757Ssam if (how & FREAD) 57112757Ssam sorflush(so); 57210267Ssam if (how & FWRITE) 57312757Ssam return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 57412757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 57510267Ssam return (0); 57610267Ssam } 57710267Ssam 57812757Ssam sorflush(so) 57912757Ssam register struct socket *so; 58012757Ssam { 58112757Ssam register struct sockbuf *sb = &so->so_rcv; 58212757Ssam register struct protosw *pr = so->so_proto; 58312757Ssam register int s; 58412757Ssam struct sockbuf asb; 58512757Ssam 58612757Ssam sblock(sb); 58712757Ssam s = splimp(); 58812757Ssam socantrcvmore(so); 58912757Ssam sbunlock(sb); 59012757Ssam asb = *sb; 59112757Ssam bzero((caddr_t)sb, sizeof (*sb)); 59212757Ssam splx(s); 593*16993Skarels if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 594*16993Skarels (*pr->pr_domain->dom_dispose)(asb.sb_mb); 59512757Ssam sbrelease(&asb); 59612757Ssam } 59712757Ssam 59810267Ssam sosetopt(so, level, optname, m) 59912757Ssam register struct socket *so; 60010267Ssam int level, optname; 60112757Ssam register struct mbuf *m; 60210267Ssam { 60310267Ssam 60410267Ssam if (level != SOL_SOCKET) 60510267Ssam return (EINVAL); /* XXX */ 60610267Ssam switch (optname) { 60710267Ssam 60810267Ssam case SO_DEBUG: 60910269Ssam case SO_KEEPALIVE: 61010599Ssam case SO_DONTROUTE: 61110599Ssam case SO_USELOOPBACK: 61210599Ssam case SO_REUSEADDR: 61310599Ssam so->so_options |= optname; 61410269Ssam break; 61510269Ssam 61610267Ssam case SO_LINGER: 61710269Ssam if (m == NULL || m->m_len != sizeof (int)) 61810269Ssam return (EINVAL); 61910267Ssam so->so_options |= SO_LINGER; 62010269Ssam so->so_linger = *mtod(m, int *); 62110267Ssam break; 62210267Ssam 62310267Ssam case SO_DONTLINGER: 62410267Ssam so->so_options &= ~SO_LINGER; 62510267Ssam so->so_linger = 0; 62610267Ssam break; 62710267Ssam 62810267Ssam default: 62910267Ssam return (EINVAL); 63010267Ssam } 63110267Ssam return (0); 63210267Ssam } 63310267Ssam 63410267Ssam sogetopt(so, level, optname, m) 63512757Ssam register struct socket *so; 63610267Ssam int level, optname; 63712757Ssam register struct mbuf *m; 63810267Ssam { 63910267Ssam 64010267Ssam if (level != SOL_SOCKET) 64110267Ssam return (EINVAL); /* XXX */ 64210267Ssam switch (optname) { 64310267Ssam 64410267Ssam case SO_USELOOPBACK: 64510267Ssam case SO_DONTROUTE: 64610267Ssam case SO_DEBUG: 64710267Ssam case SO_KEEPALIVE: 64810267Ssam case SO_LINGER: 64910599Ssam case SO_REUSEADDR: 65010267Ssam if ((so->so_options & optname) == 0) 65110267Ssam return (ENOPROTOOPT); 65210269Ssam if (optname == SO_LINGER && m != NULL) { 65310267Ssam *mtod(m, int *) = so->so_linger; 65410267Ssam m->m_len = sizeof (so->so_linger); 65510267Ssam } 65610267Ssam break; 65710267Ssam 65810267Ssam default: 65910267Ssam return (EINVAL); 66010267Ssam } 66110267Ssam return (0); 66210267Ssam } 66310267Ssam 6645423Swnj sohasoutofband(so) 66512757Ssam register struct socket *so; 6665423Swnj { 6675423Swnj 6685423Swnj if (so->so_pgrp == 0) 6695423Swnj return; 6705423Swnj if (so->so_pgrp > 0) 6715423Swnj gsignal(so->so_pgrp, SIGURG); 6725429Swnj else { 6735429Swnj struct proc *p = pfind(-so->so_pgrp); 6745429Swnj 6755429Swnj if (p) 6765429Swnj psignal(p, SIGURG); 6775429Swnj } 6785423Swnj } 679