1*6259Sroot /* uipc_socket.c 4.35 82/03/19 */ 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" 194786Swnj 204786Swnj /* 214890Swnj * Socket support routines. 224890Swnj * 234890Swnj * DEAL WITH INTERRUPT NOTIFICATION. 244786Swnj */ 254786Swnj 264786Swnj /* 274786Swnj * Create a socket. 284786Swnj */ 294927Swnj socreate(aso, type, asp, asa, options) 304786Swnj struct socket **aso; 314786Swnj int type; 324927Swnj struct sockproto *asp; 334927Swnj struct sockaddr *asa; 344829Swnj int options; 354786Swnj { 364786Swnj register struct protosw *prp; 374786Swnj register struct socket *so; 384786Swnj struct mbuf *m; 394890Swnj int pf, proto, error; 404927Swnj COUNT(SOCREATE); 414786Swnj 424786Swnj /* 434890Swnj * Use process standard protocol/protocol family if none 444890Swnj * specified by address argument. 454786Swnj */ 464927Swnj if (asp == 0) { 474890Swnj pf = PF_INET; /* should be u.u_protof */ 484786Swnj proto = 0; 494786Swnj } else { 504927Swnj pf = asp->sp_family; 514927Swnj proto = asp->sp_protocol; 524786Swnj } 534786Swnj 544786Swnj /* 554890Swnj * If protocol specified, look for it, otherwise 564890Swnj * for a protocol of the correct type in the right family. 574890Swnj */ 584890Swnj if (proto) 594890Swnj prp = pffindproto(pf, proto); 604890Swnj else 614890Swnj prp = pffindtype(pf, type); 624890Swnj if (prp == 0) 634890Swnj return (EPROTONOSUPPORT); 644890Swnj 654890Swnj /* 664786Swnj * Get a socket structure. 674786Swnj */ 684890Swnj m = m_getclr(M_WAIT); 694786Swnj if (m == 0) 704786Swnj return (ENOBUFS); 714786Swnj so = mtod(m, struct socket *); 724829Swnj so->so_options = options; 736214Swnj so->so_state = 0; 746214Swnj if (u.u_uid == 0) 756214Swnj so->so_state = SS_PRIV; 764786Swnj 774786Swnj /* 784890Swnj * Attach protocol to socket, initializing 794890Swnj * and reserving resources. 804786Swnj */ 814786Swnj so->so_proto = prp; 824979Swnj error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 834979Swnj if (error) { 844971Swnj (void) m_free(dtom(so)); 854890Swnj return (error); 864786Swnj } 874786Swnj *aso = so; 884786Swnj return (0); 894786Swnj } 904786Swnj 914916Swnj sofree(so) 924916Swnj struct socket *so; 934916Swnj { 944916Swnj 954927Swnj COUNT(SOFREE); 964950Swnj if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) 974950Swnj return; 984950Swnj sbrelease(&so->so_snd); 994950Swnj sbrelease(&so->so_rcv); 1004971Swnj (void) m_free(dtom(so)); 1014916Swnj } 1024916Swnj 1034786Swnj /* 1044890Swnj * Close a socket on last file table reference removal. 1054890Swnj * Initiate disconnect if connected. 1064890Swnj * Free socket when disconnect complete. 1075580Sroot * 1085580Sroot * THIS IS REALLY A UNIX INTERFACE ROUTINE 1094829Swnj */ 1105580Sroot soclose(so, exiting) 1114829Swnj register struct socket *so; 1125580Sroot int exiting; 1134829Swnj { 1144890Swnj int s = splnet(); /* conservative */ 1154829Swnj 1164927Swnj COUNT(SOCLOSE); 1174890Swnj if (so->so_pcb == 0) 1184890Swnj goto discard; 119*6259Sroot if (exiting) 120*6259Sroot so->so_options |= SO_KEEPALIVE; 1214890Swnj if (so->so_state & SS_ISCONNECTED) { 1224890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1234927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1244890Swnj if (u.u_error) { 1255580Sroot if (exiting) 1265580Sroot goto drop; 1274890Swnj splx(s); 1284890Swnj return; 1294890Swnj } 1304890Swnj } 1315388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1325281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1336214Swnj (so->so_state & SS_NBIO) && 1345580Sroot exiting == 0) { 1355281Sroot u.u_error = EINPROGRESS; 1365281Sroot splx(s); 1375281Sroot return; 1385281Sroot } 1395580Sroot /* should use tsleep here, for at most linger */ 1405281Sroot while (so->so_state & SS_ISCONNECTED) 1415281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1424890Swnj } 1434890Swnj } 1445580Sroot drop: 1454890Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 1464890Swnj discard: 1474950Swnj so->so_state |= SS_USERGONE; 1484950Swnj sofree(so); 1494890Swnj splx(s); 1504829Swnj } 1514829Swnj 1524927Swnj sosplice(pso, so) 1534927Swnj struct socket *pso, *so; 1544927Swnj { 1554927Swnj 1564927Swnj COUNT(SOSPLICE); 1575168Swnj if (pso->so_proto->pr_family != PF_UNIX) { 1584927Swnj struct socket *tso; 1594927Swnj tso = pso; pso = so; so = tso; 1604927Swnj } 1615168Swnj if (pso->so_proto->pr_family != PF_UNIX) 1624927Swnj return (EOPNOTSUPP); 1634927Swnj /* check types and buffer space */ 1644927Swnj /* merge buffers */ 1654927Swnj return (0); 1664927Swnj } 1674927Swnj 1684916Swnj /*ARGSUSED*/ 1694890Swnj sostat(so, sb) 1704829Swnj struct socket *so; 1714890Swnj struct stat *sb; 1724829Swnj { 1734829Swnj 1744927Swnj COUNT(SOSTAT); 1755303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1765303Sroot return (0); /* XXX */ 1774829Swnj } 1784829Swnj 1794829Swnj /* 1804927Swnj * Accept connection on a socket. 1814927Swnj */ 1824927Swnj soaccept(so, asa) 1834927Swnj struct socket *so; 1844927Swnj struct sockaddr *asa; 1854927Swnj { 1864927Swnj int s = splnet(); 1874927Swnj int error; 1884927Swnj 1894927Swnj COUNT(SOACCEPT); 1904927Swnj if ((so->so_options & SO_ACCEPTCONN) == 0) { 1914927Swnj error = EINVAL; /* XXX */ 1924927Swnj goto bad; 1934927Swnj } 1945265Swnj if ((so->so_state & SS_CONNAWAITING) == 0) { 1955265Swnj error = ENOTCONN; 1965265Swnj goto bad; 1975265Swnj } 1985265Swnj so->so_state &= ~SS_CONNAWAITING; 1994927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 2004927Swnj bad: 2014927Swnj splx(s); 2024927Swnj return (error); 2034927Swnj } 2044927Swnj 2054927Swnj /* 2064890Swnj * Connect socket to a specified address. 2074890Swnj * If already connected or connecting, then avoid 2084890Swnj * the protocol entry, to keep its job simpler. 2094786Swnj */ 2104927Swnj soconnect(so, asa) 2114786Swnj struct socket *so; 2124927Swnj struct sockaddr *asa; 2134786Swnj { 2144890Swnj int s = splnet(); 2154890Swnj int error; 2164786Swnj 2174927Swnj COUNT(SOCONNECT); 2184890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2194890Swnj error = EISCONN; 2204890Swnj goto bad; 2214890Swnj } 2224927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 2234890Swnj bad: 2244890Swnj splx(s); 2254890Swnj return (error); 2264786Swnj } 2274786Swnj 2284786Swnj /* 2294890Swnj * Disconnect from a socket. 2304890Swnj * Address parameter is from system call for later multicast 2314890Swnj * protocols. Check to make sure that connected and no disconnect 2324890Swnj * in progress (for protocol's sake), and then invoke protocol. 2334786Swnj */ 2344927Swnj sodisconnect(so, asa) 2354786Swnj struct socket *so; 2364927Swnj struct sockaddr *asa; 2374786Swnj { 2384890Swnj int s = splnet(); 2394890Swnj int error; 2404786Swnj 2414927Swnj COUNT(SODISCONNECT); 2424890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2434890Swnj error = ENOTCONN; 2444890Swnj goto bad; 2454890Swnj } 2464890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2474890Swnj error = EALREADY; 2484890Swnj goto bad; 2494890Swnj } 2504927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 2514890Swnj bad: 2524890Swnj splx(s); 2534890Swnj return (error); 2544786Swnj } 2554786Swnj 2564786Swnj /* 2574890Swnj * Send on a socket. 2584890Swnj * If send must go all at once and message is larger than 2594890Swnj * send buffering, then hard error. 2604890Swnj * Lock against other senders. 2614890Swnj * If must go all at once and not enough room now, then 2624890Swnj * inform user that this would block and do nothing. 2634786Swnj */ 2644927Swnj sosend(so, asa) 2654786Swnj register struct socket *so; 2664927Swnj struct sockaddr *asa; 2674786Swnj { 2684890Swnj struct mbuf *top = 0; 2694890Swnj register struct mbuf *m, **mp = ⊤ 2704916Swnj register u_int len; 2714916Swnj int error = 0, space, s; 2724786Swnj 2734927Swnj COUNT(SOSEND); 2745950Swnj if (so->so_state & SS_CANTSENDMORE) { 2755950Swnj psignal(u.u_procp, SIGPIPE); 2764890Swnj return (EPIPE); 2775950Swnj } 2784890Swnj if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 2794890Swnj return (EMSGSIZE); 2806214Swnj if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 2814890Swnj return (EWOULDBLOCK); 2824890Swnj sblock(&so->so_snd); 2834890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2844890Swnj 2854890Swnj s = splnet(); 2864890Swnj again: 2875168Swnj if (so->so_error) { 2885168Swnj error = so->so_error; 2895168Swnj so->so_error = 0; 2905168Swnj splx(s); 2915168Swnj goto release; 2925168Swnj } 2934890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2944890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2954890Swnj snderr(ENOTCONN); 2964927Swnj if (asa == 0) 2974890Swnj snderr(EDESTADDRREQ); 2984890Swnj } 2994890Swnj if (top) { 3004927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 3014890Swnj if (error) { 3024890Swnj splx(s); 3034786Swnj goto release; 3044786Swnj } 3054890Swnj top = 0; 3064890Swnj mp = ⊤ 3074786Swnj } 3084979Swnj if (u.u_count == 0) { 3094979Swnj splx(s); 3104979Swnj goto release; 3114979Swnj } 3125018Swnj space = sbspace(&so->so_snd); 3135610Swnj if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 3146214Swnj if (so->so_state & SS_NBIO) 3154890Swnj snderr(EWOULDBLOCK); 3164890Swnj sbunlock(&so->so_snd); 3174890Swnj sbwait(&so->so_snd); 3184890Swnj splx(s); 3194786Swnj goto again; 3204786Swnj } 3214890Swnj splx(s); 3225018Swnj while (u.u_count && space > 0) { 3234890Swnj MGET(m, 1); 3244890Swnj if (m == NULL) { 3254890Swnj error = ENOBUFS; 3264890Swnj m_freem(top); 3274890Swnj goto release; 3284786Swnj } 3295095Swnj if (u.u_count >= CLBYTES && space >= CLBYTES) { 3304890Swnj register struct mbuf *p; 3315095Swnj MCLGET(p, 1); 3324890Swnj if (p == 0) 3334890Swnj goto nopages; 3344890Swnj m->m_off = (int)p - (int)m; 3355095Swnj len = CLBYTES; 3364890Swnj } else { 3374786Swnj nopages: 3384890Swnj m->m_off = MMINOFF; 3394890Swnj len = MIN(MLEN, u.u_count); 3404786Swnj } 3414890Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3424890Swnj m->m_len = len; 3434890Swnj *mp = m; 3444890Swnj mp = &m->m_next; 3455018Swnj space = sbspace(&so->so_snd); 3464786Swnj } 3474890Swnj s = splnet(); 3484890Swnj goto again; 3494890Swnj 3504786Swnj release: 3514890Swnj sbunlock(&so->so_snd); 3524786Swnj return (error); 3534786Swnj } 3544786Swnj 3554927Swnj soreceive(so, asa) 3564786Swnj register struct socket *so; 3574927Swnj struct sockaddr *asa; 3584786Swnj { 3594786Swnj register struct mbuf *m, *n; 3604916Swnj u_int len; 3615423Swnj int eor, s, error = 0, cnt = u.u_count; 3625423Swnj caddr_t base = u.u_base; 3634786Swnj 3644927Swnj COUNT(SORECEIVE); 3654890Swnj restart: 3664890Swnj sblock(&so->so_rcv); 3674890Swnj s = splnet(); 3684890Swnj 3694890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3704786Swnj if (so->so_rcv.sb_cc == 0) { 3715168Swnj if (so->so_error) { 3725168Swnj error = so->so_error; 3735168Swnj so->so_error = 0; 3745168Swnj splx(s); 3755168Swnj goto release; 3765168Swnj } 3774890Swnj if (so->so_state & SS_CANTRCVMORE) { 3784890Swnj splx(s); 3794890Swnj goto release; 3804890Swnj } 3815015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3825015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3835015Sroot rcverr(ENOTCONN); 3846214Swnj if (so->so_state & SS_NBIO) 3855168Swnj rcverr(EWOULDBLOCK); 3864890Swnj sbunlock(&so->so_rcv); 3874971Swnj sbwait(&so->so_rcv); 3885012Swnj splx(s); 3894890Swnj goto restart; 3904786Swnj } 3914829Swnj m = so->so_rcv.sb_mb; 3924786Swnj if (m == 0) 3934786Swnj panic("receive"); 3945039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 3955039Swnj if (m->m_len != sizeof (struct sockaddr)) 3965039Swnj panic("soreceive addr"); 3975039Swnj if (asa) 3985039Swnj bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 3995039Swnj so->so_rcv.sb_cc -= m->m_len; 4005039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 4015018Swnj m = m_free(m); 4024890Swnj if (m == 0) 4034890Swnj panic("receive 2"); 4045018Swnj so->so_rcv.sb_mb = m; 4054890Swnj } 4065423Swnj so->so_state &= ~SS_RCVATMARK; 4075423Swnj if (so->so_oobmark && cnt > so->so_oobmark) 4085423Swnj cnt = so->so_oobmark; 4094786Swnj eor = 0; 4104786Swnj do { 4115423Swnj len = MIN(m->m_len, cnt); 4124786Swnj splx(s); 4134786Swnj iomove(mtod(m, caddr_t), len, B_READ); 4145423Swnj cnt -= len; 4154786Swnj s = splnet(); 4164786Swnj if (len == m->m_len) { 4176091Sroot eor = (int)m->m_act; 4186091Sroot sbfree(&so->so_rcv, m); 4196091Sroot so->so_rcv.sb_mb = m->m_next; 4204786Swnj MFREE(m, n); 4214786Swnj } else { 4224786Swnj m->m_off += len; 4234786Swnj m->m_len -= len; 4244829Swnj so->so_rcv.sb_cc -= len; 4254786Swnj } 4265423Swnj } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 4274786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4284786Swnj do { 4294786Swnj if (m == 0) 4304890Swnj panic("receive 3"); 4314890Swnj sbfree(&so->so_rcv, m); 4324786Swnj eor = (int)m->m_act; 4334786Swnj so->so_rcv.sb_mb = m->m_next; 4344786Swnj MFREE(m, n); 4354890Swnj m = n; 4364786Swnj } while (eor == 0); 4374890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 4384890Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 4395423Swnj if (so->so_oobmark) { 4405423Swnj so->so_oobmark -= u.u_base - base; 4415423Swnj if (so->so_oobmark == 0) 4425423Swnj so->so_state |= SS_RCVATMARK; 4435423Swnj } 4444890Swnj release: 4454916Swnj sbunlock(&so->so_rcv); 4464890Swnj splx(s); 4474916Swnj return (error); 4484786Swnj } 4494786Swnj 4505423Swnj sohasoutofband(so) 4515423Swnj struct socket *so; 4525423Swnj { 4535423Swnj 4545423Swnj if (so->so_pgrp == 0) 4555423Swnj return; 4565423Swnj if (so->so_pgrp > 0) 4575423Swnj gsignal(so->so_pgrp, SIGURG); 4585429Swnj else { 4595429Swnj struct proc *p = pfind(-so->so_pgrp); 4605429Swnj 4615429Swnj if (p) 4625429Swnj psignal(p, SIGURG); 4635429Swnj } 4645423Swnj } 4655423Swnj 4664916Swnj /*ARGSUSED*/ 4674916Swnj soioctl(so, cmd, cmdp) 4684829Swnj register struct socket *so; 4694829Swnj int cmd; 4704829Swnj register caddr_t cmdp; 4714786Swnj { 4724786Swnj 4734927Swnj COUNT(SOIOCTL); 4745358Sroot switch (cmd) { 4754829Swnj 4765388Sroot case FIONBIO: { 4775388Sroot int nbio; 4785388Sroot if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 4795388Sroot u.u_error = EFAULT; 4805388Sroot return; 4815388Sroot } 4825388Sroot if (nbio) 4836214Swnj so->so_state |= SS_NBIO; 4845388Sroot else 4856214Swnj so->so_state &= ~SS_NBIO; 4865388Sroot return; 4875388Sroot } 4885388Sroot 4895388Sroot case FIOASYNC: { 4905388Sroot int async; 4915388Sroot if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 4925388Sroot u.u_error = EFAULT; 4935388Sroot return; 4945388Sroot } 4955388Sroot if (async) 4966214Swnj so->so_state |= SS_ASYNC; 4975388Sroot else 4986214Swnj so->so_state &= ~SS_ASYNC; 4995388Sroot return; 5005388Sroot } 5015388Sroot 5025388Sroot case SIOCSKEEP: { 5035388Sroot int keep; 5045388Sroot if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 5055388Sroot u.u_error = EFAULT; 5065388Sroot return; 5075388Sroot } 5085388Sroot if (keep) 5096214Swnj so->so_options &= ~SO_KEEPALIVE; 5105388Sroot else 5116214Swnj so->so_options |= SO_KEEPALIVE; 5125388Sroot return; 5135388Sroot } 5145388Sroot 5155388Sroot case SIOCGKEEP: { 5166214Swnj int keep = (so->so_options & SO_KEEPALIVE) != 0; 5175388Sroot if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 5185388Sroot u.u_error = EFAULT; 5195388Sroot return; 5205388Sroot } 5215388Sroot 5225388Sroot case SIOCSLINGER: { 5235388Sroot int linger; 5245388Sroot if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 5255388Sroot u.u_error = EFAULT; 5265388Sroot return; 5275388Sroot } 5285388Sroot so->so_linger = linger; 5295388Sroot if (so->so_linger) 5305388Sroot so->so_options &= ~SO_DONTLINGER; 5315388Sroot else 5325388Sroot so->so_options |= SO_DONTLINGER; 5335388Sroot return; 5345388Sroot } 5355388Sroot 5365388Sroot case SIOCGLINGER: { 5375388Sroot int linger = so->so_linger; 5385388Sroot if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 5395388Sroot u.u_error = EFAULT; 5405388Sroot return; 5415388Sroot } 5425388Sroot } 5435423Swnj case SIOCSPGRP: { 5445423Swnj int pgrp; 5455423Swnj if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 5465423Swnj u.u_error = EFAULT; 5475423Swnj return; 5485423Swnj } 5495423Swnj so->so_pgrp = pgrp; 5505423Swnj return; 5515423Swnj } 5525388Sroot 5535423Swnj case SIOCGPGRP: { 5545423Swnj int pgrp = so->so_pgrp; 5555423Swnj if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 5565423Swnj u.u_error = EFAULT; 5575423Swnj return; 5585423Swnj } 5595423Swnj } 5605423Swnj 5615281Sroot case SIOCDONE: { 5625281Sroot int flags; 5635281Sroot if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 5645281Sroot u.u_error = EFAULT; 5655281Sroot return; 5665281Sroot } 5675388Sroot flags++; 5685281Sroot if (flags & FREAD) { 5695281Sroot int s = splimp(); 5705281Sroot socantrcvmore(so); 5715281Sroot sbflush(&so->so_rcv); 5726140Ssam splx(s); 5735281Sroot } 5745281Sroot if (flags & FWRITE) 5755404Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 5765281Sroot return; 5774829Swnj } 5785281Sroot 5795423Swnj case SIOCSENDOOB: { 5805423Swnj char oob; 5815423Swnj struct mbuf *m; 5825423Swnj if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 5835423Swnj u.u_error = EFAULT; 5845423Swnj return; 5855423Swnj } 5865423Swnj m = m_get(M_DONTWAIT); 5875423Swnj if (m == 0) { 5885423Swnj u.u_error = ENOBUFS; 5895423Swnj return; 5905423Swnj } 5915423Swnj m->m_off = MMINOFF; 5925423Swnj m->m_len = 1; 5935423Swnj *mtod(m, caddr_t) = oob; 5945423Swnj (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 5955423Swnj return; 5965281Sroot } 5975423Swnj 5985423Swnj case SIOCRCVOOB: { 5995423Swnj struct mbuf *m = m_get(M_DONTWAIT); 6005423Swnj if (m == 0) { 6015423Swnj u.u_error = ENOBUFS; 6025423Swnj return; 6035423Swnj } 6045423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 6055423Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 6065423Swnj if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 6075423Swnj u.u_error = EFAULT; 6085423Swnj return; 6095423Swnj } 6105423Swnj m_free(m); 6115423Swnj return; 6125423Swnj } 6135423Swnj 6145423Swnj case SIOCATMARK: { 6155423Swnj int atmark = (so->so_state&SS_RCVATMARK) != 0; 6165423Swnj if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 6175423Swnj u.u_error = EFAULT; 6185423Swnj return; 6195423Swnj } 6205423Swnj return; 6215423Swnj } 6225445Swnj /* type/protocol specific ioctls */ 6235423Swnj } 6245445Swnj u.u_error = EOPNOTSUPP; 6254786Swnj } 626