1*9026Sroot /* uipc_socket.c 4.63 82/11/02 */ 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 */ 1348713Sroot int error; 1354829Swnj 1367507Sroot if (so->so_options & SO_ACCEPTCONN) { 1377507Sroot while (so->so_q0 != so) 1388713Sroot (void) soclose(so->so_q0, 1); 1397507Sroot while (so->so_q != so) 1408713Sroot (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) { 1488725Sroot error = sodisconnect(so, (struct mbuf *)0); 1498713Sroot if (error) { 1505580Sroot if (exiting) 1515580Sroot goto drop; 1524890Swnj splx(s); 1538713Sroot 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) && 1598713Sroot exiting == 0) 1608713Sroot 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) { 1688713Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1698300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 1708713Sroot if (exiting == 0 && error) { 1716880Ssam splx(s); 1728713Sroot return (error); 1736880Ssam } 1746880Ssam } 1754890Swnj discard: 1767507Sroot so->so_state |= SS_NOFDREF; 1774950Swnj sofree(so); 1784890Swnj splx(s); 1798713Sroot return (0); 1804829Swnj } 1814829Swnj 1824916Swnj /*ARGSUSED*/ 183*9026Sroot sostat(so, ub) 1844829Swnj struct socket *so; 185*9026Sroot struct stat *ub; 1864829Swnj { 187*9026Sroot struct stat sb; 1884829Swnj 189*9026Sroot bzero((caddr_t)&sb, sizeof (sb)); /* XXX */ 1908963Sroot copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */ 1915303Sroot return (0); /* XXX */ 1924829Swnj } 1934829Swnj 1948300Sroot soaccept(so, nam, opt) 1954927Swnj struct socket *so; 1968300Sroot struct mbuf *nam; 1978300Sroot struct socketopt *opt; 1984927Swnj { 1994927Swnj int s = splnet(); 2004927Swnj int error; 2014927Swnj 2028300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 2038300Sroot (struct mbuf *)0, nam, opt); 2044927Swnj splx(s); 2054927Swnj return (error); 2064927Swnj } 2074927Swnj 2088300Sroot soconnect(so, nam, opt) 2094786Swnj struct socket *so; 2108300Sroot struct mbuf *nam; 2118300Sroot struct socketopt *opt; 2124786Swnj { 2134890Swnj int s = splnet(); 2144890Swnj int error; 2154786Swnj 2164890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2174890Swnj error = EISCONN; 2184890Swnj goto bad; 2194890Swnj } 2208300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 2218300Sroot (struct mbuf *)0, nam, opt); 2224890Swnj bad: 2234890Swnj splx(s); 2244890Swnj return (error); 2254786Swnj } 2264786Swnj 2278300Sroot sodisconnect(so, nam) 2284786Swnj struct socket *so; 2298300Sroot struct mbuf *nam; 2304786Swnj { 2314890Swnj int s = splnet(); 2324890Swnj int error; 2334786Swnj 2344890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2354890Swnj error = ENOTCONN; 2364890Swnj goto bad; 2374890Swnj } 2384890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2394890Swnj error = EALREADY; 2404890Swnj goto bad; 2414890Swnj } 2428300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 2438300Sroot (struct mbuf *)0, nam, (struct socketopt *)0); 2444890Swnj bad: 2454890Swnj splx(s); 2464890Swnj return (error); 2474786Swnj } 2484786Swnj 2494786Swnj /* 2504890Swnj * Send on a socket. 2514890Swnj * If send must go all at once and message is larger than 2524890Swnj * send buffering, then hard error. 2534890Swnj * Lock against other senders. 2544890Swnj * If must go all at once and not enough room now, then 2554890Swnj * inform user that this would block and do nothing. 2564786Swnj */ 2578319Sroot sosend(so, nam, uio, flags) 2584786Swnj register struct socket *so; 2598300Sroot struct mbuf *nam; 2607827Sroot struct uio *uio; 2618319Sroot int flags; 2624786Swnj { 2634890Swnj struct mbuf *top = 0; 2644890Swnj register struct mbuf *m, **mp = ⊤ 2658713Sroot register int len; 2664916Swnj int error = 0, space, s; 2674786Swnj 2687827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2694890Swnj return (EMSGSIZE); 2706419Sroot restart: 2714890Swnj sblock(&so->so_snd); 2724890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2734890Swnj 2748041Sroot u.u_ru.ru_msgsnd++; 2756419Sroot again: 2764890Swnj s = splnet(); 2776419Sroot if (so->so_state & SS_CANTSENDMORE) { 2786419Sroot psignal(u.u_procp, SIGPIPE); 2796419Sroot snderr(EPIPE); 2806419Sroot } 2815168Swnj if (so->so_error) { 2825168Swnj error = so->so_error; 2836419Sroot so->so_error = 0; /* ??? */ 2845168Swnj splx(s); 2855168Swnj goto release; 2865168Swnj } 2874890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2884890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2894890Swnj snderr(ENOTCONN); 2908300Sroot if (nam == 0) 2914890Swnj snderr(EDESTADDRREQ); 2924890Swnj } 2934890Swnj if (top) { 2948319Sroot error = (*so->so_proto->pr_usrreq)(so, 2958319Sroot (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 2968300Sroot top, (caddr_t)nam, (struct socketopt *)0); 2976419Sroot top = 0; 2984890Swnj if (error) { 2994890Swnj splx(s); 3004786Swnj goto release; 3014786Swnj } 3024890Swnj mp = ⊤ 3034786Swnj } 3047827Sroot if (uio->uio_resid == 0) { 3054979Swnj splx(s); 3064979Swnj goto release; 3074979Swnj } 3088319Sroot if (flags & SOF_OOB) 3098319Sroot space = 1024; 3108319Sroot else { 3118319Sroot space = sbspace(&so->so_snd); 3128319Sroot if (space <= 0 || 3138319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3148319Sroot if (so->so_state & SS_NBIO) 3158319Sroot snderr(EWOULDBLOCK); 3168319Sroot sbunlock(&so->so_snd); 3178319Sroot sbwait(&so->so_snd); 3188319Sroot splx(s); 3198319Sroot goto restart; 3208319Sroot } 3214786Swnj } 3224890Swnj splx(s); 3237827Sroot while (uio->uio_resid > 0 && space > 0) { 3247827Sroot register struct iovec *iov = uio->uio_iov; 3257827Sroot 3267827Sroot if (iov->iov_len == 0) { 3277827Sroot uio->uio_iov++; 3287827Sroot uio->uio_iovcnt--; 3297827Sroot if (uio->uio_iovcnt < 0) 3307827Sroot panic("sosend"); 3317827Sroot continue; 3327827Sroot } 3334890Swnj MGET(m, 1); 3344890Swnj if (m == NULL) { 3356419Sroot error = ENOBUFS; /* SIGPIPE? */ 3364890Swnj goto release; 3374786Swnj } 3387827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3394890Swnj register struct mbuf *p; 3405095Swnj MCLGET(p, 1); 3414890Swnj if (p == 0) 3424890Swnj goto nopages; 3434890Swnj m->m_off = (int)p - (int)m; 3445095Swnj len = CLBYTES; 3454890Swnj } else { 3464786Swnj nopages: 3477827Sroot len = MIN(MLEN, iov->iov_len); 3484786Swnj } 3498771Sroot (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3504890Swnj m->m_len = len; 3514890Swnj *mp = m; 3524890Swnj mp = &m->m_next; 3538319Sroot if (flags & SOF_OOB) 3548319Sroot space -= len; 3558319Sroot else 3568319Sroot space = sbspace(&so->so_snd); 3574786Swnj } 3584890Swnj goto again; 3594890Swnj 3604786Swnj release: 3614890Swnj sbunlock(&so->so_snd); 3626419Sroot if (top) 3636419Sroot m_freem(top); 3644786Swnj return (error); 3654786Swnj } 3664786Swnj 3678319Sroot soreceive(so, aname, uio, flags) 3684786Swnj register struct socket *so; 3698300Sroot struct mbuf **aname; 3707747Sroot struct uio *uio; 3718319Sroot int flags; 3724786Swnj { 3734786Swnj register struct mbuf *m, *n; 3748713Sroot int len; 3758319Sroot int eor, s, error = 0, moff, tomark; 3764786Swnj 3778319Sroot if (flags & SOF_OOB) { 3788594Sroot m = m_get(M_WAIT); 3798594Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 3808319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 3818594Sroot if (error) 3828713Sroot return (error); 3838319Sroot len = uio->uio_resid; 3848319Sroot do { 3858319Sroot if (len > m->m_len) 3868319Sroot len = m->m_len; 3878594Sroot error = 3888793Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 3898319Sroot m = m_free(m); 3908594Sroot } while (uio->uio_resid && error == 0 && m); 3918319Sroot if (m) 3928771Sroot m_freem(m); 3938594Sroot return (error); 3948319Sroot } 3958319Sroot 3964890Swnj restart: 3974890Swnj sblock(&so->so_rcv); 3988835Sroot s = splnet(); 3998552Sroot SBCHECK(&so->so_rcv, "soreceive restart"); 4004890Swnj 4014890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4024786Swnj if (so->so_rcv.sb_cc == 0) { 4035168Swnj if (so->so_error) { 4045168Swnj error = so->so_error; 4055168Swnj so->so_error = 0; 4065168Swnj splx(s); 4075168Swnj goto release; 4085168Swnj } 4094890Swnj if (so->so_state & SS_CANTRCVMORE) { 4104890Swnj splx(s); 4114890Swnj goto release; 4124890Swnj } 4135015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4145015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4155015Sroot rcverr(ENOTCONN); 4166214Swnj if (so->so_state & SS_NBIO) 4175168Swnj rcverr(EWOULDBLOCK); 4184890Swnj sbunlock(&so->so_rcv); 4194971Swnj sbwait(&so->so_rcv); 4205012Swnj splx(s); 4214890Swnj goto restart; 4224786Swnj } 4238041Sroot u.u_ru.ru_msgrcv++; 4244829Swnj m = so->so_rcv.sb_mb; 4254786Swnj if (m == 0) 4264786Swnj panic("receive"); 4278548Sroot SBCHECK(&so->so_snd, "soreceive havecc"); 4285039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4298319Sroot if ((flags & SOF_PREVIEW) == 0) { 4308319Sroot so->so_rcv.sb_cc -= m->m_len; 4318319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4328319Sroot } 4338300Sroot if (aname) { 4348319Sroot if (flags & SOF_PREVIEW) 4358319Sroot *aname = m_copy(m, 0, m->m_len); 4368319Sroot else 4378319Sroot *aname = m; 4388300Sroot m = m->m_next; 4398300Sroot (*aname)->m_next = 0; 4408300Sroot } else 4418319Sroot if (flags & SOF_PREVIEW) 4428319Sroot m = m->m_next; 4438319Sroot else 4448319Sroot m = m_free(m); 4454890Swnj if (m == 0) 4464890Swnj panic("receive 2"); 4478548Sroot if ((flags & SOF_PREVIEW) == 0) 4488548Sroot so->so_rcv.sb_mb = m; 4498548Sroot SBCHECK(&so->so_snd, "soreceive afteraddr"); 4504890Swnj } 4514786Swnj eor = 0; 4528319Sroot moff = 0; 4538319Sroot tomark = so->so_oobmark; 4544786Swnj do { 4557827Sroot if (uio->uio_resid <= 0) 4567747Sroot break; 4577827Sroot len = uio->uio_resid; 4587747Sroot so->so_state &= ~SS_RCVATMARK; 4598319Sroot if (tomark && len > tomark) 4608319Sroot len = tomark; 4618548Sroot if (moff+len > m->m_len - moff) 4628319Sroot len = m->m_len - moff; 4634786Swnj splx(s); 4648594Sroot error = 4658793Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4664786Swnj s = splnet(); 4674786Swnj if (len == m->m_len) { 4686091Sroot eor = (int)m->m_act; 4698319Sroot if (flags & SOF_PREVIEW) 4708319Sroot m = m->m_next; 4718319Sroot else { 4728319Sroot sbfree(&so->so_rcv, m); 4738319Sroot MFREE(m, n); 4748319Sroot m = n; 4758548Sroot so->so_rcv.sb_mb = m; 4768319Sroot } 4778319Sroot moff = 0; 4784786Swnj } else { 4798319Sroot if (flags & SOF_PREVIEW) 4808319Sroot moff += len; 4818319Sroot else { 4828319Sroot m->m_off += len; 4838319Sroot m->m_len -= len; 4848319Sroot so->so_rcv.sb_cc -= len; 4858319Sroot } 4864786Swnj } 4878319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4887747Sroot so->so_oobmark -= len; 4897747Sroot if (so->so_oobmark == 0) { 4907747Sroot so->so_state |= SS_RCVATMARK; 4917747Sroot break; 4927747Sroot } 4937747Sroot } 4948319Sroot if (tomark) { 4958319Sroot tomark -= len; 4968319Sroot if (tomark == 0) 4978319Sroot break; 4988319Sroot } 4998548Sroot SBCHECK(&so->so_snd, "soreceive rcvloop"); 5008594Sroot } while (m && error == 0 && !eor); 5018319Sroot if (flags & SOF_PREVIEW) 5028319Sroot goto release; 5034786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5044786Swnj do { 5054786Swnj if (m == 0) 5064890Swnj panic("receive 3"); 5074890Swnj sbfree(&so->so_rcv, m); 5084786Swnj eor = (int)m->m_act; 5094786Swnj so->so_rcv.sb_mb = m->m_next; 5104786Swnj MFREE(m, n); 5114890Swnj m = n; 5128548Sroot SBCHECK(&so->so_snd, "soreceive atomicloop"); 5134786Swnj } while (eor == 0); 5144890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5158300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5168300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5174890Swnj release: 5184916Swnj sbunlock(&so->so_rcv); 5194890Swnj splx(s); 5204916Swnj return (error); 5214786Swnj } 5224786Swnj 5235423Swnj sohasoutofband(so) 5245423Swnj struct socket *so; 5255423Swnj { 5265423Swnj 5275423Swnj if (so->so_pgrp == 0) 5285423Swnj return; 5295423Swnj if (so->so_pgrp > 0) 5305423Swnj gsignal(so->so_pgrp, SIGURG); 5315429Swnj else { 5325429Swnj struct proc *p = pfind(-so->so_pgrp); 5335429Swnj 5345429Swnj if (p) 5355429Swnj psignal(p, SIGURG); 5365429Swnj } 5375423Swnj } 5385423Swnj 5394916Swnj /*ARGSUSED*/ 5407627Ssam soioctl(so, cmd, data) 5414829Swnj register struct socket *so; 5424829Swnj int cmd; 5437627Ssam register char *data; 5444786Swnj { 5454786Swnj 5465358Sroot switch (cmd) { 5474829Swnj 5487627Ssam case FIONBIO: 5497627Ssam if (*(int *)data) 5506214Swnj so->so_state |= SS_NBIO; 5515388Sroot else 5526214Swnj so->so_state &= ~SS_NBIO; 5538594Sroot break; 5545388Sroot 5557627Ssam case FIOASYNC: 5567627Ssam if (*(int *)data) 5576214Swnj so->so_state |= SS_ASYNC; 5585388Sroot else 5596214Swnj so->so_state &= ~SS_ASYNC; 5608594Sroot break; 5615388Sroot 5627627Ssam case SIOCSKEEP: 5637627Ssam if (*(int *)data) 5647507Sroot so->so_options &= ~SO_KEEPALIVE; 5657507Sroot else 5667491Ssam so->so_options |= SO_KEEPALIVE; 5678594Sroot break; 5685388Sroot 5697627Ssam case SIOCGKEEP: 5707627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5718594Sroot break; 5725388Sroot 5737627Ssam case SIOCSLINGER: 5747627Ssam so->so_linger = *(int *)data; 5755388Sroot if (so->so_linger) 5765388Sroot so->so_options &= ~SO_DONTLINGER; 5775388Sroot else 5785388Sroot so->so_options |= SO_DONTLINGER; 5798594Sroot break; 5805388Sroot 5817627Ssam case SIOCGLINGER: 5827627Ssam *(int *)data = so->so_linger; 5838594Sroot break; 5845388Sroot 5857627Ssam case SIOCSPGRP: 5867627Ssam so->so_pgrp = *(int *)data; 5878594Sroot break; 5885423Swnj 5897627Ssam case SIOCGPGRP: 5907627Ssam *(int *)data = so->so_pgrp; 5918594Sroot break; 5927627Ssam 5935281Sroot case SIOCDONE: { 5947627Ssam int flags = *(int *)data; 5957627Ssam 5965388Sroot flags++; 5975281Sroot if (flags & FREAD) { 5985281Sroot int s = splimp(); 5995281Sroot socantrcvmore(so); 6005281Sroot sbflush(&so->so_rcv); 6016140Ssam splx(s); 6025281Sroot } 6035281Sroot if (flags & FWRITE) 6048560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 6058300Sroot (struct mbuf *)0, (struct mbuf *)0, 6068560Sroot (struct socketopt *)0)); 6078594Sroot break; 6084829Swnj } 6095281Sroot 6105423Swnj case SIOCSENDOOB: { 6117627Ssam char oob = *(char *)data; 6128319Sroot struct mbuf *m = m_get(M_DONTWAIT); 6137627Ssam 6148594Sroot if (m == 0) 6158594Sroot return (ENOBUFS); 6168319Sroot m->m_len = 1; 6177627Ssam *mtod(m, char *) = oob; 6188560Sroot return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 6198560Sroot m, (struct mbuf *)0, (struct socketopt *)0)); 6205281Sroot } 6215423Swnj 6225423Swnj case SIOCRCVOOB: { 6238319Sroot struct mbuf *m = m_get(M_WAIT); 6247627Ssam 6258594Sroot if (m == 0) 6268594Sroot return (ENOBUFS); 6278319Sroot *mtod(m, caddr_t) = 0; 6288300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 6298300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6307627Ssam *(char *)data = *mtod(m, char *); 6317627Ssam (void) m_free(m); 6328594Sroot break; 6335423Swnj } 6345423Swnj 6357627Ssam case SIOCATMARK: 6367627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6378594Sroot break; 6386355Ssam 6396355Ssam /* routing table update calls */ 6406355Ssam case SIOCADDRT: 6416355Ssam case SIOCDELRT: 6426355Ssam if (!suser()) 6438560Sroot return (u.u_error); /* XXX */ 6448560Sroot return (rtrequest(cmd, (struct rtentry *)data)); 6456355Ssam 6465445Swnj /* type/protocol specific ioctls */ 6478594Sroot default: 6488594Sroot return (ENOTTY); 6495423Swnj } 6508594Sroot return (0); 6514786Swnj } 652