1*8300Sroot /* uipc_socket.c 4.50 82/10/03 */ 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 /* 23*8300Sroot * Socket operation routines. 24*8300Sroot * These routines are called by the routines in 25*8300Sroot * sys_socket.c or from a system process, and 26*8300Sroot * implement the semantics of socket operations by 27*8300Sroot * switching out to the protocol specific routines. 284786Swnj */ 294786Swnj 30*8300Sroot socreate(dom, aso, type, proto, opt) 314786Swnj struct socket **aso; 32*8300Sroot int type, proto; 33*8300Sroot struct socketopt *opt; 344786Swnj { 354786Swnj register struct protosw *prp; 364786Swnj register struct socket *so; 374786Swnj struct mbuf *m; 38*8300Sroot int pf, error; 394786Swnj 40*8300Sroot 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); 47*8300Sroot if (prp->pr_type != type) 48*8300Sroot return (EPROTOTYPE); 494890Swnj m = m_getclr(M_WAIT); 504786Swnj if (m == 0) 514786Swnj return (ENOBUFS); 524786Swnj so = mtod(m, struct socket *); 53*8300Sroot 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; 58*8300Sroot error = (*prp->pr_usrreq)(so, PRU_ATTACH, 59*8300Sroot (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 69*8300Sroot sobind(so, nam, opt) 70*8300Sroot struct socket *so; 71*8300Sroot struct mbuf *nam; 72*8300Sroot struct socketopt *opt; 73*8300Sroot { 74*8300Sroot int s = splnet(); 75*8300Sroot int error; 76*8300Sroot 77*8300Sroot error = 78*8300Sroot (*so->so_proto->pr_usrreq)(so, PRU_BIND, 79*8300Sroot (struct mbuf *)0, nam, opt); 80*8300Sroot splx(s); 81*8300Sroot return (error); 82*8300Sroot } 83*8300Sroot 84*8300Sroot solisten(so, backlog) 85*8300Sroot struct socket *so; 86*8300Sroot int backlog; 87*8300Sroot { 88*8300Sroot int s = splnet(); 89*8300Sroot int error; 90*8300Sroot 91*8300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 92*8300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 93*8300Sroot if (error) { 94*8300Sroot splx(s); 95*8300Sroot return (error); 96*8300Sroot } 97*8300Sroot if (so->so_q == 0) { 98*8300Sroot so->so_q = so; 99*8300Sroot so->so_q0 = so; 100*8300Sroot so->so_options |= SO_ACCEPTCONN; 101*8300Sroot } 102*8300Sroot if (backlog < 0) 103*8300Sroot backlog = 0; 104*8300Sroot so->so_qlimit = backlog < 5 ? backlog : 5; 105*8300Sroot so->so_options |= SO_NEWFDONCONN; 106*8300Sroot return (0); 107*8300Sroot } 108*8300Sroot 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) { 171*8300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 172*8300Sroot (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 194*8300Sroot soaccept(so, nam, opt) 1954927Swnj struct socket *so; 196*8300Sroot struct mbuf *nam; 197*8300Sroot struct socketopt *opt; 1984927Swnj { 1994927Swnj int s = splnet(); 2004927Swnj int error; 2014927Swnj 202*8300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 203*8300Sroot (struct mbuf *)0, nam, opt); 2044927Swnj splx(s); 2054927Swnj return (error); 2064927Swnj } 2074927Swnj 208*8300Sroot soconnect(so, nam, opt) 2094786Swnj struct socket *so; 210*8300Sroot struct mbuf *nam; 211*8300Sroot 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 } 220*8300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 221*8300Sroot (struct mbuf *)0, nam, opt); 2224890Swnj bad: 2234890Swnj splx(s); 2244890Swnj return (error); 2254786Swnj } 2264786Swnj 227*8300Sroot sodisconnect(so, nam) 2284786Swnj struct socket *so; 229*8300Sroot 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 } 242*8300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 243*8300Sroot (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*8300Sroot sosend(so, nam, uio) 2584786Swnj register struct socket *so; 259*8300Sroot struct mbuf *nam; 2607827Sroot struct uio *uio; 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 #ifdef notdef 2706419Sroot /* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING */ 2716214Swnj if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 2724890Swnj return (EWOULDBLOCK); 2736419Sroot #endif 2746419Sroot restart: 2754890Swnj sblock(&so->so_snd); 2764890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2774890Swnj 2788041Sroot u.u_ru.ru_msgsnd++; 2796419Sroot again: 2804890Swnj s = splnet(); 2816419Sroot if (so->so_state & SS_CANTSENDMORE) { 2826419Sroot psignal(u.u_procp, SIGPIPE); 2836419Sroot snderr(EPIPE); 2846419Sroot } 2855168Swnj if (so->so_error) { 2865168Swnj error = so->so_error; 2876419Sroot so->so_error = 0; /* ??? */ 2885168Swnj splx(s); 2895168Swnj goto release; 2905168Swnj } 2914890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2924890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2934890Swnj snderr(ENOTCONN); 294*8300Sroot if (nam == 0) 2954890Swnj snderr(EDESTADDRREQ); 2964890Swnj } 2974890Swnj if (top) { 298*8300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, 299*8300Sroot top, (caddr_t)nam, (struct socketopt *)0); 3006419Sroot top = 0; 3014890Swnj if (error) { 3024890Swnj splx(s); 3034786Swnj goto release; 3044786Swnj } 3054890Swnj mp = ⊤ 3064786Swnj } 3077827Sroot if (uio->uio_resid == 0) { 3084979Swnj splx(s); 3094979Swnj goto release; 3104979Swnj } 3115018Swnj space = sbspace(&so->so_snd); 3127827Sroot if (space <= 0 || sosendallatonce(so) && space < uio->uio_resid) { 3136214Swnj if (so->so_state & SS_NBIO) 3144890Swnj snderr(EWOULDBLOCK); 3154890Swnj sbunlock(&so->so_snd); 3164890Swnj sbwait(&so->so_snd); 3174890Swnj splx(s); 3186419Sroot goto restart; 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: 3454890Swnj m->m_off = MMINOFF; 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; 3525018Swnj space = sbspace(&so->so_snd); 3534786Swnj } 3544890Swnj goto again; 3554890Swnj 3564786Swnj release: 3574890Swnj sbunlock(&so->so_snd); 3586419Sroot if (top) 3596419Sroot m_freem(top); 3604786Swnj return (error); 3614786Swnj } 3624786Swnj 363*8300Sroot soreceive(so, aname, uio) 3644786Swnj register struct socket *so; 365*8300Sroot struct mbuf **aname; 3667747Sroot struct uio *uio; 3674786Swnj { 3687747Sroot register struct iovec *iov; 3694786Swnj register struct mbuf *m, *n; 3704916Swnj u_int len; 3717827Sroot int eor, s, error = 0; 3724786Swnj 3734890Swnj restart: 3744890Swnj sblock(&so->so_rcv); 3754890Swnj s = splnet(); 3764890Swnj 3774890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3784786Swnj if (so->so_rcv.sb_cc == 0) { 3795168Swnj if (so->so_error) { 3805168Swnj error = so->so_error; 3815168Swnj so->so_error = 0; 3825168Swnj splx(s); 3835168Swnj goto release; 3845168Swnj } 3854890Swnj if (so->so_state & SS_CANTRCVMORE) { 3864890Swnj splx(s); 3874890Swnj goto release; 3884890Swnj } 3895015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3905015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3915015Sroot rcverr(ENOTCONN); 3926214Swnj if (so->so_state & SS_NBIO) 3935168Swnj rcverr(EWOULDBLOCK); 3944890Swnj sbunlock(&so->so_rcv); 3954971Swnj sbwait(&so->so_rcv); 3965012Swnj splx(s); 3974890Swnj goto restart; 3984786Swnj } 3998041Sroot u.u_ru.ru_msgrcv++; 4004829Swnj m = so->so_rcv.sb_mb; 4014786Swnj if (m == 0) 4024786Swnj panic("receive"); 4035039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4045039Swnj so->so_rcv.sb_cc -= m->m_len; 4055039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 406*8300Sroot if (aname) { 407*8300Sroot *aname = m; 408*8300Sroot m = m->m_next; 409*8300Sroot (*aname)->m_next = 0; 410*8300Sroot } else 411*8300Sroot m = m_free(m); 4124890Swnj if (m == 0) 4134890Swnj panic("receive 2"); 4145018Swnj so->so_rcv.sb_mb = m; 4154890Swnj } 4164786Swnj eor = 0; 4174786Swnj do { 4187827Sroot if (uio->uio_resid <= 0) 4197747Sroot break; 4207827Sroot len = uio->uio_resid; 4217747Sroot so->so_state &= ~SS_RCVATMARK; 4227747Sroot if (so->so_oobmark && len > so->so_oobmark) 4237747Sroot len = so->so_oobmark; 4247747Sroot if (len > m->m_len) 4257747Sroot len = m->m_len; 4264786Swnj splx(s); 4277827Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 4284786Swnj s = splnet(); 4294786Swnj if (len == m->m_len) { 4306091Sroot eor = (int)m->m_act; 4316091Sroot sbfree(&so->so_rcv, m); 4326091Sroot so->so_rcv.sb_mb = m->m_next; 4334786Swnj MFREE(m, n); 4344786Swnj } else { 4354786Swnj m->m_off += len; 4364786Swnj m->m_len -= len; 4374829Swnj so->so_rcv.sb_cc -= len; 4384786Swnj } 4397747Sroot if (so->so_oobmark) { 4407747Sroot so->so_oobmark -= len; 4417747Sroot if (so->so_oobmark == 0) { 4427747Sroot so->so_state |= SS_RCVATMARK; 4437747Sroot break; 4447747Sroot } 4457747Sroot } 4467747Sroot } while ((m = so->so_rcv.sb_mb) && !eor); 4474786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4484786Swnj do { 4494786Swnj if (m == 0) 4504890Swnj panic("receive 3"); 4514890Swnj sbfree(&so->so_rcv, m); 4524786Swnj eor = (int)m->m_act; 4534786Swnj so->so_rcv.sb_mb = m->m_next; 4544786Swnj MFREE(m, n); 4554890Swnj m = n; 4564786Swnj } while (eor == 0); 4574890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 458*8300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 459*8300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 4604890Swnj release: 4614916Swnj sbunlock(&so->so_rcv); 4624890Swnj splx(s); 4634916Swnj return (error); 4644786Swnj } 4654786Swnj 4665423Swnj sohasoutofband(so) 4675423Swnj struct socket *so; 4685423Swnj { 4695423Swnj 4705423Swnj if (so->so_pgrp == 0) 4715423Swnj return; 4725423Swnj if (so->so_pgrp > 0) 4735423Swnj gsignal(so->so_pgrp, SIGURG); 4745429Swnj else { 4755429Swnj struct proc *p = pfind(-so->so_pgrp); 4765429Swnj 4775429Swnj if (p) 4785429Swnj psignal(p, SIGURG); 4795429Swnj } 4805423Swnj } 4815423Swnj 4824916Swnj /*ARGSUSED*/ 4837627Ssam soioctl(so, cmd, data) 4844829Swnj register struct socket *so; 4854829Swnj int cmd; 4867627Ssam register char *data; 4874786Swnj { 4884786Swnj 4895358Sroot switch (cmd) { 4904829Swnj 4917627Ssam case FIONBIO: 4927627Ssam if (*(int *)data) 4936214Swnj so->so_state |= SS_NBIO; 4945388Sroot else 4956214Swnj so->so_state &= ~SS_NBIO; 4965388Sroot return; 4975388Sroot 4987627Ssam case FIOASYNC: 4997627Ssam if (*(int *)data) 5006214Swnj so->so_state |= SS_ASYNC; 5015388Sroot else 5026214Swnj so->so_state &= ~SS_ASYNC; 5035388Sroot return; 5045388Sroot 5057627Ssam case SIOCSKEEP: 5067627Ssam if (*(int *)data) 5077507Sroot so->so_options &= ~SO_KEEPALIVE; 5087507Sroot else 5097491Ssam so->so_options |= SO_KEEPALIVE; 5105388Sroot return; 5115388Sroot 5127627Ssam case SIOCGKEEP: 5137627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5145388Sroot return; 5155388Sroot 5167627Ssam case SIOCSLINGER: 5177627Ssam so->so_linger = *(int *)data; 5185388Sroot if (so->so_linger) 5195388Sroot so->so_options &= ~SO_DONTLINGER; 5205388Sroot else 5215388Sroot so->so_options |= SO_DONTLINGER; 5225388Sroot return; 5235388Sroot 5247627Ssam case SIOCGLINGER: 5257627Ssam *(int *)data = so->so_linger; 5265423Swnj return; 5275388Sroot 5287627Ssam case SIOCSPGRP: 5297627Ssam so->so_pgrp = *(int *)data; 5307627Ssam return; 5315423Swnj 5327627Ssam case SIOCGPGRP: 5337627Ssam *(int *)data = so->so_pgrp; 5347627Ssam return; 5357627Ssam 5365281Sroot case SIOCDONE: { 5377627Ssam int flags = *(int *)data; 5387627Ssam 5395388Sroot flags++; 5405281Sroot if (flags & FREAD) { 5415281Sroot int s = splimp(); 5425281Sroot socantrcvmore(so); 5435281Sroot sbflush(&so->so_rcv); 5446140Ssam splx(s); 5455281Sroot } 5465281Sroot if (flags & FWRITE) 547*8300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 548*8300Sroot (struct mbuf *)0, (struct mbuf *)0, 549*8300Sroot (struct socketopt *)0); 5505281Sroot return; 5514829Swnj } 5525281Sroot 5535423Swnj case SIOCSENDOOB: { 5547627Ssam char oob = *(char *)data; 5555423Swnj struct mbuf *m; 5567627Ssam 5575423Swnj m = m_get(M_DONTWAIT); 5585423Swnj if (m == 0) { 5595423Swnj u.u_error = ENOBUFS; 5605423Swnj return; 5615423Swnj } 5625423Swnj m->m_off = MMINOFF; 5637627Ssam m->m_len = sizeof (char); 5647627Ssam *mtod(m, char *) = oob; 565*8300Sroot (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 566*8300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 5675423Swnj return; 5685281Sroot } 5695423Swnj 5705423Swnj case SIOCRCVOOB: { 5715423Swnj struct mbuf *m = m_get(M_DONTWAIT); 5727627Ssam 5735423Swnj if (m == 0) { 5745423Swnj u.u_error = ENOBUFS; 5755423Swnj return; 5765423Swnj } 5775423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 578*8300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 579*8300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 5807627Ssam *(char *)data = *mtod(m, char *); 5817627Ssam (void) m_free(m); 5825423Swnj return; 5835423Swnj } 5845423Swnj 5857627Ssam case SIOCATMARK: 5867627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 5875423Swnj return; 5886355Ssam 5896355Ssam /* routing table update calls */ 5906355Ssam case SIOCADDRT: 5916355Ssam case SIOCDELRT: 5926355Ssam if (!suser()) 5936355Ssam return; 5947627Ssam u.u_error = rtrequest(cmd, (struct rtentry *)data); 5956355Ssam return; 5966355Ssam 5975445Swnj /* type/protocol specific ioctls */ 5985423Swnj } 5995445Swnj u.u_error = EOPNOTSUPP; 6004786Swnj } 601