1*8548Sroot /* uipc_socket.c 4.53 82/10/16 */ 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 288300Sroot socreate(dom, aso, type, proto, opt) 294786Swnj struct socket **aso; 308300Sroot int type, proto; 318300Sroot struct socketopt *opt; 324786Swnj { 334786Swnj register struct protosw *prp; 344786Swnj register struct socket *so; 354786Swnj struct mbuf *m; 368300Sroot int pf, error; 374786Swnj 388300Sroot pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ 394890Swnj if (proto) 404890Swnj prp = pffindproto(pf, proto); 414890Swnj else 424890Swnj prp = pffindtype(pf, type); 434890Swnj if (prp == 0) 444890Swnj return (EPROTONOSUPPORT); 458300Sroot if (prp->pr_type != type) 468300Sroot return (EPROTOTYPE); 474890Swnj m = m_getclr(M_WAIT); 484786Swnj if (m == 0) 494786Swnj return (ENOBUFS); 504786Swnj so = mtod(m, struct socket *); 518300Sroot so->so_options = 0; 526214Swnj so->so_state = 0; 536214Swnj if (u.u_uid == 0) 546214Swnj so->so_state = SS_PRIV; 554786Swnj so->so_proto = prp; 568300Sroot error = (*prp->pr_usrreq)(so, PRU_ATTACH, 578300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 584979Swnj if (error) { 597507Sroot so->so_state |= SS_NOFDREF; 607180Swnj sofree(so); 614890Swnj return (error); 624786Swnj } 634786Swnj *aso = so; 644786Swnj return (0); 654786Swnj } 664786Swnj 678300Sroot sobind(so, nam, opt) 688300Sroot struct socket *so; 698300Sroot struct mbuf *nam; 708300Sroot struct socketopt *opt; 718300Sroot { 728300Sroot int s = splnet(); 738300Sroot int error; 748300Sroot 758300Sroot error = 768300Sroot (*so->so_proto->pr_usrreq)(so, PRU_BIND, 778300Sroot (struct mbuf *)0, nam, opt); 788300Sroot splx(s); 798300Sroot return (error); 808300Sroot } 818300Sroot 828300Sroot solisten(so, backlog) 838300Sroot struct socket *so; 848300Sroot int backlog; 858300Sroot { 868300Sroot int s = splnet(); 878300Sroot int error; 888300Sroot 898300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 908300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 918300Sroot if (error) { 928300Sroot splx(s); 938300Sroot return (error); 948300Sroot } 958300Sroot if (so->so_q == 0) { 968300Sroot so->so_q = so; 978300Sroot so->so_q0 = so; 988300Sroot so->so_options |= SO_ACCEPTCONN; 998300Sroot } 1008300Sroot if (backlog < 0) 1018300Sroot backlog = 0; 1028300Sroot so->so_qlimit = backlog < 5 ? backlog : 5; 1038300Sroot so->so_options |= SO_NEWFDONCONN; 1048300Sroot return (0); 1058300Sroot } 1068300Sroot 1074916Swnj sofree(so) 1084916Swnj struct socket *so; 1094916Swnj { 1104916Swnj 1117507Sroot if (so->so_head) { 1127507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1137507Sroot panic("sofree dq"); 1147507Sroot so->so_head = 0; 1157507Sroot } 1167507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1174950Swnj return; 1184950Swnj sbrelease(&so->so_snd); 1194950Swnj sbrelease(&so->so_rcv); 1204971Swnj (void) m_free(dtom(so)); 1214916Swnj } 1224916Swnj 1234786Swnj /* 1244890Swnj * Close a socket on last file table reference removal. 1254890Swnj * Initiate disconnect if connected. 1264890Swnj * Free socket when disconnect complete. 1274829Swnj */ 1285580Sroot soclose(so, exiting) 1294829Swnj register struct socket *so; 1305580Sroot int exiting; 1314829Swnj { 1324890Swnj int s = splnet(); /* conservative */ 1334829Swnj 1347507Sroot if (so->so_options & SO_ACCEPTCONN) { 1357507Sroot while (so->so_q0 != so) 1367507Sroot soclose(so->so_q0, 1); 1377507Sroot while (so->so_q != so) 1387507Sroot soclose(so->so_q, 1); 1397507Sroot } 1404890Swnj if (so->so_pcb == 0) 1414890Swnj goto discard; 1426259Sroot if (exiting) 1436259Sroot so->so_options |= SO_KEEPALIVE; 1444890Swnj if (so->so_state & SS_ISCONNECTED) { 1454890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1464927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1474890Swnj if (u.u_error) { 1485580Sroot if (exiting) 1495580Sroot goto drop; 1504890Swnj splx(s); 1514890Swnj return; 1524890Swnj } 1534890Swnj } 1545388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1555281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1566214Swnj (so->so_state & SS_NBIO) && 1575580Sroot exiting == 0) { 1585281Sroot u.u_error = EINPROGRESS; 1595281Sroot splx(s); 1605281Sroot return; 1615281Sroot } 1625580Sroot /* should use tsleep here, for at most linger */ 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) { 1698300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1708300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 1716880Ssam if (exiting == 0 && u.u_error) { 1726880Ssam splx(s); 1736880Ssam return; 1746880Ssam } 1756880Ssam } 1764890Swnj discard: 1777507Sroot so->so_state |= SS_NOFDREF; 1784950Swnj sofree(so); 1794890Swnj splx(s); 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 = ⊤ 2634916Swnj register u_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 { 3717747Sroot register struct iovec *iov; 3724786Swnj register struct mbuf *m, *n; 3734916Swnj u_int len; 3748319Sroot int eor, s, error = 0, moff, tomark; 3754786Swnj 3768319Sroot if (flags & SOF_OOB) { 3778319Sroot struct mbuf *m = m_get(M_WAIT); 3788319Sroot 3798319Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 3808319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 3818319Sroot len = uio->uio_resid; 3828319Sroot do { 3838319Sroot if (len > m->m_len) 3848319Sroot len = m->m_len; 3858319Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 3868319Sroot m = m_free(m); 3878319Sroot } while (uio->uio_resid && u.u_error == 0 && m); 3888319Sroot if (m) 3898319Sroot (void) m_freem(m); 3908319Sroot return; 3918319Sroot } 3928319Sroot 3934890Swnj restart: 3944890Swnj sblock(&so->so_rcv); 395*8548Sroot SBCHECK(&so->so_snd, "soreceive restart"); 3964890Swnj s = splnet(); 3974890Swnj 3984890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3994786Swnj if (so->so_rcv.sb_cc == 0) { 4005168Swnj if (so->so_error) { 4015168Swnj error = so->so_error; 4025168Swnj so->so_error = 0; 4035168Swnj splx(s); 4045168Swnj goto release; 4055168Swnj } 4064890Swnj if (so->so_state & SS_CANTRCVMORE) { 4074890Swnj splx(s); 4084890Swnj goto release; 4094890Swnj } 4105015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4115015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4125015Sroot rcverr(ENOTCONN); 4136214Swnj if (so->so_state & SS_NBIO) 4145168Swnj rcverr(EWOULDBLOCK); 4154890Swnj sbunlock(&so->so_rcv); 4164971Swnj sbwait(&so->so_rcv); 4175012Swnj splx(s); 4184890Swnj goto restart; 4194786Swnj } 4208041Sroot u.u_ru.ru_msgrcv++; 4214829Swnj m = so->so_rcv.sb_mb; 4224786Swnj if (m == 0) 4234786Swnj panic("receive"); 424*8548Sroot SBCHECK(&so->so_snd, "soreceive havecc"); 4255039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4268319Sroot if ((flags & SOF_PREVIEW) == 0) { 4278319Sroot so->so_rcv.sb_cc -= m->m_len; 4288319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4298319Sroot } 4308300Sroot if (aname) { 4318319Sroot if (flags & SOF_PREVIEW) 4328319Sroot *aname = m_copy(m, 0, m->m_len); 4338319Sroot else 4348319Sroot *aname = m; 4358300Sroot m = m->m_next; 4368300Sroot (*aname)->m_next = 0; 4378300Sroot } else 4388319Sroot if (flags & SOF_PREVIEW) 4398319Sroot m = m->m_next; 4408319Sroot else 4418319Sroot m = m_free(m); 4424890Swnj if (m == 0) 4434890Swnj panic("receive 2"); 444*8548Sroot if ((flags & SOF_PREVIEW) == 0) 445*8548Sroot so->so_rcv.sb_mb = m; 446*8548Sroot SBCHECK(&so->so_snd, "soreceive afteraddr"); 4474890Swnj } 4484786Swnj eor = 0; 4498319Sroot moff = 0; 4508319Sroot tomark = so->so_oobmark; 4514786Swnj do { 4527827Sroot if (uio->uio_resid <= 0) 4537747Sroot break; 4547827Sroot len = uio->uio_resid; 4557747Sroot so->so_state &= ~SS_RCVATMARK; 4568319Sroot if (tomark && len > tomark) 4578319Sroot len = tomark; 458*8548Sroot if (moff+len > m->m_len - moff) 4598319Sroot len = m->m_len - moff; 4604786Swnj splx(s); 4618319Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4624786Swnj s = splnet(); 4634786Swnj if (len == m->m_len) { 4646091Sroot eor = (int)m->m_act; 4658319Sroot if (flags & SOF_PREVIEW) 4668319Sroot m = m->m_next; 4678319Sroot else { 4688319Sroot sbfree(&so->so_rcv, m); 4698319Sroot MFREE(m, n); 4708319Sroot m = n; 471*8548Sroot so->so_rcv.sb_mb = m; 4728319Sroot } 4738319Sroot moff = 0; 4744786Swnj } else { 4758319Sroot if (flags & SOF_PREVIEW) 4768319Sroot moff += len; 4778319Sroot else { 4788319Sroot m->m_off += len; 4798319Sroot m->m_len -= len; 4808319Sroot so->so_rcv.sb_cc -= len; 4818319Sroot } 4824786Swnj } 4838319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4847747Sroot so->so_oobmark -= len; 4857747Sroot if (so->so_oobmark == 0) { 4867747Sroot so->so_state |= SS_RCVATMARK; 4877747Sroot break; 4887747Sroot } 4897747Sroot } 4908319Sroot if (tomark) { 4918319Sroot tomark -= len; 4928319Sroot if (tomark == 0) 4938319Sroot break; 4948319Sroot } 495*8548Sroot SBCHECK(&so->so_snd, "soreceive rcvloop"); 4968319Sroot } while (m && !eor); 4978319Sroot if (flags & SOF_PREVIEW) 4988319Sroot goto release; 4994786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5004786Swnj do { 5014786Swnj if (m == 0) 5024890Swnj panic("receive 3"); 5034890Swnj sbfree(&so->so_rcv, m); 5044786Swnj eor = (int)m->m_act; 5054786Swnj so->so_rcv.sb_mb = m->m_next; 5064786Swnj MFREE(m, n); 5074890Swnj m = n; 508*8548Sroot SBCHECK(&so->so_snd, "soreceive atomicloop"); 5094786Swnj } while (eor == 0); 5104890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5118300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5128300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5134890Swnj release: 5144916Swnj sbunlock(&so->so_rcv); 5154890Swnj splx(s); 5164916Swnj return (error); 5174786Swnj } 5184786Swnj 5195423Swnj sohasoutofband(so) 5205423Swnj struct socket *so; 5215423Swnj { 5225423Swnj 5235423Swnj if (so->so_pgrp == 0) 5245423Swnj return; 5255423Swnj if (so->so_pgrp > 0) 5265423Swnj gsignal(so->so_pgrp, SIGURG); 5275429Swnj else { 5285429Swnj struct proc *p = pfind(-so->so_pgrp); 5295429Swnj 5305429Swnj if (p) 5315429Swnj psignal(p, SIGURG); 5325429Swnj } 5335423Swnj } 5345423Swnj 5354916Swnj /*ARGSUSED*/ 5367627Ssam soioctl(so, cmd, data) 5374829Swnj register struct socket *so; 5384829Swnj int cmd; 5397627Ssam register char *data; 5404786Swnj { 5414786Swnj 5425358Sroot switch (cmd) { 5434829Swnj 5447627Ssam case FIONBIO: 5457627Ssam if (*(int *)data) 5466214Swnj so->so_state |= SS_NBIO; 5475388Sroot else 5486214Swnj so->so_state &= ~SS_NBIO; 5495388Sroot return; 5505388Sroot 5517627Ssam case FIOASYNC: 5527627Ssam if (*(int *)data) 5536214Swnj so->so_state |= SS_ASYNC; 5545388Sroot else 5556214Swnj so->so_state &= ~SS_ASYNC; 5565388Sroot return; 5575388Sroot 5587627Ssam case SIOCSKEEP: 5597627Ssam if (*(int *)data) 5607507Sroot so->so_options &= ~SO_KEEPALIVE; 5617507Sroot else 5627491Ssam so->so_options |= SO_KEEPALIVE; 5635388Sroot return; 5645388Sroot 5657627Ssam case SIOCGKEEP: 5667627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5675388Sroot return; 5685388Sroot 5697627Ssam case SIOCSLINGER: 5707627Ssam so->so_linger = *(int *)data; 5715388Sroot if (so->so_linger) 5725388Sroot so->so_options &= ~SO_DONTLINGER; 5735388Sroot else 5745388Sroot so->so_options |= SO_DONTLINGER; 5755388Sroot return; 5765388Sroot 5777627Ssam case SIOCGLINGER: 5787627Ssam *(int *)data = so->so_linger; 5795423Swnj return; 5805388Sroot 5817627Ssam case SIOCSPGRP: 5827627Ssam so->so_pgrp = *(int *)data; 5837627Ssam return; 5845423Swnj 5857627Ssam case SIOCGPGRP: 5867627Ssam *(int *)data = so->so_pgrp; 5877627Ssam return; 5887627Ssam 5895281Sroot case SIOCDONE: { 5907627Ssam int flags = *(int *)data; 5917627Ssam 5925388Sroot flags++; 5935281Sroot if (flags & FREAD) { 5945281Sroot int s = splimp(); 5955281Sroot socantrcvmore(so); 5965281Sroot sbflush(&so->so_rcv); 5976140Ssam splx(s); 5985281Sroot } 5995281Sroot if (flags & FWRITE) 6008300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 6018300Sroot (struct mbuf *)0, (struct mbuf *)0, 6028300Sroot (struct socketopt *)0); 6035281Sroot return; 6044829Swnj } 6055281Sroot 6065423Swnj case SIOCSENDOOB: { 6077627Ssam char oob = *(char *)data; 6088319Sroot struct mbuf *m = m_get(M_DONTWAIT); 6097627Ssam 6105423Swnj if (m == 0) { 6115423Swnj u.u_error = ENOBUFS; 6125423Swnj return; 6135423Swnj } 6148319Sroot m->m_len = 1; 6157627Ssam *mtod(m, char *) = oob; 6168300Sroot (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 6178300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6185423Swnj return; 6195281Sroot } 6205423Swnj 6215423Swnj case SIOCRCVOOB: { 6228319Sroot struct mbuf *m = m_get(M_WAIT); 6237627Ssam 6245423Swnj if (m == 0) { 6255423Swnj u.u_error = ENOBUFS; 6265423Swnj return; 6275423Swnj } 6288319Sroot *mtod(m, caddr_t) = 0; 6298300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 6308300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6317627Ssam *(char *)data = *mtod(m, char *); 6327627Ssam (void) m_free(m); 6335423Swnj return; 6345423Swnj } 6355423Swnj 6367627Ssam case SIOCATMARK: 6377627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6385423Swnj return; 6396355Ssam 6406355Ssam /* routing table update calls */ 6416355Ssam case SIOCADDRT: 6426355Ssam case SIOCDELRT: 6436355Ssam if (!suser()) 6446355Ssam return; 6457627Ssam u.u_error = rtrequest(cmd, (struct rtentry *)data); 6466355Ssam return; 6476355Ssam 6485445Swnj /* type/protocol specific ioctls */ 6495423Swnj } 6505445Swnj u.u_error = EOPNOTSUPP; 6514786Swnj } 652