1*12757Ssam /* uipc_socket.c 4.75 83/05/27 */ 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" 12*12757Ssam #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" 20*12757Ssam #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. 29*12757Ssam * 30*12757Ssam * TODO: 31*12757Ssam * sostat 32*12757Ssam * test socketpair 33*12757Ssam * PR_RIGHTS 34*12757Ssam * clean up select, async 35*12757Ssam * out-of-band is a kludge 364786Swnj */ 378594Sroot /*ARGSUSED*/ 3810267Ssam socreate(dom, aso, type, proto) 394786Swnj struct socket **aso; 40*12757Ssam register int type; 41*12757Ssam int proto; 424786Swnj { 434786Swnj register struct protosw *prp; 444786Swnj register struct socket *so; 45*12757Ssam register struct mbuf *m; 46*12757Ssam 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 *); 60*12757Ssam 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; 66*12757Ssam error = 67*12757Ssam (*prp->pr_usrreq)(so, PRU_ATTACH, 68*12757Ssam (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 = 86*12757Ssam (*so->so_proto->pr_usrreq)(so, PRU_BIND, 87*12757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 888300Sroot splx(s); 898300Sroot return (error); 908300Sroot } 918300Sroot 928300Sroot solisten(so, backlog) 93*12757Ssam register struct socket *so; 948300Sroot int backlog; 958300Sroot { 96*12757Ssam int s = splnet(), error; 978300Sroot 98*12757Ssam error = 99*12757Ssam (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 100*12757Ssam (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) 118*12757Ssam 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); 129*12757Ssam 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 */ 138*12757Ssam 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); 155*12757Ssam if (error) 156*12757Ssam goto drop; 1574890Swnj } 15810267Ssam if (so->so_options & SO_LINGER) { 1595281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 160*12757Ssam (so->so_state & SS_NBIO)) 161*12757Ssam 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) { 168*12757Ssam int error2 = 169*12757Ssam (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 170*12757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 171*12757Ssam if (error == 0) 172*12757Ssam 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); 180*12757Ssam return (error); 1814829Swnj } 1824829Swnj 18310399Ssam /* 18410399Ssam * Must be called at splnet... 18510399Ssam */ 18610399Ssam soabort(so) 18710399Ssam struct socket *so; 18810399Ssam { 18910399Ssam 190*12757Ssam return ( 191*12757Ssam (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 192*12757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 19310399Ssam } 19410399Ssam 19510267Ssam soaccept(so, nam) 196*12757Ssam 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, 206*12757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2074927Swnj splx(s); 2084927Swnj return (error); 2094927Swnj } 2104927Swnj 21110267Ssam soconnect(so, nam) 212*12757Ssam 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, 223*12757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2244890Swnj bad: 2254890Swnj splx(s); 2264890Swnj return (error); 2274786Swnj } 2284786Swnj 229*12757Ssam #ifdef notdef 230*12757Ssam soconnect2(so1, so2) 231*12757Ssam register struct socket *so1; 232*12757Ssam struct socket *so2; 233*12757Ssam { 234*12757Ssam int s = splnet(); 235*12757Ssam int error; 236*12757Ssam 237*12757Ssam error = 238*12757Ssam (*so1->so_proto->pr_usrreq)(so, PRU_CONNECT2, 239*12757Ssam (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 240*12757Ssam splx(s); 241*12757Ssam return (error); 242*12757Ssam } 243*12757Ssam #endif 244*12757Ssam 2458300Sroot sodisconnect(so, nam) 246*12757Ssam register struct socket *so; 2478300Sroot struct mbuf *nam; 2484786Swnj { 2494890Swnj int s = splnet(); 2504890Swnj int error; 2514786Swnj 2524890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2534890Swnj error = ENOTCONN; 2544890Swnj goto bad; 2554890Swnj } 2564890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2574890Swnj error = EALREADY; 2584890Swnj goto bad; 2594890Swnj } 2608300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 261*12757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2624890Swnj bad: 2634890Swnj splx(s); 2644890Swnj return (error); 2654786Swnj } 2664786Swnj 2674786Swnj /* 2684890Swnj * Send on a socket. 2694890Swnj * If send must go all at once and message is larger than 2704890Swnj * send buffering, then hard error. 2714890Swnj * Lock against other senders. 2724890Swnj * If must go all at once and not enough room now, then 2734890Swnj * inform user that this would block and do nothing. 2744786Swnj */ 275*12757Ssam sosend(so, nam, uio, flags, rights) 2764786Swnj register struct socket *so; 2778300Sroot struct mbuf *nam; 278*12757Ssam register struct uio *uio; 2798319Sroot int flags; 280*12757Ssam struct mbuf *rights; 2814786Swnj { 2824890Swnj struct mbuf *top = 0; 2834890Swnj register struct mbuf *m, **mp = ⊤ 284*12757Ssam register int space; 285*12757Ssam int len, error = 0, s, dontroute; 2864786Swnj 2877827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2884890Swnj return (EMSGSIZE); 289*12757Ssam dontroute = 290*12757Ssam (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 291*12757Ssam (so->so_proto->pr_flags & PR_ATOMIC); 2926419Sroot restart: 2934890Swnj sblock(&so->so_snd); 2944890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2954890Swnj 2968041Sroot u.u_ru.ru_msgsnd++; 2976419Sroot again: 2984890Swnj s = splnet(); 2996419Sroot if (so->so_state & SS_CANTSENDMORE) { 3006419Sroot psignal(u.u_procp, SIGPIPE); 3016419Sroot snderr(EPIPE); 3026419Sroot } 3035168Swnj if (so->so_error) { 3045168Swnj error = so->so_error; 3056419Sroot so->so_error = 0; /* ??? */ 3065168Swnj splx(s); 3075168Swnj goto release; 3085168Swnj } 3094890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 3104890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 3114890Swnj snderr(ENOTCONN); 3128300Sroot if (nam == 0) 3134890Swnj snderr(EDESTADDRREQ); 3144890Swnj } 3154890Swnj if (top) { 31610267Ssam if (dontroute) 31710267Ssam so->so_options |= SO_DONTROUTE; 3188319Sroot error = (*so->so_proto->pr_usrreq)(so, 319*12757Ssam (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 320*12757Ssam top, (caddr_t)nam, rights); 32110267Ssam if (dontroute) 32210267Ssam so->so_options &= ~SO_DONTROUTE; 3236419Sroot top = 0; 3244890Swnj if (error) { 3254890Swnj splx(s); 3264786Swnj goto release; 3274786Swnj } 3284890Swnj mp = ⊤ 3294786Swnj } 3307827Sroot if (uio->uio_resid == 0) { 3314979Swnj splx(s); 3324979Swnj goto release; 3334979Swnj } 334*12757Ssam if (flags & MSG_OOB) 3358319Sroot space = 1024; 3368319Sroot else { 3378319Sroot space = sbspace(&so->so_snd); 3388319Sroot if (space <= 0 || 3398319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3408319Sroot if (so->so_state & SS_NBIO) 3418319Sroot snderr(EWOULDBLOCK); 3428319Sroot sbunlock(&so->so_snd); 3438319Sroot sbwait(&so->so_snd); 3448319Sroot splx(s); 3458319Sroot goto restart; 3468319Sroot } 3474786Swnj } 3484890Swnj splx(s); 3497827Sroot while (uio->uio_resid > 0 && space > 0) { 3507827Sroot register struct iovec *iov = uio->uio_iov; 3517827Sroot 3527827Sroot if (iov->iov_len == 0) { 3537827Sroot uio->uio_iov++; 3547827Sroot uio->uio_iovcnt--; 3557827Sroot if (uio->uio_iovcnt < 0) 3567827Sroot panic("sosend"); 3577827Sroot continue; 3587827Sroot } 3599635Ssam MGET(m, M_WAIT, MT_DATA); 3604890Swnj if (m == NULL) { 3616419Sroot error = ENOBUFS; /* SIGPIPE? */ 3624890Swnj goto release; 3634786Swnj } 3647827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3654890Swnj register struct mbuf *p; 3665095Swnj MCLGET(p, 1); 3674890Swnj if (p == 0) 3684890Swnj goto nopages; 3694890Swnj m->m_off = (int)p - (int)m; 3705095Swnj len = CLBYTES; 3714890Swnj } else { 3724786Swnj nopages: 3737827Sroot len = MIN(MLEN, iov->iov_len); 3744786Swnj } 3758771Sroot (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3764890Swnj m->m_len = len; 3774890Swnj *mp = m; 3784890Swnj mp = &m->m_next; 379*12757Ssam if (flags & MSG_OOB) 3808319Sroot space -= len; 3818319Sroot else 3828319Sroot space = sbspace(&so->so_snd); 3834786Swnj } 3844890Swnj goto again; 3854890Swnj 3864786Swnj release: 3874890Swnj sbunlock(&so->so_snd); 3886419Sroot if (top) 3896419Sroot m_freem(top); 3904786Swnj return (error); 3914786Swnj } 3924786Swnj 393*12757Ssam soreceive(so, aname, uio, flags, rightsp) 3944786Swnj register struct socket *so; 3958300Sroot struct mbuf **aname; 396*12757Ssam register struct uio *uio; 3978319Sroot int flags; 398*12757Ssam struct mbuf **rightsp; 3994786Swnj { 4004786Swnj register struct mbuf *m, *n; 401*12757Ssam register int len, error = 0, s, eor, tomark; 402*12757Ssam struct protosw *pr = so->so_proto; 403*12757Ssam int moff; 4044786Swnj 405*12757Ssam if (rightsp) 406*12757Ssam *rightsp = 0; 407*12757Ssam if (aname) 408*12757Ssam *aname = 0; 409*12757Ssam if (flags & MSG_OOB) { 4109635Ssam m = m_get(M_WAIT, MT_DATA); 411*12757Ssam if (m == 0) 41210137Ssam return (ENOBUFS); 413*12757Ssam error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 414*12757Ssam m, (struct mbuf *)0, (struct mbuf *)0); 4158594Sroot if (error) 41610137Ssam goto bad; 4178319Sroot do { 41810137Ssam len = uio->uio_resid; 4198319Sroot if (len > m->m_len) 4208319Sroot len = m->m_len; 4218594Sroot error = 4228793Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 4238319Sroot m = m_free(m); 4248594Sroot } while (uio->uio_resid && error == 0 && m); 42510137Ssam bad: 4268319Sroot if (m) 4278771Sroot m_freem(m); 4288594Sroot return (error); 4298319Sroot } 4308319Sroot 4314890Swnj restart: 4324890Swnj sblock(&so->so_rcv); 4338835Sroot s = splnet(); 4344890Swnj 4354890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4364786Swnj if (so->so_rcv.sb_cc == 0) { 4375168Swnj if (so->so_error) { 4385168Swnj error = so->so_error; 4395168Swnj so->so_error = 0; 4405168Swnj splx(s); 4415168Swnj goto release; 4425168Swnj } 4434890Swnj if (so->so_state & SS_CANTRCVMORE) { 4444890Swnj splx(s); 4454890Swnj goto release; 4464890Swnj } 4475015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4485015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4495015Sroot rcverr(ENOTCONN); 4506214Swnj if (so->so_state & SS_NBIO) 4515168Swnj rcverr(EWOULDBLOCK); 4524890Swnj sbunlock(&so->so_rcv); 4534971Swnj sbwait(&so->so_rcv); 4545012Swnj splx(s); 4554890Swnj goto restart; 4564786Swnj } 4578041Sroot u.u_ru.ru_msgrcv++; 4584829Swnj m = so->so_rcv.sb_mb; 4594786Swnj if (m == 0) 4604786Swnj panic("receive"); 461*12757Ssam if (pr->pr_flags & PR_ADDR) { 462*12757Ssam if ((flags & MSG_PEEK) == 0) { 4638319Sroot so->so_rcv.sb_cc -= m->m_len; 4648319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4658319Sroot } 4668300Sroot if (aname) { 467*12757Ssam if (flags & MSG_PEEK) { 4688319Sroot *aname = m_copy(m, 0, m->m_len); 46910137Ssam if (*aname == NULL) 47010137Ssam panic("receive 2"); 47110137Ssam } else 4728319Sroot *aname = m; 4738300Sroot m = m->m_next; 4748300Sroot (*aname)->m_next = 0; 4758300Sroot } else 476*12757Ssam if (flags & MSG_PEEK) 4778319Sroot m = m->m_next; 4788319Sroot else 4798319Sroot m = m_free(m); 4804890Swnj if (m == 0) 481*12757Ssam panic("receive 2a"); 482*12757Ssam if (rightsp) { 483*12757Ssam if (m->m_len) 484*12757Ssam *rightsp = m_copy(m, 0, m->m_len); 485*12757Ssam else { 486*12757Ssam *rightsp = m_get(M_DONTWAIT, MT_SONAME); 487*12757Ssam if (*rightsp) 488*12757Ssam (*rightsp)->m_len = 0; 489*12757Ssam } 490*12757Ssam if (*rightsp == NULL) 491*12757Ssam panic("receive 2b"); 492*12757Ssam } 493*12757Ssam if (flags & MSG_PEEK) 494*12757Ssam m = m->m_next; 495*12757Ssam else { 496*12757Ssam so->so_rcv.sb_cc -= m->m_len; 497*12757Ssam so->so_rcv.sb_mbcnt -= MSIZE; 498*12757Ssam m = m_free(m); 499*12757Ssam } 500*12757Ssam if (m == 0) 50110137Ssam panic("receive 3"); 502*12757Ssam if ((flags & MSG_PEEK) == 0) 5038548Sroot so->so_rcv.sb_mb = m; 5044890Swnj } 5054786Swnj eor = 0; 5068319Sroot moff = 0; 5078319Sroot tomark = so->so_oobmark; 5084786Swnj do { 5097827Sroot if (uio->uio_resid <= 0) 5107747Sroot break; 5117827Sroot len = uio->uio_resid; 5127747Sroot so->so_state &= ~SS_RCVATMARK; 5138319Sroot if (tomark && len > tomark) 5148319Sroot len = tomark; 5158548Sroot if (moff+len > m->m_len - moff) 5168319Sroot len = m->m_len - moff; 5174786Swnj splx(s); 5188594Sroot error = 5198793Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 5204786Swnj s = splnet(); 5214786Swnj if (len == m->m_len) { 5226091Sroot eor = (int)m->m_act; 523*12757Ssam if (flags & MSG_PEEK) 5248319Sroot m = m->m_next; 5258319Sroot else { 5268319Sroot sbfree(&so->so_rcv, m); 5278319Sroot MFREE(m, n); 5288319Sroot m = n; 5298548Sroot so->so_rcv.sb_mb = m; 5308319Sroot } 5318319Sroot moff = 0; 5324786Swnj } else { 533*12757Ssam if (flags & MSG_PEEK) 5348319Sroot moff += len; 5358319Sroot else { 5368319Sroot m->m_off += len; 5378319Sroot m->m_len -= len; 5388319Sroot so->so_rcv.sb_cc -= len; 5398319Sroot } 5404786Swnj } 541*12757Ssam if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 5427747Sroot so->so_oobmark -= len; 5437747Sroot if (so->so_oobmark == 0) { 5447747Sroot so->so_state |= SS_RCVATMARK; 5457747Sroot break; 5467747Sroot } 5477747Sroot } 5488319Sroot if (tomark) { 5498319Sroot tomark -= len; 5508319Sroot if (tomark == 0) 5518319Sroot break; 5528319Sroot } 5538594Sroot } while (m && error == 0 && !eor); 554*12757Ssam if (flags & MSG_PEEK) 5558319Sroot goto release; 5564786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5574786Swnj do { 5584786Swnj if (m == 0) 55910137Ssam panic("receive 4"); 5604890Swnj sbfree(&so->so_rcv, m); 5614786Swnj eor = (int)m->m_act; 5624786Swnj so->so_rcv.sb_mb = m->m_next; 5634786Swnj MFREE(m, n); 5644890Swnj m = n; 5654786Swnj } while (eor == 0); 5664890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5678300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 568*12757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 5694890Swnj release: 5704916Swnj sbunlock(&so->so_rcv); 571*12757Ssam if (error == 0 && rightsp && 572*12757Ssam *rightsp && so->so_proto->pr_family == AF_UNIX) 573*12757Ssam error = unp_externalize(*rightsp); 5744890Swnj splx(s); 5754916Swnj return (error); 5764786Swnj } 5774786Swnj 57810267Ssam soshutdown(so, how) 579*12757Ssam register struct socket *so; 580*12757Ssam register int how; 58110267Ssam { 582*12757Ssam register struct protosw *pr = so->so_proto; 58310267Ssam 58410267Ssam how++; 585*12757Ssam if (how & FREAD) 586*12757Ssam sorflush(so); 58710267Ssam if (how & FWRITE) 588*12757Ssam return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 589*12757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 59010267Ssam return (0); 59110267Ssam } 59210267Ssam 593*12757Ssam sorflush(so) 594*12757Ssam register struct socket *so; 595*12757Ssam { 596*12757Ssam register struct sockbuf *sb = &so->so_rcv; 597*12757Ssam register struct protosw *pr = so->so_proto; 598*12757Ssam register int s; 599*12757Ssam struct sockbuf asb; 600*12757Ssam 601*12757Ssam sblock(sb); 602*12757Ssam s = splimp(); 603*12757Ssam socantrcvmore(so); 604*12757Ssam sbunlock(sb); 605*12757Ssam asb = *sb; 606*12757Ssam bzero((caddr_t)sb, sizeof (*sb)); 607*12757Ssam splx(s); 608*12757Ssam if (pr->pr_family == AF_UNIX && (pr->pr_flags & PR_RIGHTS)) 609*12757Ssam unp_scan(asb.sb_mb, unp_discard); 610*12757Ssam sbrelease(&asb); 611*12757Ssam } 612*12757Ssam 61310267Ssam sosetopt(so, level, optname, m) 614*12757Ssam register struct socket *so; 61510267Ssam int level, optname; 616*12757Ssam register struct mbuf *m; 61710267Ssam { 61810267Ssam 61910267Ssam if (level != SOL_SOCKET) 62010267Ssam return (EINVAL); /* XXX */ 62110267Ssam switch (optname) { 62210267Ssam 62310267Ssam case SO_DEBUG: 62410269Ssam case SO_KEEPALIVE: 62510599Ssam case SO_DONTROUTE: 62610599Ssam case SO_USELOOPBACK: 62710599Ssam case SO_REUSEADDR: 62810599Ssam so->so_options |= optname; 62910269Ssam break; 63010269Ssam 63110267Ssam case SO_LINGER: 63210269Ssam if (m == NULL || m->m_len != sizeof (int)) 63310269Ssam return (EINVAL); 63410267Ssam so->so_options |= SO_LINGER; 63510269Ssam so->so_linger = *mtod(m, int *); 63610267Ssam break; 63710267Ssam 63810267Ssam case SO_DONTLINGER: 63910267Ssam so->so_options &= ~SO_LINGER; 64010267Ssam so->so_linger = 0; 64110267Ssam break; 64210267Ssam 64310267Ssam default: 64410267Ssam return (EINVAL); 64510267Ssam } 64610267Ssam return (0); 64710267Ssam } 64810267Ssam 64910267Ssam sogetopt(so, level, optname, m) 650*12757Ssam register struct socket *so; 65110267Ssam int level, optname; 652*12757Ssam register struct mbuf *m; 65310267Ssam { 65410267Ssam 65510267Ssam if (level != SOL_SOCKET) 65610267Ssam return (EINVAL); /* XXX */ 65710267Ssam switch (optname) { 65810267Ssam 65910267Ssam case SO_USELOOPBACK: 66010267Ssam case SO_DONTROUTE: 66110267Ssam case SO_DEBUG: 66210267Ssam case SO_KEEPALIVE: 66310267Ssam case SO_LINGER: 66410599Ssam case SO_REUSEADDR: 66510267Ssam if ((so->so_options & optname) == 0) 66610267Ssam return (ENOPROTOOPT); 66710269Ssam if (optname == SO_LINGER && m != NULL) { 66810267Ssam *mtod(m, int *) = so->so_linger; 66910267Ssam m->m_len = sizeof (so->so_linger); 67010267Ssam } 67110267Ssam break; 67210267Ssam 67310267Ssam default: 67410267Ssam return (EINVAL); 67510267Ssam } 67610267Ssam return (0); 67710267Ssam } 67810267Ssam 6795423Swnj sohasoutofband(so) 680*12757Ssam register struct socket *so; 6815423Swnj { 6825423Swnj 6835423Swnj if (so->so_pgrp == 0) 6845423Swnj return; 6855423Swnj if (so->so_pgrp > 0) 6865423Swnj gsignal(so->so_pgrp, SIGURG); 6875429Swnj else { 6885429Swnj struct proc *p = pfind(-so->so_pgrp); 6895429Swnj 6905429Swnj if (p) 6915429Swnj psignal(p, SIGURG); 6925429Swnj } 6935423Swnj } 694