1*16992Skarels /* uipc_socket.c 6.5 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" 134829Swnj #include "../h/protosw.h" 144829Swnj #include "../h/socket.h" 154829Swnj #include "../h/socketvar.h" 164916Swnj #include "../h/stat.h" 175281Sroot #include "../h/ioctl.h" 188391Swnj #include "../h/uio.h" 196355Ssam #include "../net/route.h" 2012757Ssam #include "../netinet/in.h" 2111571Ssam #include "../net/if.h" 224786Swnj 234786Swnj /* 248300Sroot * Socket operation routines. 258300Sroot * These routines are called by the routines in 268300Sroot * sys_socket.c or from a system process, and 278300Sroot * implement the semantics of socket operations by 288300Sroot * switching out to the protocol specific routines. 2912757Ssam * 3012757Ssam * TODO: 3112757Ssam * sostat 3212757Ssam * test socketpair 3312757Ssam * PR_RIGHTS 3412757Ssam * clean up select, async 3512757Ssam * out-of-band is a kludge 364786Swnj */ 378594Sroot /*ARGSUSED*/ 3810267Ssam socreate(dom, aso, type, proto) 394786Swnj struct socket **aso; 4012757Ssam register int type; 4112757Ssam int proto; 424786Swnj { 434786Swnj register struct protosw *prp; 444786Swnj register struct socket *so; 4512757Ssam register struct mbuf *m; 4612757Ssam register int error; 474786Swnj 484890Swnj if (proto) 499168Ssam prp = pffindproto(dom, proto); 504890Swnj else 519168Ssam prp = pffindtype(dom, type); 524890Swnj if (prp == 0) 534890Swnj return (EPROTONOSUPPORT); 548300Sroot if (prp->pr_type != type) 558300Sroot return (EPROTOTYPE); 569635Ssam m = m_getclr(M_WAIT, MT_SOCKET); 574786Swnj if (m == 0) 584786Swnj return (ENOBUFS); 594786Swnj so = mtod(m, struct socket *); 6012757Ssam so->so_options = 0; 616214Swnj so->so_state = 0; 629168Ssam so->so_type = type; 636214Swnj if (u.u_uid == 0) 646214Swnj so->so_state = SS_PRIV; 654786Swnj so->so_proto = prp; 6612757Ssam error = 6712757Ssam (*prp->pr_usrreq)(so, PRU_ATTACH, 6812757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 694979Swnj if (error) { 707507Sroot so->so_state |= SS_NOFDREF; 717180Swnj sofree(so); 724890Swnj return (error); 734786Swnj } 744786Swnj *aso = so; 754786Swnj return (0); 764786Swnj } 774786Swnj 7810267Ssam sobind(so, nam) 798300Sroot struct socket *so; 808300Sroot struct mbuf *nam; 818300Sroot { 828300Sroot int s = splnet(); 838300Sroot int error; 848300Sroot 858300Sroot error = 8612757Ssam (*so->so_proto->pr_usrreq)(so, PRU_BIND, 8712757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 888300Sroot splx(s); 898300Sroot return (error); 908300Sroot } 918300Sroot 928300Sroot solisten(so, backlog) 9312757Ssam register struct socket *so; 948300Sroot int backlog; 958300Sroot { 9612757Ssam int s = splnet(), error; 978300Sroot 9812757Ssam error = 9912757Ssam (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 10012757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 1018300Sroot if (error) { 1028300Sroot splx(s); 1038300Sroot return (error); 1048300Sroot } 1058300Sroot if (so->so_q == 0) { 1068300Sroot so->so_q = so; 1078300Sroot so->so_q0 = so; 1088300Sroot so->so_options |= SO_ACCEPTCONN; 1098300Sroot } 1108300Sroot if (backlog < 0) 1118300Sroot backlog = 0; 11210137Ssam so->so_qlimit = MIN(backlog, SOMAXCONN); 11312493Ssam splx(s); 1148300Sroot return (0); 1158300Sroot } 1168300Sroot 1174916Swnj sofree(so) 11812757Ssam register struct socket *so; 1194916Swnj { 1204916Swnj 1217507Sroot if (so->so_head) { 1227507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1237507Sroot panic("sofree dq"); 1247507Sroot so->so_head = 0; 1257507Sroot } 1267507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1274950Swnj return; 1284950Swnj sbrelease(&so->so_snd); 12912757Ssam sorflush(so); 1304971Swnj (void) m_free(dtom(so)); 1314916Swnj } 1324916Swnj 1334786Swnj /* 1344890Swnj * Close a socket on last file table reference removal. 1354890Swnj * Initiate disconnect if connected. 1364890Swnj * Free socket when disconnect complete. 1374829Swnj */ 13812757Ssam soclose(so) 1394829Swnj register struct socket *so; 1404829Swnj { 1414890Swnj int s = splnet(); /* conservative */ 1428713Sroot int error; 1434829Swnj 1447507Sroot if (so->so_options & SO_ACCEPTCONN) { 1457507Sroot while (so->so_q0 != so) 14610399Ssam (void) soabort(so->so_q0); 1477507Sroot while (so->so_q != so) 14810399Ssam (void) soabort(so->so_q); 1497507Sroot } 1504890Swnj if (so->so_pcb == 0) 1514890Swnj goto discard; 1524890Swnj if (so->so_state & SS_ISCONNECTED) { 1534890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1548725Sroot error = sodisconnect(so, (struct mbuf *)0); 15512757Ssam if (error) 15612757Ssam goto drop; 1574890Swnj } 15810267Ssam if (so->so_options & SO_LINGER) { 1595281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 16012757Ssam (so->so_state & SS_NBIO)) 16112757Ssam goto drop; 1625281Sroot while (so->so_state & SS_ISCONNECTED) 1635281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1644890Swnj } 1654890Swnj } 1665580Sroot drop: 1676880Ssam if (so->so_pcb) { 16812757Ssam int error2 = 16912757Ssam (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 17012757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 17112757Ssam if (error == 0) 17212757Ssam error = error2; 1736880Ssam } 1744890Swnj discard: 17510399Ssam if (so->so_state & SS_NOFDREF) 17610399Ssam panic("soclose: NOFDREF"); 1777507Sroot so->so_state |= SS_NOFDREF; 1784950Swnj sofree(so); 1794890Swnj splx(s); 18012757Ssam return (error); 1814829Swnj } 1824829Swnj 18310399Ssam /* 18410399Ssam * Must be called at splnet... 18510399Ssam */ 18610399Ssam soabort(so) 18710399Ssam struct socket *so; 18810399Ssam { 18910399Ssam 19012757Ssam return ( 19112757Ssam (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 19212757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 19310399Ssam } 19410399Ssam 19510267Ssam soaccept(so, nam) 19612757Ssam register struct socket *so; 1978300Sroot struct mbuf *nam; 1984927Swnj { 1994927Swnj int s = splnet(); 2004927Swnj int error; 2014927Swnj 20210399Ssam if ((so->so_state & SS_NOFDREF) == 0) 20310399Ssam panic("soaccept: !NOFDREF"); 20410267Ssam so->so_state &= ~SS_NOFDREF; 2058300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 20612757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2074927Swnj splx(s); 2084927Swnj return (error); 2094927Swnj } 2104927Swnj 21110267Ssam soconnect(so, nam) 21212757Ssam register struct socket *so; 2138300Sroot struct mbuf *nam; 2144786Swnj { 2154890Swnj int s = splnet(); 2164890Swnj int error; 2174786Swnj 2184890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2194890Swnj error = EISCONN; 2204890Swnj goto bad; 2214890Swnj } 2228300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 22312757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2244890Swnj bad: 2254890Swnj splx(s); 2264890Swnj return (error); 2274786Swnj } 2284786Swnj 22912757Ssam soconnect2(so1, so2) 23012757Ssam register struct socket *so1; 23112757Ssam struct socket *so2; 23212757Ssam { 23312757Ssam int s = splnet(); 23412757Ssam int error; 23512757Ssam 23613113Ssam error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 23713113Ssam (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 23812757Ssam splx(s); 23912757Ssam return (error); 24012757Ssam } 24112757Ssam 2428300Sroot sodisconnect(so, nam) 24312757Ssam register struct socket *so; 2448300Sroot struct mbuf *nam; 2454786Swnj { 2464890Swnj int s = splnet(); 2474890Swnj int error; 2484786Swnj 2494890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2504890Swnj error = ENOTCONN; 2514890Swnj goto bad; 2524890Swnj } 2534890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2544890Swnj error = EALREADY; 2554890Swnj goto bad; 2564890Swnj } 2578300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 25812757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2594890Swnj bad: 2604890Swnj splx(s); 2614890Swnj return (error); 2624786Swnj } 2634786Swnj 2644786Swnj /* 2654890Swnj * Send on a socket. 2664890Swnj * If send must go all at once and message is larger than 2674890Swnj * send buffering, then hard error. 2684890Swnj * Lock against other senders. 2694890Swnj * If must go all at once and not enough room now, then 2704890Swnj * inform user that this would block and do nothing. 27116412Skarels * Otherwise, if nonblocking, send as much as possible. 2724786Swnj */ 27312757Ssam sosend(so, nam, uio, flags, rights) 2744786Swnj register struct socket *so; 2758300Sroot struct mbuf *nam; 27612757Ssam register struct uio *uio; 2778319Sroot int flags; 27812757Ssam struct mbuf *rights; 2794786Swnj { 2804890Swnj struct mbuf *top = 0; 28116412Skarels register struct mbuf *m, **mp; 28212757Ssam register int space; 28316412Skarels int len, error = 0, s, dontroute, first = 1; 2844786Swnj 2857827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2864890Swnj return (EMSGSIZE); 28712757Ssam dontroute = 28812757Ssam (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 28912757Ssam (so->so_proto->pr_flags & PR_ATOMIC); 29016412Skarels u.u_ru.ru_msgsnd++; 29116412Skarels #define snderr(errno) { error = errno; splx(s); goto release; } 29216412Skarels 2936419Sroot restart: 2944890Swnj sblock(&so->so_snd); 29516412Skarels do { 29616412Skarels s = splnet(); 29716412Skarels if (so->so_state & SS_CANTSENDMORE) { 29816412Skarels psignal(u.u_procp, SIGPIPE); 29916412Skarels snderr(EPIPE); 30016412Skarels } 30116412Skarels if (so->so_error) { 30216412Skarels error = so->so_error; 30316412Skarels so->so_error = 0; /* ??? */ 30416412Skarels splx(s); 30516412Skarels goto release; 30616412Skarels } 30716412Skarels if ((so->so_state & SS_ISCONNECTED) == 0) { 30816412Skarels if (so->so_proto->pr_flags & PR_CONNREQUIRED) 30916412Skarels snderr(ENOTCONN); 31016412Skarels if (nam == 0) 31116412Skarels snderr(EDESTADDRREQ); 31216412Skarels } 31316412Skarels if (flags & MSG_OOB) 31416412Skarels space = 1024; 31516412Skarels else { 31616412Skarels space = sbspace(&so->so_snd); 31716412Skarels if (space <= 0 || 318*16992Skarels (sosendallatonce(so) && space < uio->uio_resid) || 319*16992Skarels (uio->uio_resid >= CLBYTES && space < CLBYTES && 320*16992Skarels so->so_snd.sb_cc >= CLBYTES && 321*16992Skarels (so->so_state & SS_NBIO) == 0)) { 32216412Skarels if (so->so_state & SS_NBIO) { 32316412Skarels if (first) 32416412Skarels error = EWOULDBLOCK; 32516412Skarels splx(s); 32616412Skarels goto release; 32716412Skarels } 32816412Skarels sbunlock(&so->so_snd); 32916412Skarels sbwait(&so->so_snd); 33016412Skarels splx(s); 33116412Skarels goto restart; 33216412Skarels } 33316412Skarels } 33416412Skarels splx(s); 33516412Skarels mp = ⊤ 33616412Skarels while (uio->uio_resid > 0 && space > 0) { 33716412Skarels register struct iovec *iov = uio->uio_iov; 3384890Swnj 33916412Skarels if (iov->iov_len == 0) { 34016412Skarels uio->uio_iov++; 34116412Skarels uio->uio_iovcnt--; 34216412Skarels if (uio->uio_iovcnt < 0) 34316412Skarels panic("sosend"); 34416412Skarels continue; 34516412Skarels } 34616412Skarels MGET(m, M_WAIT, MT_DATA); 34716412Skarels if (m == NULL) { 34816412Skarels error = ENOBUFS; /* SIGPIPE? */ 34916412Skarels goto release; 35016412Skarels } 35116412Skarels if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 35216412Skarels register struct mbuf *p; 35316412Skarels MCLGET(p, 1); 35416412Skarels if (p == 0) 35516412Skarels goto nopages; 35616412Skarels m->m_off = (int)p - (int)m; 35716412Skarels len = CLBYTES; 35816412Skarels } else { 35916412Skarels nopages: 36016412Skarels len = MIN(MLEN, iov->iov_len); 36116412Skarels } 36216412Skarels error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 36316412Skarels m->m_len = len; 36416412Skarels *mp = m; 36516412Skarels if (error) 36616412Skarels goto release; 36716412Skarels mp = &m->m_next; 36816412Skarels space -= len; 36916412Skarels } 370*16992Skarels if (top) { 371*16992Skarels if (dontroute) 372*16992Skarels so->so_options |= SO_DONTROUTE; 373*16992Skarels s = splnet(); 374*16992Skarels error = (*so->so_proto->pr_usrreq)(so, 375*16992Skarels (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 376*16992Skarels top, (caddr_t)nam, rights); 377*16992Skarels splx(s); 378*16992Skarels if (dontroute) 379*16992Skarels so->so_options &= ~SO_DONTROUTE; 380*16992Skarels } 3816419Sroot top = 0; 38216412Skarels first = 0; 38314781Ssam if (error) 38416412Skarels break; 38516412Skarels } while (uio->uio_resid); 3864890Swnj 3874786Swnj release: 3884890Swnj sbunlock(&so->so_snd); 3896419Sroot if (top) 3906419Sroot m_freem(top); 3914786Swnj return (error); 3924786Swnj } 3934786Swnj 39412757Ssam soreceive(so, aname, uio, flags, rightsp) 3954786Swnj register struct socket *so; 3968300Sroot struct mbuf **aname; 39712757Ssam register struct uio *uio; 3988319Sroot int flags; 39912757Ssam struct mbuf **rightsp; 4004786Swnj { 4014786Swnj register struct mbuf *m, *n; 40212757Ssam register int len, error = 0, s, eor, tomark; 40312757Ssam struct protosw *pr = so->so_proto; 40412757Ssam int moff; 4054786Swnj 40612757Ssam if (rightsp) 40712757Ssam *rightsp = 0; 40812757Ssam if (aname) 40912757Ssam *aname = 0; 41012757Ssam if (flags & MSG_OOB) { 4119635Ssam m = m_get(M_WAIT, MT_DATA); 41212757Ssam if (m == 0) 41310137Ssam return (ENOBUFS); 41412757Ssam error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 41512757Ssam m, (struct mbuf *)0, (struct mbuf *)0); 4168594Sroot if (error) 41710137Ssam goto bad; 4188319Sroot do { 41910137Ssam len = uio->uio_resid; 4208319Sroot if (len > m->m_len) 4218319Sroot len = m->m_len; 4228594Sroot error = 4238793Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 4248319Sroot m = m_free(m); 4258594Sroot } while (uio->uio_resid && error == 0 && m); 42610137Ssam bad: 4278319Sroot if (m) 4288771Sroot m_freem(m); 4298594Sroot return (error); 4308319Sroot } 4318319Sroot 4324890Swnj restart: 4334890Swnj sblock(&so->so_rcv); 4348835Sroot s = splnet(); 4354890Swnj 4364890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4374786Swnj if (so->so_rcv.sb_cc == 0) { 4385168Swnj if (so->so_error) { 4395168Swnj error = so->so_error; 4405168Swnj so->so_error = 0; 4415168Swnj splx(s); 4425168Swnj goto release; 4435168Swnj } 4444890Swnj if (so->so_state & SS_CANTRCVMORE) { 4454890Swnj splx(s); 4464890Swnj goto release; 4474890Swnj } 4485015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4495015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4505015Sroot rcverr(ENOTCONN); 4516214Swnj if (so->so_state & SS_NBIO) 4525168Swnj rcverr(EWOULDBLOCK); 4534890Swnj sbunlock(&so->so_rcv); 4544971Swnj sbwait(&so->so_rcv); 4555012Swnj splx(s); 4564890Swnj goto restart; 4574786Swnj } 4588041Sroot u.u_ru.ru_msgrcv++; 4594829Swnj m = so->so_rcv.sb_mb; 4604786Swnj if (m == 0) 4614786Swnj panic("receive"); 46212757Ssam if (pr->pr_flags & PR_ADDR) { 46312757Ssam if ((flags & MSG_PEEK) == 0) { 4648319Sroot so->so_rcv.sb_cc -= m->m_len; 4658319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4668319Sroot } 4678300Sroot if (aname) { 46812757Ssam if (flags & MSG_PEEK) { 4698319Sroot *aname = m_copy(m, 0, m->m_len); 47010137Ssam if (*aname == NULL) 47110137Ssam panic("receive 2"); 47210137Ssam } else 4738319Sroot *aname = m; 4748300Sroot m = m->m_next; 4758300Sroot (*aname)->m_next = 0; 4768300Sroot } else 47712757Ssam if (flags & MSG_PEEK) 4788319Sroot m = m->m_next; 4798319Sroot else 4808319Sroot m = m_free(m); 4814890Swnj if (m == 0) 48212757Ssam panic("receive 2a"); 48312757Ssam if (rightsp) { 48412757Ssam if (m->m_len) 48512757Ssam *rightsp = m_copy(m, 0, m->m_len); 48612757Ssam else { 48712757Ssam *rightsp = m_get(M_DONTWAIT, MT_SONAME); 48812757Ssam if (*rightsp) 48912757Ssam (*rightsp)->m_len = 0; 49012757Ssam } 49114813Ssam #ifdef notdef 49212757Ssam if (*rightsp == NULL) 49312757Ssam panic("receive 2b"); 49414813Ssam #endif 49512757Ssam } 49612757Ssam if (flags & MSG_PEEK) 49712757Ssam m = m->m_next; 49812757Ssam else { 49912757Ssam so->so_rcv.sb_cc -= m->m_len; 50012757Ssam so->so_rcv.sb_mbcnt -= MSIZE; 50112757Ssam m = m_free(m); 50212757Ssam } 50312757Ssam if (m == 0) 50410137Ssam panic("receive 3"); 50512757Ssam if ((flags & MSG_PEEK) == 0) 5068548Sroot so->so_rcv.sb_mb = m; 5074890Swnj } 5084786Swnj eor = 0; 5098319Sroot moff = 0; 5108319Sroot tomark = so->so_oobmark; 5114786Swnj do { 5127827Sroot if (uio->uio_resid <= 0) 5137747Sroot break; 5147827Sroot len = uio->uio_resid; 5157747Sroot so->so_state &= ~SS_RCVATMARK; 5168319Sroot if (tomark && len > tomark) 5178319Sroot len = tomark; 5188548Sroot if (moff+len > m->m_len - moff) 5198319Sroot len = m->m_len - moff; 5204786Swnj splx(s); 5218594Sroot error = 5228793Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 5234786Swnj s = splnet(); 5244786Swnj if (len == m->m_len) { 5256091Sroot eor = (int)m->m_act; 52612757Ssam if (flags & MSG_PEEK) 5278319Sroot m = m->m_next; 5288319Sroot else { 5298319Sroot sbfree(&so->so_rcv, m); 5308319Sroot MFREE(m, n); 5318319Sroot m = n; 5328548Sroot so->so_rcv.sb_mb = m; 5338319Sroot } 5348319Sroot moff = 0; 5354786Swnj } else { 53612757Ssam if (flags & MSG_PEEK) 5378319Sroot moff += len; 5388319Sroot else { 5398319Sroot m->m_off += len; 5408319Sroot m->m_len -= len; 5418319Sroot so->so_rcv.sb_cc -= len; 5428319Sroot } 5434786Swnj } 54412757Ssam if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 5457747Sroot so->so_oobmark -= len; 5467747Sroot if (so->so_oobmark == 0) { 5477747Sroot so->so_state |= SS_RCVATMARK; 5487747Sroot break; 5497747Sroot } 5507747Sroot } 5518319Sroot if (tomark) { 5528319Sroot tomark -= len; 5538319Sroot if (tomark == 0) 5548319Sroot break; 5558319Sroot } 5568594Sroot } while (m && error == 0 && !eor); 55712757Ssam if (flags & MSG_PEEK) 5588319Sroot goto release; 5594786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5604786Swnj do { 5614786Swnj if (m == 0) 56210137Ssam panic("receive 4"); 5634890Swnj sbfree(&so->so_rcv, m); 5644786Swnj eor = (int)m->m_act; 5654786Swnj so->so_rcv.sb_mb = m->m_next; 5664786Swnj MFREE(m, n); 5674890Swnj m = n; 5684786Swnj } while (eor == 0); 5694890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5708300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 57112757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 5724890Swnj release: 5734916Swnj sbunlock(&so->so_rcv); 57412757Ssam if (error == 0 && rightsp && 57512757Ssam *rightsp && so->so_proto->pr_family == AF_UNIX) 57612757Ssam error = unp_externalize(*rightsp); 5774890Swnj splx(s); 5784916Swnj return (error); 5794786Swnj } 5804786Swnj 58110267Ssam soshutdown(so, how) 58212757Ssam register struct socket *so; 58312757Ssam register int how; 58410267Ssam { 58512757Ssam register struct protosw *pr = so->so_proto; 58610267Ssam 58710267Ssam how++; 58812757Ssam if (how & FREAD) 58912757Ssam sorflush(so); 59010267Ssam if (how & FWRITE) 59112757Ssam return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 59212757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 59310267Ssam return (0); 59410267Ssam } 59510267Ssam 59612757Ssam sorflush(so) 59712757Ssam register struct socket *so; 59812757Ssam { 59912757Ssam register struct sockbuf *sb = &so->so_rcv; 60012757Ssam register struct protosw *pr = so->so_proto; 60112757Ssam register int s; 60212757Ssam struct sockbuf asb; 60312757Ssam 60412757Ssam sblock(sb); 60512757Ssam s = splimp(); 60612757Ssam socantrcvmore(so); 60712757Ssam sbunlock(sb); 60812757Ssam asb = *sb; 60912757Ssam bzero((caddr_t)sb, sizeof (*sb)); 61012757Ssam splx(s); 61112757Ssam if (pr->pr_family == AF_UNIX && (pr->pr_flags & PR_RIGHTS)) 61212757Ssam unp_scan(asb.sb_mb, unp_discard); 61312757Ssam sbrelease(&asb); 61412757Ssam } 61512757Ssam 61610267Ssam sosetopt(so, level, optname, m) 61712757Ssam register struct socket *so; 61810267Ssam int level, optname; 61912757Ssam register struct mbuf *m; 62010267Ssam { 62110267Ssam 62210267Ssam if (level != SOL_SOCKET) 62310267Ssam return (EINVAL); /* XXX */ 62410267Ssam switch (optname) { 62510267Ssam 62610267Ssam case SO_DEBUG: 62710269Ssam case SO_KEEPALIVE: 62810599Ssam case SO_DONTROUTE: 62910599Ssam case SO_USELOOPBACK: 63010599Ssam case SO_REUSEADDR: 63110599Ssam so->so_options |= optname; 63210269Ssam break; 63310269Ssam 63410267Ssam case SO_LINGER: 63510269Ssam if (m == NULL || m->m_len != sizeof (int)) 63610269Ssam return (EINVAL); 63710267Ssam so->so_options |= SO_LINGER; 63810269Ssam so->so_linger = *mtod(m, int *); 63910267Ssam break; 64010267Ssam 64110267Ssam case SO_DONTLINGER: 64210267Ssam so->so_options &= ~SO_LINGER; 64310267Ssam so->so_linger = 0; 64410267Ssam break; 64510267Ssam 64610267Ssam default: 64710267Ssam return (EINVAL); 64810267Ssam } 64910267Ssam return (0); 65010267Ssam } 65110267Ssam 65210267Ssam sogetopt(so, level, optname, m) 65312757Ssam register struct socket *so; 65410267Ssam int level, optname; 65512757Ssam register struct mbuf *m; 65610267Ssam { 65710267Ssam 65810267Ssam if (level != SOL_SOCKET) 65910267Ssam return (EINVAL); /* XXX */ 66010267Ssam switch (optname) { 66110267Ssam 66210267Ssam case SO_USELOOPBACK: 66310267Ssam case SO_DONTROUTE: 66410267Ssam case SO_DEBUG: 66510267Ssam case SO_KEEPALIVE: 66610267Ssam case SO_LINGER: 66710599Ssam case SO_REUSEADDR: 66810267Ssam if ((so->so_options & optname) == 0) 66910267Ssam return (ENOPROTOOPT); 67010269Ssam if (optname == SO_LINGER && m != NULL) { 67110267Ssam *mtod(m, int *) = so->so_linger; 67210267Ssam m->m_len = sizeof (so->so_linger); 67310267Ssam } 67410267Ssam break; 67510267Ssam 67610267Ssam default: 67710267Ssam return (EINVAL); 67810267Ssam } 67910267Ssam return (0); 68010267Ssam } 68110267Ssam 6825423Swnj sohasoutofband(so) 68312757Ssam register struct socket *so; 6845423Swnj { 6855423Swnj 6865423Swnj if (so->so_pgrp == 0) 6875423Swnj return; 6885423Swnj if (so->so_pgrp > 0) 6895423Swnj gsignal(so->so_pgrp, SIGURG); 6905429Swnj else { 6915429Swnj struct proc *p = pfind(-so->so_pgrp); 6925429Swnj 6935429Swnj if (p) 6945429Swnj psignal(p, SIGURG); 6955429Swnj } 6965423Swnj } 697