1*10137Ssam /* uipc_socket.c 4.67 83/01/04 */ 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; 379168Ssam int error; 384786Swnj 394890Swnj if (proto) 409168Ssam prp = pffindproto(dom, proto); 414890Swnj else 429168Ssam prp = pffindtype(dom, type); 434890Swnj if (prp == 0) 444890Swnj return (EPROTONOSUPPORT); 458300Sroot if (prp->pr_type != type) 468300Sroot return (EPROTOTYPE); 479635Ssam m = m_getclr(M_WAIT, MT_SOCKET); 484786Swnj if (m == 0) 494786Swnj return (ENOBUFS); 504786Swnj so = mtod(m, struct socket *); 518300Sroot so->so_options = 0; 526214Swnj so->so_state = 0; 539168Ssam so->so_type = type; 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, 58*10137Ssam (struct mbuf *)0, (struct mbuf *)0, opt); 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; 103*10137Ssam #define SOMAXCONN 5 104*10137Ssam so->so_qlimit = MIN(backlog, SOMAXCONN); 1058300Sroot so->so_options |= SO_NEWFDONCONN; 1068300Sroot return (0); 1078300Sroot } 1088300Sroot 1094916Swnj sofree(so) 1104916Swnj struct socket *so; 1114916Swnj { 1124916Swnj 1137507Sroot if (so->so_head) { 1147507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1157507Sroot panic("sofree dq"); 1167507Sroot so->so_head = 0; 1177507Sroot } 1187507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1194950Swnj return; 1204950Swnj sbrelease(&so->so_snd); 1214950Swnj sbrelease(&so->so_rcv); 1224971Swnj (void) m_free(dtom(so)); 1234916Swnj } 1244916Swnj 1254786Swnj /* 1264890Swnj * Close a socket on last file table reference removal. 1274890Swnj * Initiate disconnect if connected. 1284890Swnj * Free socket when disconnect complete. 1294829Swnj */ 1305580Sroot soclose(so, exiting) 1314829Swnj register struct socket *so; 1325580Sroot int exiting; 1334829Swnj { 1344890Swnj int s = splnet(); /* conservative */ 1358713Sroot int error; 1364829Swnj 1377507Sroot if (so->so_options & SO_ACCEPTCONN) { 1387507Sroot while (so->so_q0 != so) 1398713Sroot (void) soclose(so->so_q0, 1); 1407507Sroot while (so->so_q != so) 1418713Sroot (void) soclose(so->so_q, 1); 1427507Sroot } 1434890Swnj if (so->so_pcb == 0) 1444890Swnj goto discard; 1456259Sroot if (exiting) 1466259Sroot so->so_options |= SO_KEEPALIVE; 1474890Swnj if (so->so_state & SS_ISCONNECTED) { 1484890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1498725Sroot error = sodisconnect(so, (struct mbuf *)0); 1508713Sroot if (error) { 1515580Sroot if (exiting) 1525580Sroot goto drop; 1534890Swnj splx(s); 1548713Sroot return (error); 1554890Swnj } 1564890Swnj } 1575388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1585281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1596214Swnj (so->so_state & SS_NBIO) && 1608713Sroot exiting == 0) 1618713Sroot return (EINPROGRESS); 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) { 1698713Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1708300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 1718713Sroot if (exiting == 0 && error) { 1726880Ssam splx(s); 1738713Sroot return (error); 1746880Ssam } 1756880Ssam } 1764890Swnj discard: 1777507Sroot so->so_state |= SS_NOFDREF; 1784950Swnj sofree(so); 1794890Swnj splx(s); 1808713Sroot return (0); 1814829Swnj } 1824829Swnj 1834916Swnj /*ARGSUSED*/ 1849026Sroot sostat(so, ub) 1854829Swnj struct socket *so; 1869026Sroot struct stat *ub; 1874829Swnj { 1889026Sroot struct stat sb; 1894829Swnj 1909026Sroot bzero((caddr_t)&sb, sizeof (sb)); /* XXX */ 1919168Ssam (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */ 1925303Sroot return (0); /* XXX */ 1934829Swnj } 1944829Swnj 1958300Sroot soaccept(so, nam, opt) 1964927Swnj struct socket *so; 1978300Sroot struct mbuf *nam; 1988300Sroot struct socketopt *opt; 1994927Swnj { 2004927Swnj int s = splnet(); 2014927Swnj int error; 2024927Swnj 2038300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 2048300Sroot (struct mbuf *)0, nam, opt); 2054927Swnj splx(s); 2064927Swnj return (error); 2074927Swnj } 2084927Swnj 2098300Sroot soconnect(so, nam, opt) 2104786Swnj struct socket *so; 2118300Sroot struct mbuf *nam; 2128300Sroot struct socketopt *opt; 2134786Swnj { 2144890Swnj int s = splnet(); 2154890Swnj int error; 2164786Swnj 2174890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2184890Swnj error = EISCONN; 2194890Swnj goto bad; 2204890Swnj } 2218300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 2228300Sroot (struct mbuf *)0, nam, opt); 2234890Swnj bad: 2244890Swnj splx(s); 2254890Swnj return (error); 2264786Swnj } 2274786Swnj 2288300Sroot sodisconnect(so, nam) 2294786Swnj struct socket *so; 2308300Sroot struct mbuf *nam; 2314786Swnj { 2324890Swnj int s = splnet(); 2334890Swnj int error; 2344786Swnj 2354890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2364890Swnj error = ENOTCONN; 2374890Swnj goto bad; 2384890Swnj } 2394890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2404890Swnj error = EALREADY; 2414890Swnj goto bad; 2424890Swnj } 2438300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 2448300Sroot (struct mbuf *)0, nam, (struct socketopt *)0); 2454890Swnj bad: 2464890Swnj splx(s); 2474890Swnj return (error); 2484786Swnj } 2494786Swnj 2504786Swnj /* 2514890Swnj * Send on a socket. 2524890Swnj * If send must go all at once and message is larger than 2534890Swnj * send buffering, then hard error. 2544890Swnj * Lock against other senders. 2554890Swnj * If must go all at once and not enough room now, then 2564890Swnj * inform user that this would block and do nothing. 2574786Swnj */ 2588319Sroot sosend(so, nam, uio, flags) 2594786Swnj register struct socket *so; 2608300Sroot struct mbuf *nam; 2617827Sroot struct uio *uio; 2628319Sroot int flags; 2634786Swnj { 2644890Swnj struct mbuf *top = 0; 2654890Swnj register struct mbuf *m, **mp = ⊤ 2668713Sroot register int len; 2674916Swnj int error = 0, space, s; 2684786Swnj 2697827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2704890Swnj return (EMSGSIZE); 2716419Sroot restart: 2724890Swnj sblock(&so->so_snd); 2734890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2744890Swnj 2758041Sroot u.u_ru.ru_msgsnd++; 2766419Sroot again: 2774890Swnj s = splnet(); 2786419Sroot if (so->so_state & SS_CANTSENDMORE) { 2796419Sroot psignal(u.u_procp, SIGPIPE); 2806419Sroot snderr(EPIPE); 2816419Sroot } 2825168Swnj if (so->so_error) { 2835168Swnj error = so->so_error; 2846419Sroot so->so_error = 0; /* ??? */ 2855168Swnj splx(s); 2865168Swnj goto release; 2875168Swnj } 2884890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2894890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2904890Swnj snderr(ENOTCONN); 2918300Sroot if (nam == 0) 2924890Swnj snderr(EDESTADDRREQ); 2934890Swnj } 2944890Swnj if (top) { 2958319Sroot error = (*so->so_proto->pr_usrreq)(so, 2968319Sroot (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 2978300Sroot top, (caddr_t)nam, (struct socketopt *)0); 2986419Sroot top = 0; 2994890Swnj if (error) { 3004890Swnj splx(s); 3014786Swnj goto release; 3024786Swnj } 3034890Swnj mp = ⊤ 3044786Swnj } 3057827Sroot if (uio->uio_resid == 0) { 3064979Swnj splx(s); 3074979Swnj goto release; 3084979Swnj } 3098319Sroot if (flags & SOF_OOB) 3108319Sroot space = 1024; 3118319Sroot else { 3128319Sroot space = sbspace(&so->so_snd); 3138319Sroot if (space <= 0 || 3148319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3158319Sroot if (so->so_state & SS_NBIO) 3168319Sroot snderr(EWOULDBLOCK); 3178319Sroot sbunlock(&so->so_snd); 3188319Sroot sbwait(&so->so_snd); 3198319Sroot splx(s); 3208319Sroot goto restart; 3218319Sroot } 3224786Swnj } 3234890Swnj splx(s); 3247827Sroot while (uio->uio_resid > 0 && space > 0) { 3257827Sroot register struct iovec *iov = uio->uio_iov; 3267827Sroot 3277827Sroot if (iov->iov_len == 0) { 3287827Sroot uio->uio_iov++; 3297827Sroot uio->uio_iovcnt--; 3307827Sroot if (uio->uio_iovcnt < 0) 3317827Sroot panic("sosend"); 3327827Sroot continue; 3337827Sroot } 3349635Ssam MGET(m, M_WAIT, MT_DATA); 3354890Swnj if (m == NULL) { 3366419Sroot error = ENOBUFS; /* SIGPIPE? */ 3374890Swnj goto release; 3384786Swnj } 3397827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3404890Swnj register struct mbuf *p; 3415095Swnj MCLGET(p, 1); 3424890Swnj if (p == 0) 3434890Swnj goto nopages; 3444890Swnj m->m_off = (int)p - (int)m; 3455095Swnj len = CLBYTES; 3464890Swnj } else { 3474786Swnj nopages: 3487827Sroot len = MIN(MLEN, iov->iov_len); 3494786Swnj } 3508771Sroot (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3514890Swnj m->m_len = len; 3524890Swnj *mp = m; 3534890Swnj mp = &m->m_next; 3548319Sroot if (flags & SOF_OOB) 3558319Sroot space -= len; 3568319Sroot else 3578319Sroot space = sbspace(&so->so_snd); 3584786Swnj } 3594890Swnj goto again; 3604890Swnj 3614786Swnj release: 3624890Swnj sbunlock(&so->so_snd); 3636419Sroot if (top) 3646419Sroot m_freem(top); 3654786Swnj return (error); 3664786Swnj } 3674786Swnj 3688319Sroot soreceive(so, aname, uio, flags) 3694786Swnj register struct socket *so; 3708300Sroot struct mbuf **aname; 3717747Sroot struct uio *uio; 3728319Sroot int flags; 3734786Swnj { 3744786Swnj register struct mbuf *m, *n; 3758713Sroot int len; 3768319Sroot int eor, s, error = 0, moff, tomark; 3774786Swnj 3788319Sroot if (flags & SOF_OOB) { 3799635Ssam m = m_get(M_WAIT, MT_DATA); 380*10137Ssam if (m == NULL) 381*10137Ssam return (ENOBUFS); 3828594Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 3838319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 3848594Sroot if (error) 385*10137Ssam goto bad; 3868319Sroot do { 387*10137Ssam len = uio->uio_resid; 3888319Sroot if (len > m->m_len) 3898319Sroot len = m->m_len; 3908594Sroot error = 3918793Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 3928319Sroot m = m_free(m); 3938594Sroot } while (uio->uio_resid && error == 0 && m); 394*10137Ssam bad: 3958319Sroot if (m) 3968771Sroot m_freem(m); 3978594Sroot return (error); 3988319Sroot } 3998319Sroot 4004890Swnj restart: 4014890Swnj sblock(&so->so_rcv); 4028835Sroot s = splnet(); 4034890Swnj 4044890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4054786Swnj if (so->so_rcv.sb_cc == 0) { 4065168Swnj if (so->so_error) { 4075168Swnj error = so->so_error; 4085168Swnj so->so_error = 0; 4095168Swnj splx(s); 4105168Swnj goto release; 4115168Swnj } 4124890Swnj if (so->so_state & SS_CANTRCVMORE) { 4134890Swnj splx(s); 4144890Swnj goto release; 4154890Swnj } 4165015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4175015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4185015Sroot rcverr(ENOTCONN); 4196214Swnj if (so->so_state & SS_NBIO) 4205168Swnj rcverr(EWOULDBLOCK); 4214890Swnj sbunlock(&so->so_rcv); 4224971Swnj sbwait(&so->so_rcv); 4235012Swnj splx(s); 4244890Swnj goto restart; 4254786Swnj } 4268041Sroot u.u_ru.ru_msgrcv++; 4274829Swnj m = so->so_rcv.sb_mb; 4284786Swnj if (m == 0) 4294786Swnj panic("receive"); 4305039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4318319Sroot if ((flags & SOF_PREVIEW) == 0) { 4328319Sroot so->so_rcv.sb_cc -= m->m_len; 4338319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4348319Sroot } 4358300Sroot if (aname) { 436*10137Ssam if (flags & SOF_PREVIEW) { 4378319Sroot *aname = m_copy(m, 0, m->m_len); 438*10137Ssam if (*aname == NULL) 439*10137Ssam panic("receive 2"); 440*10137Ssam } else 4418319Sroot *aname = m; 4428300Sroot m = m->m_next; 4438300Sroot (*aname)->m_next = 0; 4448300Sroot } else 4458319Sroot if (flags & SOF_PREVIEW) 4468319Sroot m = m->m_next; 4478319Sroot else 4488319Sroot m = m_free(m); 4494890Swnj if (m == 0) 450*10137Ssam panic("receive 3"); 4518548Sroot if ((flags & SOF_PREVIEW) == 0) 4528548Sroot so->so_rcv.sb_mb = m; 4534890Swnj } 4544786Swnj eor = 0; 4558319Sroot moff = 0; 4568319Sroot tomark = so->so_oobmark; 4574786Swnj do { 4587827Sroot if (uio->uio_resid <= 0) 4597747Sroot break; 4607827Sroot len = uio->uio_resid; 4617747Sroot so->so_state &= ~SS_RCVATMARK; 4628319Sroot if (tomark && len > tomark) 4638319Sroot len = tomark; 4648548Sroot if (moff+len > m->m_len - moff) 4658319Sroot len = m->m_len - moff; 4664786Swnj splx(s); 4678594Sroot error = 4688793Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4694786Swnj s = splnet(); 4704786Swnj if (len == m->m_len) { 4716091Sroot eor = (int)m->m_act; 4728319Sroot if (flags & SOF_PREVIEW) 4738319Sroot m = m->m_next; 4748319Sroot else { 4758319Sroot sbfree(&so->so_rcv, m); 4768319Sroot MFREE(m, n); 4778319Sroot m = n; 4788548Sroot so->so_rcv.sb_mb = m; 4798319Sroot } 4808319Sroot moff = 0; 4814786Swnj } else { 4828319Sroot if (flags & SOF_PREVIEW) 4838319Sroot moff += len; 4848319Sroot else { 4858319Sroot m->m_off += len; 4868319Sroot m->m_len -= len; 4878319Sroot so->so_rcv.sb_cc -= len; 4888319Sroot } 4894786Swnj } 4908319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4917747Sroot so->so_oobmark -= len; 4927747Sroot if (so->so_oobmark == 0) { 4937747Sroot so->so_state |= SS_RCVATMARK; 4947747Sroot break; 4957747Sroot } 4967747Sroot } 4978319Sroot if (tomark) { 4988319Sroot tomark -= len; 4998319Sroot if (tomark == 0) 5008319Sroot break; 5018319Sroot } 5028594Sroot } while (m && error == 0 && !eor); 5038319Sroot if (flags & SOF_PREVIEW) 5048319Sroot goto release; 5054786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5064786Swnj do { 5074786Swnj if (m == 0) 508*10137Ssam panic("receive 4"); 5094890Swnj sbfree(&so->so_rcv, m); 5104786Swnj eor = (int)m->m_act; 5114786Swnj so->so_rcv.sb_mb = m->m_next; 5124786Swnj MFREE(m, n); 5134890Swnj m = n; 5144786Swnj } while (eor == 0); 5154890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5168300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5178300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5184890Swnj release: 5194916Swnj sbunlock(&so->so_rcv); 5204890Swnj splx(s); 5214916Swnj return (error); 5224786Swnj } 5234786Swnj 5245423Swnj sohasoutofband(so) 5255423Swnj struct socket *so; 5265423Swnj { 5275423Swnj 5285423Swnj if (so->so_pgrp == 0) 5295423Swnj return; 5305423Swnj if (so->so_pgrp > 0) 5315423Swnj gsignal(so->so_pgrp, SIGURG); 5325429Swnj else { 5335429Swnj struct proc *p = pfind(-so->so_pgrp); 5345429Swnj 5355429Swnj if (p) 5365429Swnj psignal(p, SIGURG); 5375429Swnj } 5385423Swnj } 5395423Swnj 5404916Swnj /*ARGSUSED*/ 5417627Ssam soioctl(so, cmd, data) 5424829Swnj register struct socket *so; 5434829Swnj int cmd; 5447627Ssam register char *data; 5454786Swnj { 5464786Swnj 5475358Sroot switch (cmd) { 5484829Swnj 5497627Ssam case FIONBIO: 5507627Ssam if (*(int *)data) 5516214Swnj so->so_state |= SS_NBIO; 5525388Sroot else 5536214Swnj so->so_state &= ~SS_NBIO; 5548594Sroot break; 5555388Sroot 5567627Ssam case FIOASYNC: 5577627Ssam if (*(int *)data) 5586214Swnj so->so_state |= SS_ASYNC; 5595388Sroot else 5606214Swnj so->so_state &= ~SS_ASYNC; 5618594Sroot break; 5625388Sroot 5637627Ssam case SIOCSKEEP: 5647627Ssam if (*(int *)data) 5657507Sroot so->so_options &= ~SO_KEEPALIVE; 5667507Sroot else 5677491Ssam so->so_options |= SO_KEEPALIVE; 5688594Sroot break; 5695388Sroot 5707627Ssam case SIOCGKEEP: 5717627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5728594Sroot break; 5735388Sroot 5747627Ssam case SIOCSLINGER: 5757627Ssam so->so_linger = *(int *)data; 5765388Sroot if (so->so_linger) 5775388Sroot so->so_options &= ~SO_DONTLINGER; 5785388Sroot else 5795388Sroot so->so_options |= SO_DONTLINGER; 5808594Sroot break; 5815388Sroot 5827627Ssam case SIOCGLINGER: 5837627Ssam *(int *)data = so->so_linger; 5848594Sroot break; 5855388Sroot 5867627Ssam case SIOCSPGRP: 5877627Ssam so->so_pgrp = *(int *)data; 5888594Sroot break; 5895423Swnj 5907627Ssam case SIOCGPGRP: 5917627Ssam *(int *)data = so->so_pgrp; 5928594Sroot break; 5937627Ssam 5945281Sroot case SIOCDONE: { 5957627Ssam int flags = *(int *)data; 5967627Ssam 5975388Sroot flags++; 5985281Sroot if (flags & FREAD) { 5995281Sroot int s = splimp(); 6005281Sroot socantrcvmore(so); 6015281Sroot sbflush(&so->so_rcv); 6026140Ssam splx(s); 6035281Sroot } 6045281Sroot if (flags & FWRITE) 6058560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 6068300Sroot (struct mbuf *)0, (struct mbuf *)0, 6078560Sroot (struct socketopt *)0)); 6088594Sroot break; 6094829Swnj } 6105281Sroot 6117627Ssam case SIOCATMARK: 6127627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6138594Sroot break; 6146355Ssam 6156355Ssam /* routing table update calls */ 6166355Ssam case SIOCADDRT: 6176355Ssam case SIOCDELRT: 6186355Ssam if (!suser()) 619*10137Ssam return (u.u_error); 6208560Sroot return (rtrequest(cmd, (struct rtentry *)data)); 6216355Ssam 6225445Swnj /* type/protocol specific ioctls */ 6238594Sroot default: 624*10137Ssam return (ENOTTY); /* XXX */ 6255423Swnj } 6268594Sroot return (0); 6274786Swnj } 628