1*8713Sroot /* uipc_socket.c 4.57 82/10/20 */ 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" 124829Swnj #include "../h/protosw.h" 134829Swnj #include "../h/socket.h" 144829Swnj #include "../h/socketvar.h" 154916Swnj #include "../h/stat.h" 165281Sroot #include "../h/ioctl.h" 178391Swnj #include "../h/uio.h" 186355Ssam #include "../net/route.h" 194786Swnj 204786Swnj /* 218300Sroot * Socket operation routines. 228300Sroot * These routines are called by the routines in 238300Sroot * sys_socket.c or from a system process, and 248300Sroot * implement the semantics of socket operations by 258300Sroot * switching out to the protocol specific routines. 264786Swnj */ 274786Swnj 288594Sroot /*ARGSUSED*/ 298300Sroot socreate(dom, aso, type, proto, opt) 304786Swnj struct socket **aso; 318300Sroot int type, proto; 328300Sroot struct socketopt *opt; 334786Swnj { 344786Swnj register struct protosw *prp; 354786Swnj register struct socket *so; 364786Swnj struct mbuf *m; 378300Sroot int pf, error; 384786Swnj 398300Sroot pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ 404890Swnj if (proto) 414890Swnj prp = pffindproto(pf, proto); 424890Swnj else 434890Swnj prp = pffindtype(pf, type); 444890Swnj if (prp == 0) 454890Swnj return (EPROTONOSUPPORT); 468300Sroot if (prp->pr_type != type) 478300Sroot return (EPROTOTYPE); 484890Swnj m = m_getclr(M_WAIT); 494786Swnj if (m == 0) 504786Swnj return (ENOBUFS); 514786Swnj so = mtod(m, struct socket *); 528300Sroot so->so_options = 0; 536214Swnj so->so_state = 0; 546214Swnj if (u.u_uid == 0) 556214Swnj so->so_state = SS_PRIV; 564786Swnj so->so_proto = prp; 578300Sroot error = (*prp->pr_usrreq)(so, PRU_ATTACH, 588300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 594979Swnj if (error) { 607507Sroot so->so_state |= SS_NOFDREF; 617180Swnj sofree(so); 624890Swnj return (error); 634786Swnj } 644786Swnj *aso = so; 654786Swnj return (0); 664786Swnj } 674786Swnj 688300Sroot sobind(so, nam, opt) 698300Sroot struct socket *so; 708300Sroot struct mbuf *nam; 718300Sroot struct socketopt *opt; 728300Sroot { 738300Sroot int s = splnet(); 748300Sroot int error; 758300Sroot 768300Sroot error = 778300Sroot (*so->so_proto->pr_usrreq)(so, PRU_BIND, 788300Sroot (struct mbuf *)0, nam, opt); 798300Sroot splx(s); 808300Sroot return (error); 818300Sroot } 828300Sroot 838300Sroot solisten(so, backlog) 848300Sroot struct socket *so; 858300Sroot int backlog; 868300Sroot { 878300Sroot int s = splnet(); 888300Sroot int error; 898300Sroot 908300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 918300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 928300Sroot if (error) { 938300Sroot splx(s); 948300Sroot return (error); 958300Sroot } 968300Sroot if (so->so_q == 0) { 978300Sroot so->so_q = so; 988300Sroot so->so_q0 = so; 998300Sroot so->so_options |= SO_ACCEPTCONN; 1008300Sroot } 1018300Sroot if (backlog < 0) 1028300Sroot backlog = 0; 1038300Sroot so->so_qlimit = backlog < 5 ? backlog : 5; 1048300Sroot so->so_options |= SO_NEWFDONCONN; 1058300Sroot return (0); 1068300Sroot } 1078300Sroot 1084916Swnj sofree(so) 1094916Swnj struct socket *so; 1104916Swnj { 1114916Swnj 1127507Sroot if (so->so_head) { 1137507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1147507Sroot panic("sofree dq"); 1157507Sroot so->so_head = 0; 1167507Sroot } 1177507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1184950Swnj return; 1194950Swnj sbrelease(&so->so_snd); 1204950Swnj sbrelease(&so->so_rcv); 1214971Swnj (void) m_free(dtom(so)); 1224916Swnj } 1234916Swnj 1244786Swnj /* 1254890Swnj * Close a socket on last file table reference removal. 1264890Swnj * Initiate disconnect if connected. 1274890Swnj * Free socket when disconnect complete. 1284829Swnj */ 1295580Sroot soclose(so, exiting) 1304829Swnj register struct socket *so; 1315580Sroot int exiting; 1324829Swnj { 1334890Swnj int s = splnet(); /* conservative */ 134*8713Sroot int error; 1354829Swnj 1367507Sroot if (so->so_options & SO_ACCEPTCONN) { 1377507Sroot while (so->so_q0 != so) 138*8713Sroot (void) soclose(so->so_q0, 1); 1397507Sroot while (so->so_q != so) 140*8713Sroot (void) soclose(so->so_q, 1); 1417507Sroot } 1424890Swnj if (so->so_pcb == 0) 1434890Swnj goto discard; 1446259Sroot if (exiting) 1456259Sroot so->so_options |= SO_KEEPALIVE; 1464890Swnj if (so->so_state & SS_ISCONNECTED) { 1474890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 148*8713Sroot error = sodisconnect(so, (struct sockaddr *)0); 149*8713Sroot if (error) { 1505580Sroot if (exiting) 1515580Sroot goto drop; 1524890Swnj splx(s); 153*8713Sroot return (error); 1544890Swnj } 1554890Swnj } 1565388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1575281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1586214Swnj (so->so_state & SS_NBIO) && 159*8713Sroot exiting == 0) 160*8713Sroot return (EINPROGRESS); 1615580Sroot /* should use tsleep here, for at most linger */ 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*8713Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1698300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 170*8713Sroot if (exiting == 0 && error) { 1716880Ssam splx(s); 172*8713Sroot return (error); 1736880Ssam } 1746880Ssam } 1754890Swnj discard: 1767507Sroot so->so_state |= SS_NOFDREF; 1774950Swnj sofree(so); 1784890Swnj splx(s); 179*8713Sroot return (0); 1804829Swnj } 1814829Swnj 1824916Swnj /*ARGSUSED*/ 1834890Swnj sostat(so, sb) 1844829Swnj struct socket *so; 1854890Swnj struct stat *sb; 1864829Swnj { 1874829Swnj 1885303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1895303Sroot return (0); /* XXX */ 1904829Swnj } 1914829Swnj 1928300Sroot soaccept(so, nam, opt) 1934927Swnj struct socket *so; 1948300Sroot struct mbuf *nam; 1958300Sroot struct socketopt *opt; 1964927Swnj { 1974927Swnj int s = splnet(); 1984927Swnj int error; 1994927Swnj 2008300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 2018300Sroot (struct mbuf *)0, nam, opt); 2024927Swnj splx(s); 2034927Swnj return (error); 2044927Swnj } 2054927Swnj 2068300Sroot soconnect(so, nam, opt) 2074786Swnj struct socket *so; 2088300Sroot struct mbuf *nam; 2098300Sroot struct socketopt *opt; 2104786Swnj { 2114890Swnj int s = splnet(); 2124890Swnj int error; 2134786Swnj 2144890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2154890Swnj error = EISCONN; 2164890Swnj goto bad; 2174890Swnj } 2188300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 2198300Sroot (struct mbuf *)0, nam, opt); 2204890Swnj bad: 2214890Swnj splx(s); 2224890Swnj return (error); 2234786Swnj } 2244786Swnj 2258300Sroot sodisconnect(so, nam) 2264786Swnj struct socket *so; 2278300Sroot struct mbuf *nam; 2284786Swnj { 2294890Swnj int s = splnet(); 2304890Swnj int error; 2314786Swnj 2324890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2334890Swnj error = ENOTCONN; 2344890Swnj goto bad; 2354890Swnj } 2364890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2374890Swnj error = EALREADY; 2384890Swnj goto bad; 2394890Swnj } 2408300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 2418300Sroot (struct mbuf *)0, nam, (struct socketopt *)0); 2424890Swnj bad: 2434890Swnj splx(s); 2444890Swnj return (error); 2454786Swnj } 2464786Swnj 2474786Swnj /* 2484890Swnj * Send on a socket. 2494890Swnj * If send must go all at once and message is larger than 2504890Swnj * send buffering, then hard error. 2514890Swnj * Lock against other senders. 2524890Swnj * If must go all at once and not enough room now, then 2534890Swnj * inform user that this would block and do nothing. 2544786Swnj */ 2558319Sroot sosend(so, nam, uio, flags) 2564786Swnj register struct socket *so; 2578300Sroot struct mbuf *nam; 2587827Sroot struct uio *uio; 2598319Sroot int flags; 2604786Swnj { 2614890Swnj struct mbuf *top = 0; 2624890Swnj register struct mbuf *m, **mp = ⊤ 263*8713Sroot register int len; 2644916Swnj int error = 0, space, s; 2654786Swnj 2667827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2674890Swnj return (EMSGSIZE); 2686419Sroot restart: 2694890Swnj sblock(&so->so_snd); 2704890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2714890Swnj 2728041Sroot u.u_ru.ru_msgsnd++; 2736419Sroot again: 2744890Swnj s = splnet(); 2756419Sroot if (so->so_state & SS_CANTSENDMORE) { 2766419Sroot psignal(u.u_procp, SIGPIPE); 2776419Sroot snderr(EPIPE); 2786419Sroot } 2795168Swnj if (so->so_error) { 2805168Swnj error = so->so_error; 2816419Sroot so->so_error = 0; /* ??? */ 2825168Swnj splx(s); 2835168Swnj goto release; 2845168Swnj } 2854890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2864890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2874890Swnj snderr(ENOTCONN); 2888300Sroot if (nam == 0) 2894890Swnj snderr(EDESTADDRREQ); 2904890Swnj } 2914890Swnj if (top) { 2928319Sroot error = (*so->so_proto->pr_usrreq)(so, 2938319Sroot (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 2948300Sroot top, (caddr_t)nam, (struct socketopt *)0); 2956419Sroot top = 0; 2964890Swnj if (error) { 2974890Swnj splx(s); 2984786Swnj goto release; 2994786Swnj } 3004890Swnj mp = ⊤ 3014786Swnj } 3027827Sroot if (uio->uio_resid == 0) { 3034979Swnj splx(s); 3044979Swnj goto release; 3054979Swnj } 3068319Sroot if (flags & SOF_OOB) 3078319Sroot space = 1024; 3088319Sroot else { 3098319Sroot space = sbspace(&so->so_snd); 3108319Sroot if (space <= 0 || 3118319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3128319Sroot if (so->so_state & SS_NBIO) 3138319Sroot snderr(EWOULDBLOCK); 3148319Sroot sbunlock(&so->so_snd); 3158319Sroot sbwait(&so->so_snd); 3168319Sroot splx(s); 3178319Sroot goto restart; 3188319Sroot } 3194786Swnj } 3204890Swnj splx(s); 3217827Sroot while (uio->uio_resid > 0 && space > 0) { 3227827Sroot register struct iovec *iov = uio->uio_iov; 3237827Sroot 3247827Sroot if (iov->iov_len == 0) { 3257827Sroot uio->uio_iov++; 3267827Sroot uio->uio_iovcnt--; 3277827Sroot if (uio->uio_iovcnt < 0) 3287827Sroot panic("sosend"); 3297827Sroot continue; 3307827Sroot } 3314890Swnj MGET(m, 1); 3324890Swnj if (m == NULL) { 3336419Sroot error = ENOBUFS; /* SIGPIPE? */ 3344890Swnj goto release; 3354786Swnj } 3367827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3374890Swnj register struct mbuf *p; 3385095Swnj MCLGET(p, 1); 3394890Swnj if (p == 0) 3404890Swnj goto nopages; 3414890Swnj m->m_off = (int)p - (int)m; 3425095Swnj len = CLBYTES; 3434890Swnj } else { 3444786Swnj nopages: 3457827Sroot len = MIN(MLEN, iov->iov_len); 3464786Swnj } 3477827Sroot uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3484890Swnj m->m_len = len; 3494890Swnj *mp = m; 3504890Swnj mp = &m->m_next; 3518319Sroot if (flags & SOF_OOB) 3528319Sroot space -= len; 3538319Sroot else 3548319Sroot space = sbspace(&so->so_snd); 3554786Swnj } 3564890Swnj goto again; 3574890Swnj 3584786Swnj release: 3594890Swnj sbunlock(&so->so_snd); 3606419Sroot if (top) 3616419Sroot m_freem(top); 3624786Swnj return (error); 3634786Swnj } 3644786Swnj 3658319Sroot soreceive(so, aname, uio, flags) 3664786Swnj register struct socket *so; 3678300Sroot struct mbuf **aname; 3687747Sroot struct uio *uio; 3698319Sroot int flags; 3704786Swnj { 3714786Swnj register struct mbuf *m, *n; 372*8713Sroot int len; 3738319Sroot int eor, s, error = 0, moff, tomark; 3744786Swnj 3758319Sroot if (flags & SOF_OOB) { 3768594Sroot m = m_get(M_WAIT); 3778594Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 3788319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 3798594Sroot if (error) 380*8713Sroot return (error); 3818319Sroot len = uio->uio_resid; 3828319Sroot do { 3838319Sroot if (len > m->m_len) 3848319Sroot len = m->m_len; 3858594Sroot error = 3868594Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 3878319Sroot m = m_free(m); 3888594Sroot } while (uio->uio_resid && error == 0 && m); 3898319Sroot if (m) 3908319Sroot (void) m_freem(m); 3918594Sroot return (error); 3928319Sroot } 3938319Sroot 3944890Swnj restart: 3954890Swnj sblock(&so->so_rcv); 3968552Sroot SBCHECK(&so->so_rcv, "soreceive restart"); 3974890Swnj s = splnet(); 3984890Swnj 3994890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4004786Swnj if (so->so_rcv.sb_cc == 0) { 4015168Swnj if (so->so_error) { 4025168Swnj error = so->so_error; 4035168Swnj so->so_error = 0; 4045168Swnj splx(s); 4055168Swnj goto release; 4065168Swnj } 4074890Swnj if (so->so_state & SS_CANTRCVMORE) { 4084890Swnj splx(s); 4094890Swnj goto release; 4104890Swnj } 4115015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4125015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4135015Sroot rcverr(ENOTCONN); 4146214Swnj if (so->so_state & SS_NBIO) 4155168Swnj rcverr(EWOULDBLOCK); 4164890Swnj sbunlock(&so->so_rcv); 4174971Swnj sbwait(&so->so_rcv); 4185012Swnj splx(s); 4194890Swnj goto restart; 4204786Swnj } 4218041Sroot u.u_ru.ru_msgrcv++; 4224829Swnj m = so->so_rcv.sb_mb; 4234786Swnj if (m == 0) 4244786Swnj panic("receive"); 4258548Sroot SBCHECK(&so->so_snd, "soreceive havecc"); 4265039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4278319Sroot if ((flags & SOF_PREVIEW) == 0) { 4288319Sroot so->so_rcv.sb_cc -= m->m_len; 4298319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4308319Sroot } 4318300Sroot if (aname) { 4328319Sroot if (flags & SOF_PREVIEW) 4338319Sroot *aname = m_copy(m, 0, m->m_len); 4348319Sroot else 4358319Sroot *aname = m; 4368300Sroot m = m->m_next; 4378300Sroot (*aname)->m_next = 0; 4388300Sroot } else 4398319Sroot if (flags & SOF_PREVIEW) 4408319Sroot m = m->m_next; 4418319Sroot else 4428319Sroot m = m_free(m); 4434890Swnj if (m == 0) 4444890Swnj panic("receive 2"); 4458548Sroot if ((flags & SOF_PREVIEW) == 0) 4468548Sroot so->so_rcv.sb_mb = m; 4478548Sroot SBCHECK(&so->so_snd, "soreceive afteraddr"); 4484890Swnj } 4494786Swnj eor = 0; 4508319Sroot moff = 0; 4518319Sroot tomark = so->so_oobmark; 4524786Swnj do { 4537827Sroot if (uio->uio_resid <= 0) 4547747Sroot break; 4557827Sroot len = uio->uio_resid; 4567747Sroot so->so_state &= ~SS_RCVATMARK; 4578319Sroot if (tomark && len > tomark) 4588319Sroot len = tomark; 4598548Sroot if (moff+len > m->m_len - moff) 4608319Sroot len = m->m_len - moff; 4614786Swnj splx(s); 4628594Sroot error = 4638594Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4644786Swnj s = splnet(); 4654786Swnj if (len == m->m_len) { 4666091Sroot eor = (int)m->m_act; 4678319Sroot if (flags & SOF_PREVIEW) 4688319Sroot m = m->m_next; 4698319Sroot else { 4708319Sroot sbfree(&so->so_rcv, m); 4718319Sroot MFREE(m, n); 4728319Sroot m = n; 4738548Sroot so->so_rcv.sb_mb = m; 4748319Sroot } 4758319Sroot moff = 0; 4764786Swnj } else { 4778319Sroot if (flags & SOF_PREVIEW) 4788319Sroot moff += len; 4798319Sroot else { 4808319Sroot m->m_off += len; 4818319Sroot m->m_len -= len; 4828319Sroot so->so_rcv.sb_cc -= len; 4838319Sroot } 4844786Swnj } 4858319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4867747Sroot so->so_oobmark -= len; 4877747Sroot if (so->so_oobmark == 0) { 4887747Sroot so->so_state |= SS_RCVATMARK; 4897747Sroot break; 4907747Sroot } 4917747Sroot } 4928319Sroot if (tomark) { 4938319Sroot tomark -= len; 4948319Sroot if (tomark == 0) 4958319Sroot break; 4968319Sroot } 4978548Sroot SBCHECK(&so->so_snd, "soreceive rcvloop"); 4988594Sroot } while (m && error == 0 && !eor); 4998319Sroot if (flags & SOF_PREVIEW) 5008319Sroot goto release; 5014786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5024786Swnj do { 5034786Swnj if (m == 0) 5044890Swnj panic("receive 3"); 5054890Swnj sbfree(&so->so_rcv, m); 5064786Swnj eor = (int)m->m_act; 5074786Swnj so->so_rcv.sb_mb = m->m_next; 5084786Swnj MFREE(m, n); 5094890Swnj m = n; 5108548Sroot SBCHECK(&so->so_snd, "soreceive atomicloop"); 5114786Swnj } while (eor == 0); 5124890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5138300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5148300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5154890Swnj release: 5164916Swnj sbunlock(&so->so_rcv); 5174890Swnj splx(s); 5184916Swnj return (error); 5194786Swnj } 5204786Swnj 5215423Swnj sohasoutofband(so) 5225423Swnj struct socket *so; 5235423Swnj { 5245423Swnj 5255423Swnj if (so->so_pgrp == 0) 5265423Swnj return; 5275423Swnj if (so->so_pgrp > 0) 5285423Swnj gsignal(so->so_pgrp, SIGURG); 5295429Swnj else { 5305429Swnj struct proc *p = pfind(-so->so_pgrp); 5315429Swnj 5325429Swnj if (p) 5335429Swnj psignal(p, SIGURG); 5345429Swnj } 5355423Swnj } 5365423Swnj 5374916Swnj /*ARGSUSED*/ 5387627Ssam soioctl(so, cmd, data) 5394829Swnj register struct socket *so; 5404829Swnj int cmd; 5417627Ssam register char *data; 5424786Swnj { 5434786Swnj 5445358Sroot switch (cmd) { 5454829Swnj 5467627Ssam case FIONBIO: 5477627Ssam if (*(int *)data) 5486214Swnj so->so_state |= SS_NBIO; 5495388Sroot else 5506214Swnj so->so_state &= ~SS_NBIO; 5518594Sroot break; 5525388Sroot 5537627Ssam case FIOASYNC: 5547627Ssam if (*(int *)data) 5556214Swnj so->so_state |= SS_ASYNC; 5565388Sroot else 5576214Swnj so->so_state &= ~SS_ASYNC; 5588594Sroot break; 5595388Sroot 5607627Ssam case SIOCSKEEP: 5617627Ssam if (*(int *)data) 5627507Sroot so->so_options &= ~SO_KEEPALIVE; 5637507Sroot else 5647491Ssam so->so_options |= SO_KEEPALIVE; 5658594Sroot break; 5665388Sroot 5677627Ssam case SIOCGKEEP: 5687627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5698594Sroot break; 5705388Sroot 5717627Ssam case SIOCSLINGER: 5727627Ssam so->so_linger = *(int *)data; 5735388Sroot if (so->so_linger) 5745388Sroot so->so_options &= ~SO_DONTLINGER; 5755388Sroot else 5765388Sroot so->so_options |= SO_DONTLINGER; 5778594Sroot break; 5785388Sroot 5797627Ssam case SIOCGLINGER: 5807627Ssam *(int *)data = so->so_linger; 5818594Sroot break; 5825388Sroot 5837627Ssam case SIOCSPGRP: 5847627Ssam so->so_pgrp = *(int *)data; 5858594Sroot break; 5865423Swnj 5877627Ssam case SIOCGPGRP: 5887627Ssam *(int *)data = so->so_pgrp; 5898594Sroot break; 5907627Ssam 5915281Sroot case SIOCDONE: { 5927627Ssam int flags = *(int *)data; 5937627Ssam 5945388Sroot flags++; 5955281Sroot if (flags & FREAD) { 5965281Sroot int s = splimp(); 5975281Sroot socantrcvmore(so); 5985281Sroot sbflush(&so->so_rcv); 5996140Ssam splx(s); 6005281Sroot } 6015281Sroot if (flags & FWRITE) 6028560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 6038300Sroot (struct mbuf *)0, (struct mbuf *)0, 6048560Sroot (struct socketopt *)0)); 6058594Sroot break; 6064829Swnj } 6075281Sroot 6085423Swnj case SIOCSENDOOB: { 6097627Ssam char oob = *(char *)data; 6108319Sroot struct mbuf *m = m_get(M_DONTWAIT); 6117627Ssam 6128594Sroot if (m == 0) 6138594Sroot return (ENOBUFS); 6148319Sroot m->m_len = 1; 6157627Ssam *mtod(m, char *) = oob; 6168560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 6178560Sroot m, (struct mbuf *)0, (struct socketopt *)0)); 6185281Sroot } 6195423Swnj 6205423Swnj case SIOCRCVOOB: { 6218319Sroot struct mbuf *m = m_get(M_WAIT); 6227627Ssam 6238594Sroot if (m == 0) 6248594Sroot return (ENOBUFS); 6258319Sroot *mtod(m, caddr_t) = 0; 6268300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 6278300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6287627Ssam *(char *)data = *mtod(m, char *); 6297627Ssam (void) m_free(m); 6308594Sroot break; 6315423Swnj } 6325423Swnj 6337627Ssam case SIOCATMARK: 6347627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6358594Sroot break; 6366355Ssam 6376355Ssam /* routing table update calls */ 6386355Ssam case SIOCADDRT: 6396355Ssam case SIOCDELRT: 6406355Ssam if (!suser()) 6418560Sroot return (u.u_error); /* XXX */ 6428560Sroot return (rtrequest(cmd, (struct rtentry *)data)); 6436355Ssam 6445445Swnj /* type/protocol specific ioctls */ 6458594Sroot default: 6468594Sroot return (ENOTTY); 6475423Swnj } 6488594Sroot return (0); 6494786Swnj } 650