1*8319Sroot /* uipc_socket.c 4.51 82/10/05 */ 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" 175095Swnj #include "../net/in.h" 185095Swnj #include "../net/in_systm.h" 196355Ssam #include "../net/route.h" 207747Sroot #include "../h/uio.h" 214786Swnj 224786Swnj /* 238300Sroot * Socket operation routines. 248300Sroot * These routines are called by the routines in 258300Sroot * sys_socket.c or from a system process, and 268300Sroot * implement the semantics of socket operations by 278300Sroot * switching out to the protocol specific routines. 284786Swnj */ 294786Swnj 308300Sroot socreate(dom, aso, type, proto, opt) 314786Swnj struct socket **aso; 328300Sroot int type, proto; 338300Sroot struct socketopt *opt; 344786Swnj { 354786Swnj register struct protosw *prp; 364786Swnj register struct socket *so; 374786Swnj struct mbuf *m; 388300Sroot int pf, error; 394786Swnj 408300Sroot pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ 414890Swnj if (proto) 424890Swnj prp = pffindproto(pf, proto); 434890Swnj else 444890Swnj prp = pffindtype(pf, type); 454890Swnj if (prp == 0) 464890Swnj return (EPROTONOSUPPORT); 478300Sroot if (prp->pr_type != type) 488300Sroot return (EPROTOTYPE); 494890Swnj m = m_getclr(M_WAIT); 504786Swnj if (m == 0) 514786Swnj return (ENOBUFS); 524786Swnj so = mtod(m, struct socket *); 538300Sroot so->so_options = 0; 546214Swnj so->so_state = 0; 556214Swnj if (u.u_uid == 0) 566214Swnj so->so_state = SS_PRIV; 574786Swnj so->so_proto = prp; 588300Sroot error = (*prp->pr_usrreq)(so, PRU_ATTACH, 598300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 604979Swnj if (error) { 617507Sroot so->so_state |= SS_NOFDREF; 627180Swnj sofree(so); 634890Swnj return (error); 644786Swnj } 654786Swnj *aso = so; 664786Swnj return (0); 674786Swnj } 684786Swnj 698300Sroot sobind(so, nam, opt) 708300Sroot struct socket *so; 718300Sroot struct mbuf *nam; 728300Sroot struct socketopt *opt; 738300Sroot { 748300Sroot int s = splnet(); 758300Sroot int error; 768300Sroot 778300Sroot error = 788300Sroot (*so->so_proto->pr_usrreq)(so, PRU_BIND, 798300Sroot (struct mbuf *)0, nam, opt); 808300Sroot splx(s); 818300Sroot return (error); 828300Sroot } 838300Sroot 848300Sroot solisten(so, backlog) 858300Sroot struct socket *so; 868300Sroot int backlog; 878300Sroot { 888300Sroot int s = splnet(); 898300Sroot int error; 908300Sroot 918300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 928300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 938300Sroot if (error) { 948300Sroot splx(s); 958300Sroot return (error); 968300Sroot } 978300Sroot if (so->so_q == 0) { 988300Sroot so->so_q = so; 998300Sroot so->so_q0 = so; 1008300Sroot so->so_options |= SO_ACCEPTCONN; 1018300Sroot } 1028300Sroot if (backlog < 0) 1038300Sroot backlog = 0; 1048300Sroot so->so_qlimit = backlog < 5 ? backlog : 5; 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 */ 1354829Swnj 1367507Sroot if (so->so_options & SO_ACCEPTCONN) { 1377507Sroot while (so->so_q0 != so) 1387507Sroot soclose(so->so_q0, 1); 1397507Sroot while (so->so_q != so) 1407507Sroot 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) { 1484927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1494890Swnj if (u.u_error) { 1505580Sroot if (exiting) 1515580Sroot goto drop; 1524890Swnj splx(s); 1534890Swnj return; 1544890Swnj } 1554890Swnj } 1565388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1575281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1586214Swnj (so->so_state & SS_NBIO) && 1595580Sroot exiting == 0) { 1605281Sroot u.u_error = EINPROGRESS; 1615281Sroot splx(s); 1625281Sroot return; 1635281Sroot } 1645580Sroot /* should use tsleep here, for at most linger */ 1655281Sroot while (so->so_state & SS_ISCONNECTED) 1665281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1674890Swnj } 1684890Swnj } 1695580Sroot drop: 1706880Ssam if (so->so_pcb) { 1718300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1728300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 1736880Ssam if (exiting == 0 && u.u_error) { 1746880Ssam splx(s); 1756880Ssam return; 1766880Ssam } 1776880Ssam } 1784890Swnj discard: 1797507Sroot so->so_state |= SS_NOFDREF; 1804950Swnj sofree(so); 1814890Swnj splx(s); 1824829Swnj } 1834829Swnj 1844916Swnj /*ARGSUSED*/ 1854890Swnj sostat(so, sb) 1864829Swnj struct socket *so; 1874890Swnj struct stat *sb; 1884829Swnj { 1894829Swnj 1905303Sroot bzero((caddr_t)sb, 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 */ 257*8319Sroot sosend(so, nam, uio, flags) 2584786Swnj register struct socket *so; 2598300Sroot struct mbuf *nam; 2607827Sroot struct uio *uio; 261*8319Sroot int flags; 2624786Swnj { 2634890Swnj struct mbuf *top = 0; 2644890Swnj register struct mbuf *m, **mp = ⊤ 2654916Swnj register u_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) { 294*8319Sroot error = (*so->so_proto->pr_usrreq)(so, 295*8319Sroot (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 } 308*8319Sroot if (flags & SOF_OOB) 309*8319Sroot space = 1024; 310*8319Sroot else { 311*8319Sroot space = sbspace(&so->so_snd); 312*8319Sroot if (space <= 0 || 313*8319Sroot sosendallatonce(so) && space < uio->uio_resid) { 314*8319Sroot if (so->so_state & SS_NBIO) 315*8319Sroot snderr(EWOULDBLOCK); 316*8319Sroot sbunlock(&so->so_snd); 317*8319Sroot sbwait(&so->so_snd); 318*8319Sroot splx(s); 319*8319Sroot goto restart; 320*8319Sroot } 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 } 3497827Sroot uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3504890Swnj m->m_len = len; 3514890Swnj *mp = m; 3524890Swnj mp = &m->m_next; 353*8319Sroot if (flags & SOF_OOB) 354*8319Sroot space -= len; 355*8319Sroot else 356*8319Sroot 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 367*8319Sroot soreceive(so, aname, uio, flags) 3684786Swnj register struct socket *so; 3698300Sroot struct mbuf **aname; 3707747Sroot struct uio *uio; 371*8319Sroot int flags; 3724786Swnj { 3737747Sroot register struct iovec *iov; 3744786Swnj register struct mbuf *m, *n; 3754916Swnj u_int len; 376*8319Sroot int eor, s, error = 0, moff, tomark; 3774786Swnj 378*8319Sroot if (flags & SOF_OOB) { 379*8319Sroot struct mbuf *m = m_get(M_WAIT); 380*8319Sroot 381*8319Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 382*8319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 383*8319Sroot len = uio->uio_resid; 384*8319Sroot do { 385*8319Sroot if (len > m->m_len) 386*8319Sroot len = m->m_len; 387*8319Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 388*8319Sroot m = m_free(m); 389*8319Sroot } while (uio->uio_resid && u.u_error == 0 && m); 390*8319Sroot if (m) 391*8319Sroot (void) m_freem(m); 392*8319Sroot return; 393*8319Sroot } 394*8319Sroot 3954890Swnj restart: 3964890Swnj sblock(&so->so_rcv); 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"); 4255039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 426*8319Sroot if ((flags & SOF_PREVIEW) == 0) { 427*8319Sroot so->so_rcv.sb_cc -= m->m_len; 428*8319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 429*8319Sroot } 4308300Sroot if (aname) { 431*8319Sroot if (flags & SOF_PREVIEW) 432*8319Sroot *aname = m_copy(m, 0, m->m_len); 433*8319Sroot else 434*8319Sroot *aname = m; 4358300Sroot m = m->m_next; 4368300Sroot (*aname)->m_next = 0; 4378300Sroot } else 438*8319Sroot if (flags & SOF_PREVIEW) 439*8319Sroot m = m->m_next; 440*8319Sroot else 441*8319Sroot m = m_free(m); 4424890Swnj if (m == 0) 4434890Swnj panic("receive 2"); 4444890Swnj } 4454786Swnj eor = 0; 446*8319Sroot moff = 0; 447*8319Sroot tomark = so->so_oobmark; 4484786Swnj do { 4497827Sroot if (uio->uio_resid <= 0) 4507747Sroot break; 4517827Sroot len = uio->uio_resid; 4527747Sroot so->so_state &= ~SS_RCVATMARK; 453*8319Sroot if (tomark && len > tomark) 454*8319Sroot len = tomark; 455*8319Sroot if (len > m->m_len - moff) 456*8319Sroot len = m->m_len - moff; 4574786Swnj splx(s); 458*8319Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4594786Swnj s = splnet(); 4604786Swnj if (len == m->m_len) { 4616091Sroot eor = (int)m->m_act; 462*8319Sroot if (flags & SOF_PREVIEW) 463*8319Sroot m = m->m_next; 464*8319Sroot else { 465*8319Sroot sbfree(&so->so_rcv, m); 466*8319Sroot MFREE(m, n); 467*8319Sroot m = n; 468*8319Sroot } 469*8319Sroot moff = 0; 4704786Swnj } else { 471*8319Sroot if (flags & SOF_PREVIEW) 472*8319Sroot moff += len; 473*8319Sroot else { 474*8319Sroot m->m_off += len; 475*8319Sroot m->m_len -= len; 476*8319Sroot so->so_rcv.sb_cc -= len; 477*8319Sroot } 4784786Swnj } 479*8319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4807747Sroot so->so_oobmark -= len; 4817747Sroot if (so->so_oobmark == 0) { 4827747Sroot so->so_state |= SS_RCVATMARK; 4837747Sroot break; 4847747Sroot } 4857747Sroot } 486*8319Sroot if (tomark) { 487*8319Sroot tomark -= len; 488*8319Sroot if (tomark == 0) 489*8319Sroot break; 490*8319Sroot } 491*8319Sroot } while (m && !eor); 492*8319Sroot if (flags & SOF_PREVIEW) 493*8319Sroot goto release; 494*8319Sroot so->so_rcv.sb_mb = m; 4954786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4964786Swnj do { 4974786Swnj if (m == 0) 4984890Swnj panic("receive 3"); 4994890Swnj sbfree(&so->so_rcv, m); 5004786Swnj eor = (int)m->m_act; 5014786Swnj so->so_rcv.sb_mb = m->m_next; 5024786Swnj MFREE(m, n); 5034890Swnj m = n; 5044786Swnj } while (eor == 0); 5054890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5068300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5078300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5084890Swnj release: 5094916Swnj sbunlock(&so->so_rcv); 5104890Swnj splx(s); 5114916Swnj return (error); 5124786Swnj } 5134786Swnj 5145423Swnj sohasoutofband(so) 5155423Swnj struct socket *so; 5165423Swnj { 5175423Swnj 5185423Swnj if (so->so_pgrp == 0) 5195423Swnj return; 5205423Swnj if (so->so_pgrp > 0) 5215423Swnj gsignal(so->so_pgrp, SIGURG); 5225429Swnj else { 5235429Swnj struct proc *p = pfind(-so->so_pgrp); 5245429Swnj 5255429Swnj if (p) 5265429Swnj psignal(p, SIGURG); 5275429Swnj } 5285423Swnj } 5295423Swnj 5304916Swnj /*ARGSUSED*/ 5317627Ssam soioctl(so, cmd, data) 5324829Swnj register struct socket *so; 5334829Swnj int cmd; 5347627Ssam register char *data; 5354786Swnj { 5364786Swnj 5375358Sroot switch (cmd) { 5384829Swnj 5397627Ssam case FIONBIO: 5407627Ssam if (*(int *)data) 5416214Swnj so->so_state |= SS_NBIO; 5425388Sroot else 5436214Swnj so->so_state &= ~SS_NBIO; 5445388Sroot return; 5455388Sroot 5467627Ssam case FIOASYNC: 5477627Ssam if (*(int *)data) 5486214Swnj so->so_state |= SS_ASYNC; 5495388Sroot else 5506214Swnj so->so_state &= ~SS_ASYNC; 5515388Sroot return; 5525388Sroot 5537627Ssam case SIOCSKEEP: 5547627Ssam if (*(int *)data) 5557507Sroot so->so_options &= ~SO_KEEPALIVE; 5567507Sroot else 5577491Ssam so->so_options |= SO_KEEPALIVE; 5585388Sroot return; 5595388Sroot 5607627Ssam case SIOCGKEEP: 5617627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5625388Sroot return; 5635388Sroot 5647627Ssam case SIOCSLINGER: 5657627Ssam so->so_linger = *(int *)data; 5665388Sroot if (so->so_linger) 5675388Sroot so->so_options &= ~SO_DONTLINGER; 5685388Sroot else 5695388Sroot so->so_options |= SO_DONTLINGER; 5705388Sroot return; 5715388Sroot 5727627Ssam case SIOCGLINGER: 5737627Ssam *(int *)data = so->so_linger; 5745423Swnj return; 5755388Sroot 5767627Ssam case SIOCSPGRP: 5777627Ssam so->so_pgrp = *(int *)data; 5787627Ssam return; 5795423Swnj 5807627Ssam case SIOCGPGRP: 5817627Ssam *(int *)data = so->so_pgrp; 5827627Ssam return; 5837627Ssam 5845281Sroot case SIOCDONE: { 5857627Ssam int flags = *(int *)data; 5867627Ssam 5875388Sroot flags++; 5885281Sroot if (flags & FREAD) { 5895281Sroot int s = splimp(); 5905281Sroot socantrcvmore(so); 5915281Sroot sbflush(&so->so_rcv); 5926140Ssam splx(s); 5935281Sroot } 5945281Sroot if (flags & FWRITE) 5958300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 5968300Sroot (struct mbuf *)0, (struct mbuf *)0, 5978300Sroot (struct socketopt *)0); 5985281Sroot return; 5994829Swnj } 6005281Sroot 6015423Swnj case SIOCSENDOOB: { 6027627Ssam char oob = *(char *)data; 603*8319Sroot struct mbuf *m = m_get(M_DONTWAIT); 6047627Ssam 6055423Swnj if (m == 0) { 6065423Swnj u.u_error = ENOBUFS; 6075423Swnj return; 6085423Swnj } 609*8319Sroot m->m_len = 1; 6107627Ssam *mtod(m, char *) = oob; 6118300Sroot (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 6128300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6135423Swnj return; 6145281Sroot } 6155423Swnj 6165423Swnj case SIOCRCVOOB: { 617*8319Sroot struct mbuf *m = m_get(M_WAIT); 6187627Ssam 6195423Swnj if (m == 0) { 6205423Swnj u.u_error = ENOBUFS; 6215423Swnj return; 6225423Swnj } 623*8319Sroot *mtod(m, caddr_t) = 0; 6248300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 6258300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6267627Ssam *(char *)data = *mtod(m, char *); 6277627Ssam (void) m_free(m); 6285423Swnj return; 6295423Swnj } 6305423Swnj 6317627Ssam case SIOCATMARK: 6327627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6335423Swnj return; 6346355Ssam 6356355Ssam /* routing table update calls */ 6366355Ssam case SIOCADDRT: 6376355Ssam case SIOCDELRT: 6386355Ssam if (!suser()) 6396355Ssam return; 6407627Ssam u.u_error = rtrequest(cmd, (struct rtentry *)data); 6416355Ssam return; 6426355Ssam 6435445Swnj /* type/protocol specific ioctls */ 6445423Swnj } 6455445Swnj u.u_error = EOPNOTSUPP; 6464786Swnj } 647