1*8594Sroot /* uipc_socket.c 4.56 82/10/17 */ 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 28*8594Sroot /*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 */ 1344829Swnj 1357507Sroot if (so->so_options & SO_ACCEPTCONN) { 1367507Sroot while (so->so_q0 != so) 1377507Sroot soclose(so->so_q0, 1); 1387507Sroot while (so->so_q != so) 1397507Sroot soclose(so->so_q, 1); 1407507Sroot } 1414890Swnj if (so->so_pcb == 0) 1424890Swnj goto discard; 1436259Sroot if (exiting) 1446259Sroot so->so_options |= SO_KEEPALIVE; 1454890Swnj if (so->so_state & SS_ISCONNECTED) { 1464890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1474927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1484890Swnj if (u.u_error) { 1495580Sroot if (exiting) 1505580Sroot goto drop; 1514890Swnj splx(s); 1524890Swnj return; 1534890Swnj } 1544890Swnj } 1555388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1565281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1576214Swnj (so->so_state & SS_NBIO) && 1585580Sroot exiting == 0) { 1595281Sroot u.u_error = EINPROGRESS; 1605281Sroot splx(s); 1615281Sroot return; 1625281Sroot } 1635580Sroot /* should use tsleep here, for at most linger */ 1645281Sroot while (so->so_state & SS_ISCONNECTED) 1655281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1664890Swnj } 1674890Swnj } 1685580Sroot drop: 1696880Ssam if (so->so_pcb) { 1708300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1718300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 1726880Ssam if (exiting == 0 && u.u_error) { 1736880Ssam splx(s); 1746880Ssam return; 1756880Ssam } 1766880Ssam } 1774890Swnj discard: 1787507Sroot so->so_state |= SS_NOFDREF; 1794950Swnj sofree(so); 1804890Swnj splx(s); 1814829Swnj } 1824829Swnj 1834916Swnj /*ARGSUSED*/ 1844890Swnj sostat(so, sb) 1854829Swnj struct socket *so; 1864890Swnj struct stat *sb; 1874829Swnj { 1884829Swnj 1895303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1905303Sroot return (0); /* XXX */ 1914829Swnj } 1924829Swnj 1938300Sroot soaccept(so, nam, opt) 1944927Swnj struct socket *so; 1958300Sroot struct mbuf *nam; 1968300Sroot struct socketopt *opt; 1974927Swnj { 1984927Swnj int s = splnet(); 1994927Swnj int error; 2004927Swnj 2018300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 2028300Sroot (struct mbuf *)0, nam, opt); 2034927Swnj splx(s); 2044927Swnj return (error); 2054927Swnj } 2064927Swnj 2078300Sroot soconnect(so, nam, opt) 2084786Swnj struct socket *so; 2098300Sroot struct mbuf *nam; 2108300Sroot struct socketopt *opt; 2114786Swnj { 2124890Swnj int s = splnet(); 2134890Swnj int error; 2144786Swnj 2154890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2164890Swnj error = EISCONN; 2174890Swnj goto bad; 2184890Swnj } 2198300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 2208300Sroot (struct mbuf *)0, nam, opt); 2214890Swnj bad: 2224890Swnj splx(s); 2234890Swnj return (error); 2244786Swnj } 2254786Swnj 2268300Sroot sodisconnect(so, nam) 2274786Swnj struct socket *so; 2288300Sroot struct mbuf *nam; 2294786Swnj { 2304890Swnj int s = splnet(); 2314890Swnj int error; 2324786Swnj 2334890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2344890Swnj error = ENOTCONN; 2354890Swnj goto bad; 2364890Swnj } 2374890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2384890Swnj error = EALREADY; 2394890Swnj goto bad; 2404890Swnj } 2418300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 2428300Sroot (struct mbuf *)0, nam, (struct socketopt *)0); 2434890Swnj bad: 2444890Swnj splx(s); 2454890Swnj return (error); 2464786Swnj } 2474786Swnj 2484786Swnj /* 2494890Swnj * Send on a socket. 2504890Swnj * If send must go all at once and message is larger than 2514890Swnj * send buffering, then hard error. 2524890Swnj * Lock against other senders. 2534890Swnj * If must go all at once and not enough room now, then 2544890Swnj * inform user that this would block and do nothing. 2554786Swnj */ 2568319Sroot sosend(so, nam, uio, flags) 2574786Swnj register struct socket *so; 2588300Sroot struct mbuf *nam; 2597827Sroot struct uio *uio; 2608319Sroot int flags; 2614786Swnj { 2624890Swnj struct mbuf *top = 0; 2634890Swnj register struct mbuf *m, **mp = ⊤ 2644916Swnj register u_int len; 2654916Swnj int error = 0, space, s; 2664786Swnj 2677827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2684890Swnj return (EMSGSIZE); 2696419Sroot restart: 2704890Swnj sblock(&so->so_snd); 2714890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2724890Swnj 2738041Sroot u.u_ru.ru_msgsnd++; 2746419Sroot again: 2754890Swnj s = splnet(); 2766419Sroot if (so->so_state & SS_CANTSENDMORE) { 2776419Sroot psignal(u.u_procp, SIGPIPE); 2786419Sroot snderr(EPIPE); 2796419Sroot } 2805168Swnj if (so->so_error) { 2815168Swnj error = so->so_error; 2826419Sroot so->so_error = 0; /* ??? */ 2835168Swnj splx(s); 2845168Swnj goto release; 2855168Swnj } 2864890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2874890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2884890Swnj snderr(ENOTCONN); 2898300Sroot if (nam == 0) 2904890Swnj snderr(EDESTADDRREQ); 2914890Swnj } 2924890Swnj if (top) { 2938319Sroot error = (*so->so_proto->pr_usrreq)(so, 2948319Sroot (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 2958300Sroot top, (caddr_t)nam, (struct socketopt *)0); 2966419Sroot top = 0; 2974890Swnj if (error) { 2984890Swnj splx(s); 2994786Swnj goto release; 3004786Swnj } 3014890Swnj mp = ⊤ 3024786Swnj } 3037827Sroot if (uio->uio_resid == 0) { 3044979Swnj splx(s); 3054979Swnj goto release; 3064979Swnj } 3078319Sroot if (flags & SOF_OOB) 3088319Sroot space = 1024; 3098319Sroot else { 3108319Sroot space = sbspace(&so->so_snd); 3118319Sroot if (space <= 0 || 3128319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3138319Sroot if (so->so_state & SS_NBIO) 3148319Sroot snderr(EWOULDBLOCK); 3158319Sroot sbunlock(&so->so_snd); 3168319Sroot sbwait(&so->so_snd); 3178319Sroot splx(s); 3188319Sroot goto restart; 3198319Sroot } 3204786Swnj } 3214890Swnj splx(s); 3227827Sroot while (uio->uio_resid > 0 && space > 0) { 3237827Sroot register struct iovec *iov = uio->uio_iov; 3247827Sroot 3257827Sroot if (iov->iov_len == 0) { 3267827Sroot uio->uio_iov++; 3277827Sroot uio->uio_iovcnt--; 3287827Sroot if (uio->uio_iovcnt < 0) 3297827Sroot panic("sosend"); 3307827Sroot continue; 3317827Sroot } 3324890Swnj MGET(m, 1); 3334890Swnj if (m == NULL) { 3346419Sroot error = ENOBUFS; /* SIGPIPE? */ 3354890Swnj goto release; 3364786Swnj } 3377827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3384890Swnj register struct mbuf *p; 3395095Swnj MCLGET(p, 1); 3404890Swnj if (p == 0) 3414890Swnj goto nopages; 3424890Swnj m->m_off = (int)p - (int)m; 3435095Swnj len = CLBYTES; 3444890Swnj } else { 3454786Swnj nopages: 3467827Sroot len = MIN(MLEN, iov->iov_len); 3474786Swnj } 3487827Sroot uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3494890Swnj m->m_len = len; 3504890Swnj *mp = m; 3514890Swnj mp = &m->m_next; 3528319Sroot if (flags & SOF_OOB) 3538319Sroot space -= len; 3548319Sroot else 3558319Sroot space = sbspace(&so->so_snd); 3564786Swnj } 3574890Swnj goto again; 3584890Swnj 3594786Swnj release: 3604890Swnj sbunlock(&so->so_snd); 3616419Sroot if (top) 3626419Sroot m_freem(top); 3634786Swnj return (error); 3644786Swnj } 3654786Swnj 3668319Sroot soreceive(so, aname, uio, flags) 3674786Swnj register struct socket *so; 3688300Sroot struct mbuf **aname; 3697747Sroot struct uio *uio; 3708319Sroot int flags; 3714786Swnj { 3724786Swnj register struct mbuf *m, *n; 3734916Swnj u_int len; 3748319Sroot int eor, s, error = 0, moff, tomark; 3754786Swnj 3768319Sroot if (flags & SOF_OOB) { 377*8594Sroot m = m_get(M_WAIT); 378*8594Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 3798319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 380*8594Sroot if (error) 381*8594Sroot return; 3828319Sroot len = uio->uio_resid; 3838319Sroot do { 3848319Sroot if (len > m->m_len) 3858319Sroot len = m->m_len; 386*8594Sroot error = 387*8594Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 3888319Sroot m = m_free(m); 389*8594Sroot } while (uio->uio_resid && error == 0 && m); 3908319Sroot if (m) 3918319Sroot (void) m_freem(m); 392*8594Sroot return (error); 3938319Sroot } 3948319Sroot 3954890Swnj restart: 3964890Swnj sblock(&so->so_rcv); 3978552Sroot SBCHECK(&so->so_rcv, "soreceive restart"); 3984890Swnj s = splnet(); 3994890Swnj 4004890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4014786Swnj if (so->so_rcv.sb_cc == 0) { 4025168Swnj if (so->so_error) { 4035168Swnj error = so->so_error; 4045168Swnj so->so_error = 0; 4055168Swnj splx(s); 4065168Swnj goto release; 4075168Swnj } 4084890Swnj if (so->so_state & SS_CANTRCVMORE) { 4094890Swnj splx(s); 4104890Swnj goto release; 4114890Swnj } 4125015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4135015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4145015Sroot rcverr(ENOTCONN); 4156214Swnj if (so->so_state & SS_NBIO) 4165168Swnj rcverr(EWOULDBLOCK); 4174890Swnj sbunlock(&so->so_rcv); 4184971Swnj sbwait(&so->so_rcv); 4195012Swnj splx(s); 4204890Swnj goto restart; 4214786Swnj } 4228041Sroot u.u_ru.ru_msgrcv++; 4234829Swnj m = so->so_rcv.sb_mb; 4244786Swnj if (m == 0) 4254786Swnj panic("receive"); 4268548Sroot SBCHECK(&so->so_snd, "soreceive havecc"); 4275039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4288319Sroot if ((flags & SOF_PREVIEW) == 0) { 4298319Sroot so->so_rcv.sb_cc -= m->m_len; 4308319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4318319Sroot } 4328300Sroot if (aname) { 4338319Sroot if (flags & SOF_PREVIEW) 4348319Sroot *aname = m_copy(m, 0, m->m_len); 4358319Sroot else 4368319Sroot *aname = m; 4378300Sroot m = m->m_next; 4388300Sroot (*aname)->m_next = 0; 4398300Sroot } else 4408319Sroot if (flags & SOF_PREVIEW) 4418319Sroot m = m->m_next; 4428319Sroot else 4438319Sroot m = m_free(m); 4444890Swnj if (m == 0) 4454890Swnj panic("receive 2"); 4468548Sroot if ((flags & SOF_PREVIEW) == 0) 4478548Sroot so->so_rcv.sb_mb = m; 4488548Sroot SBCHECK(&so->so_snd, "soreceive afteraddr"); 4494890Swnj } 4504786Swnj eor = 0; 4518319Sroot moff = 0; 4528319Sroot tomark = so->so_oobmark; 4534786Swnj do { 4547827Sroot if (uio->uio_resid <= 0) 4557747Sroot break; 4567827Sroot len = uio->uio_resid; 4577747Sroot so->so_state &= ~SS_RCVATMARK; 4588319Sroot if (tomark && len > tomark) 4598319Sroot len = tomark; 4608548Sroot if (moff+len > m->m_len - moff) 4618319Sroot len = m->m_len - moff; 4624786Swnj splx(s); 463*8594Sroot error = 464*8594Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4654786Swnj s = splnet(); 4664786Swnj if (len == m->m_len) { 4676091Sroot eor = (int)m->m_act; 4688319Sroot if (flags & SOF_PREVIEW) 4698319Sroot m = m->m_next; 4708319Sroot else { 4718319Sroot sbfree(&so->so_rcv, m); 4728319Sroot MFREE(m, n); 4738319Sroot m = n; 4748548Sroot so->so_rcv.sb_mb = m; 4758319Sroot } 4768319Sroot moff = 0; 4774786Swnj } else { 4788319Sroot if (flags & SOF_PREVIEW) 4798319Sroot moff += len; 4808319Sroot else { 4818319Sroot m->m_off += len; 4828319Sroot m->m_len -= len; 4838319Sroot so->so_rcv.sb_cc -= len; 4848319Sroot } 4854786Swnj } 4868319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4877747Sroot so->so_oobmark -= len; 4887747Sroot if (so->so_oobmark == 0) { 4897747Sroot so->so_state |= SS_RCVATMARK; 4907747Sroot break; 4917747Sroot } 4927747Sroot } 4938319Sroot if (tomark) { 4948319Sroot tomark -= len; 4958319Sroot if (tomark == 0) 4968319Sroot break; 4978319Sroot } 4988548Sroot SBCHECK(&so->so_snd, "soreceive rcvloop"); 499*8594Sroot } while (m && error == 0 && !eor); 5008319Sroot if (flags & SOF_PREVIEW) 5018319Sroot goto release; 5024786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5034786Swnj do { 5044786Swnj if (m == 0) 5054890Swnj panic("receive 3"); 5064890Swnj sbfree(&so->so_rcv, m); 5074786Swnj eor = (int)m->m_act; 5084786Swnj so->so_rcv.sb_mb = m->m_next; 5094786Swnj MFREE(m, n); 5104890Swnj m = n; 5118548Sroot SBCHECK(&so->so_snd, "soreceive atomicloop"); 5124786Swnj } while (eor == 0); 5134890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5148300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5158300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5164890Swnj release: 5174916Swnj sbunlock(&so->so_rcv); 5184890Swnj splx(s); 5194916Swnj return (error); 5204786Swnj } 5214786Swnj 5225423Swnj sohasoutofband(so) 5235423Swnj struct socket *so; 5245423Swnj { 5255423Swnj 5265423Swnj if (so->so_pgrp == 0) 5275423Swnj return; 5285423Swnj if (so->so_pgrp > 0) 5295423Swnj gsignal(so->so_pgrp, SIGURG); 5305429Swnj else { 5315429Swnj struct proc *p = pfind(-so->so_pgrp); 5325429Swnj 5335429Swnj if (p) 5345429Swnj psignal(p, SIGURG); 5355429Swnj } 5365423Swnj } 5375423Swnj 5384916Swnj /*ARGSUSED*/ 5397627Ssam soioctl(so, cmd, data) 5404829Swnj register struct socket *so; 5414829Swnj int cmd; 5427627Ssam register char *data; 5434786Swnj { 5444786Swnj 5455358Sroot switch (cmd) { 5464829Swnj 5477627Ssam case FIONBIO: 5487627Ssam if (*(int *)data) 5496214Swnj so->so_state |= SS_NBIO; 5505388Sroot else 5516214Swnj so->so_state &= ~SS_NBIO; 552*8594Sroot break; 5535388Sroot 5547627Ssam case FIOASYNC: 5557627Ssam if (*(int *)data) 5566214Swnj so->so_state |= SS_ASYNC; 5575388Sroot else 5586214Swnj so->so_state &= ~SS_ASYNC; 559*8594Sroot break; 5605388Sroot 5617627Ssam case SIOCSKEEP: 5627627Ssam if (*(int *)data) 5637507Sroot so->so_options &= ~SO_KEEPALIVE; 5647507Sroot else 5657491Ssam so->so_options |= SO_KEEPALIVE; 566*8594Sroot break; 5675388Sroot 5687627Ssam case SIOCGKEEP: 5697627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 570*8594Sroot break; 5715388Sroot 5727627Ssam case SIOCSLINGER: 5737627Ssam so->so_linger = *(int *)data; 5745388Sroot if (so->so_linger) 5755388Sroot so->so_options &= ~SO_DONTLINGER; 5765388Sroot else 5775388Sroot so->so_options |= SO_DONTLINGER; 578*8594Sroot break; 5795388Sroot 5807627Ssam case SIOCGLINGER: 5817627Ssam *(int *)data = so->so_linger; 582*8594Sroot break; 5835388Sroot 5847627Ssam case SIOCSPGRP: 5857627Ssam so->so_pgrp = *(int *)data; 586*8594Sroot break; 5875423Swnj 5887627Ssam case SIOCGPGRP: 5897627Ssam *(int *)data = so->so_pgrp; 590*8594Sroot break; 5917627Ssam 5925281Sroot case SIOCDONE: { 5937627Ssam int flags = *(int *)data; 5947627Ssam 5955388Sroot flags++; 5965281Sroot if (flags & FREAD) { 5975281Sroot int s = splimp(); 5985281Sroot socantrcvmore(so); 5995281Sroot sbflush(&so->so_rcv); 6006140Ssam splx(s); 6015281Sroot } 6025281Sroot if (flags & FWRITE) 6038560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 6048300Sroot (struct mbuf *)0, (struct mbuf *)0, 6058560Sroot (struct socketopt *)0)); 606*8594Sroot break; 6074829Swnj } 6085281Sroot 6095423Swnj case SIOCSENDOOB: { 6107627Ssam char oob = *(char *)data; 6118319Sroot struct mbuf *m = m_get(M_DONTWAIT); 6127627Ssam 613*8594Sroot if (m == 0) 614*8594Sroot return (ENOBUFS); 6158319Sroot m->m_len = 1; 6167627Ssam *mtod(m, char *) = oob; 6178560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 6188560Sroot m, (struct mbuf *)0, (struct socketopt *)0)); 6195281Sroot } 6205423Swnj 6215423Swnj case SIOCRCVOOB: { 6228319Sroot struct mbuf *m = m_get(M_WAIT); 6237627Ssam 624*8594Sroot if (m == 0) 625*8594Sroot return (ENOBUFS); 6268319Sroot *mtod(m, caddr_t) = 0; 6278300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 6288300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6297627Ssam *(char *)data = *mtod(m, char *); 6307627Ssam (void) m_free(m); 631*8594Sroot break; 6325423Swnj } 6335423Swnj 6347627Ssam case SIOCATMARK: 6357627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 636*8594Sroot break; 6376355Ssam 6386355Ssam /* routing table update calls */ 6396355Ssam case SIOCADDRT: 6406355Ssam case SIOCDELRT: 6416355Ssam if (!suser()) 6428560Sroot return (u.u_error); /* XXX */ 6438560Sroot return (rtrequest(cmd, (struct rtentry *)data)); 6446355Ssam 6455445Swnj /* type/protocol specific ioctls */ 646*8594Sroot default: 647*8594Sroot return (ENOTTY); 6485423Swnj } 649*8594Sroot return (0); 6504786Swnj } 651