1*5950Swnj /* uipc_socket.c 4.31 82/02/25 */ 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; 734786Swnj 744786Swnj /* 754890Swnj * Attach protocol to socket, initializing 764890Swnj * and reserving resources. 774786Swnj */ 784786Swnj so->so_proto = prp; 794979Swnj error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 804979Swnj if (error) { 814971Swnj (void) m_free(dtom(so)); 824890Swnj return (error); 834786Swnj } 844786Swnj *aso = so; 854786Swnj return (0); 864786Swnj } 874786Swnj 884916Swnj sofree(so) 894916Swnj struct socket *so; 904916Swnj { 914916Swnj 924927Swnj COUNT(SOFREE); 934950Swnj if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) 944950Swnj return; 954950Swnj sbrelease(&so->so_snd); 964950Swnj sbrelease(&so->so_rcv); 974971Swnj (void) m_free(dtom(so)); 984916Swnj } 994916Swnj 1004786Swnj /* 1014890Swnj * Close a socket on last file table reference removal. 1024890Swnj * Initiate disconnect if connected. 1034890Swnj * Free socket when disconnect complete. 1045580Sroot * 1055580Sroot * THIS IS REALLY A UNIX INTERFACE ROUTINE 1064829Swnj */ 1075580Sroot soclose(so, exiting) 1084829Swnj register struct socket *so; 1095580Sroot int exiting; 1104829Swnj { 1114890Swnj int s = splnet(); /* conservative */ 1124829Swnj 1134927Swnj COUNT(SOCLOSE); 1144890Swnj if (so->so_pcb == 0) 1154890Swnj goto discard; 1164890Swnj if (so->so_state & SS_ISCONNECTED) { 1174890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1184927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1194890Swnj if (u.u_error) { 1205580Sroot if (exiting) 1215580Sroot goto drop; 1224890Swnj splx(s); 1234890Swnj return; 1244890Swnj } 1254890Swnj } 1265388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1275281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1285580Sroot (so->so_options & SO_NONBLOCKING) && 1295580Sroot exiting == 0) { 1305281Sroot u.u_error = EINPROGRESS; 1315281Sroot splx(s); 1325281Sroot return; 1335281Sroot } 1345580Sroot /* should use tsleep here, for at most linger */ 1355281Sroot while (so->so_state & SS_ISCONNECTED) 1365281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1374890Swnj } 1384890Swnj } 1395580Sroot drop: 1404890Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 1414890Swnj discard: 1424950Swnj so->so_state |= SS_USERGONE; 1434950Swnj sofree(so); 1444890Swnj splx(s); 1454829Swnj } 1464829Swnj 1474927Swnj sosplice(pso, so) 1484927Swnj struct socket *pso, *so; 1494927Swnj { 1504927Swnj 1514927Swnj COUNT(SOSPLICE); 1525168Swnj if (pso->so_proto->pr_family != PF_UNIX) { 1534927Swnj struct socket *tso; 1544927Swnj tso = pso; pso = so; so = tso; 1554927Swnj } 1565168Swnj if (pso->so_proto->pr_family != PF_UNIX) 1574927Swnj return (EOPNOTSUPP); 1584927Swnj /* check types and buffer space */ 1594927Swnj /* merge buffers */ 1604927Swnj return (0); 1614927Swnj } 1624927Swnj 1634916Swnj /*ARGSUSED*/ 1644890Swnj sostat(so, sb) 1654829Swnj struct socket *so; 1664890Swnj struct stat *sb; 1674829Swnj { 1684829Swnj 1694927Swnj COUNT(SOSTAT); 1705303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1715303Sroot return (0); /* XXX */ 1724829Swnj } 1734829Swnj 1744829Swnj /* 1754927Swnj * Accept connection on a socket. 1764927Swnj */ 1774927Swnj soaccept(so, asa) 1784927Swnj struct socket *so; 1794927Swnj struct sockaddr *asa; 1804927Swnj { 1814927Swnj int s = splnet(); 1824927Swnj int error; 1834927Swnj 1844927Swnj COUNT(SOACCEPT); 1854927Swnj if ((so->so_options & SO_ACCEPTCONN) == 0) { 1864927Swnj error = EINVAL; /* XXX */ 1874927Swnj goto bad; 1884927Swnj } 1895265Swnj if ((so->so_state & SS_CONNAWAITING) == 0) { 1905265Swnj error = ENOTCONN; 1915265Swnj goto bad; 1925265Swnj } 1935265Swnj so->so_state &= ~SS_CONNAWAITING; 1944927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 1954927Swnj bad: 1964927Swnj splx(s); 1974927Swnj return (error); 1984927Swnj } 1994927Swnj 2004927Swnj /* 2014890Swnj * Connect socket to a specified address. 2024890Swnj * If already connected or connecting, then avoid 2034890Swnj * the protocol entry, to keep its job simpler. 2044786Swnj */ 2054927Swnj soconnect(so, asa) 2064786Swnj struct socket *so; 2074927Swnj struct sockaddr *asa; 2084786Swnj { 2094890Swnj int s = splnet(); 2104890Swnj int error; 2114786Swnj 2124927Swnj COUNT(SOCONNECT); 2134890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2144890Swnj error = EISCONN; 2154890Swnj goto bad; 2164890Swnj } 2174927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 2184890Swnj bad: 2194890Swnj splx(s); 2204890Swnj return (error); 2214786Swnj } 2224786Swnj 2234786Swnj /* 2244890Swnj * Disconnect from a socket. 2254890Swnj * Address parameter is from system call for later multicast 2264890Swnj * protocols. Check to make sure that connected and no disconnect 2274890Swnj * in progress (for protocol's sake), and then invoke protocol. 2284786Swnj */ 2294927Swnj sodisconnect(so, asa) 2304786Swnj struct socket *so; 2314927Swnj struct sockaddr *asa; 2324786Swnj { 2334890Swnj int s = splnet(); 2344890Swnj int error; 2354786Swnj 2364927Swnj COUNT(SODISCONNECT); 2374890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2384890Swnj error = ENOTCONN; 2394890Swnj goto bad; 2404890Swnj } 2414890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2424890Swnj error = EALREADY; 2434890Swnj goto bad; 2444890Swnj } 2454927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 2464890Swnj bad: 2474890Swnj splx(s); 2484890Swnj return (error); 2494786Swnj } 2504786Swnj 2514786Swnj /* 2524890Swnj * Send on a socket. 2534890Swnj * If send must go all at once and message is larger than 2544890Swnj * send buffering, then hard error. 2554890Swnj * Lock against other senders. 2564890Swnj * If must go all at once and not enough room now, then 2574890Swnj * inform user that this would block and do nothing. 2584786Swnj */ 2594927Swnj sosend(so, asa) 2604786Swnj register struct socket *so; 2614927Swnj struct sockaddr *asa; 2624786Swnj { 2634890Swnj struct mbuf *top = 0; 2644890Swnj register struct mbuf *m, **mp = ⊤ 2654916Swnj register u_int len; 2664916Swnj int error = 0, space, s; 2674786Swnj 2684927Swnj COUNT(SOSEND); 269*5950Swnj if (so->so_state & SS_CANTSENDMORE) { 270*5950Swnj psignal(u.u_procp, SIGPIPE); 2714890Swnj return (EPIPE); 272*5950Swnj } 2734890Swnj if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 2744890Swnj return (EMSGSIZE); 2755388Sroot if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_options & SO_NONBLOCKING)) 2764890Swnj return (EWOULDBLOCK); 2774890Swnj sblock(&so->so_snd); 2784890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2794890Swnj 2804890Swnj s = splnet(); 2814890Swnj again: 2825168Swnj if (so->so_error) { 2835168Swnj error = so->so_error; 2845168Swnj 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); 2914927Swnj if (asa == 0) 2924890Swnj snderr(EDESTADDRREQ); 2934890Swnj } 2944890Swnj if (top) { 2954927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 2964890Swnj if (error) { 2974890Swnj splx(s); 2984786Swnj goto release; 2994786Swnj } 3004890Swnj top = 0; 3014890Swnj mp = ⊤ 3024786Swnj } 3034979Swnj if (u.u_count == 0) { 3044979Swnj splx(s); 3054979Swnj goto release; 3064979Swnj } 3075018Swnj space = sbspace(&so->so_snd); 3085610Swnj if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 3095388Sroot if (so->so_options & SO_NONBLOCKING) 3104890Swnj snderr(EWOULDBLOCK); 3114890Swnj sbunlock(&so->so_snd); 3124890Swnj sbwait(&so->so_snd); 3134890Swnj splx(s); 3144786Swnj goto again; 3154786Swnj } 3164890Swnj splx(s); 3175018Swnj while (u.u_count && space > 0) { 3184890Swnj MGET(m, 1); 3194890Swnj if (m == NULL) { 3204890Swnj error = ENOBUFS; 3214890Swnj m_freem(top); 3224890Swnj goto release; 3234786Swnj } 3245095Swnj if (u.u_count >= CLBYTES && space >= CLBYTES) { 3254890Swnj register struct mbuf *p; 3265095Swnj MCLGET(p, 1); 3274890Swnj if (p == 0) 3284890Swnj goto nopages; 3294890Swnj m->m_off = (int)p - (int)m; 3305095Swnj len = CLBYTES; 3314890Swnj } else { 3324786Swnj nopages: 3334890Swnj m->m_off = MMINOFF; 3344890Swnj len = MIN(MLEN, u.u_count); 3354786Swnj } 3364890Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3374890Swnj m->m_len = len; 3384890Swnj *mp = m; 3394890Swnj mp = &m->m_next; 3405018Swnj space = sbspace(&so->so_snd); 3414786Swnj } 3424890Swnj s = splnet(); 3434890Swnj goto again; 3444890Swnj 3454786Swnj release: 3464890Swnj sbunlock(&so->so_snd); 3474786Swnj return (error); 3484786Swnj } 3494786Swnj 3504927Swnj soreceive(so, asa) 3514786Swnj register struct socket *so; 3524927Swnj struct sockaddr *asa; 3534786Swnj { 3544786Swnj register struct mbuf *m, *n; 3554916Swnj u_int len; 3565423Swnj int eor, s, error = 0, cnt = u.u_count; 3575423Swnj caddr_t base = u.u_base; 3584786Swnj 3594927Swnj COUNT(SORECEIVE); 3604890Swnj restart: 3614890Swnj sblock(&so->so_rcv); 3624890Swnj s = splnet(); 3634890Swnj 3644890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3654786Swnj if (so->so_rcv.sb_cc == 0) { 3665168Swnj if (so->so_error) { 3675168Swnj error = so->so_error; 3685168Swnj so->so_error = 0; 3695168Swnj splx(s); 3705168Swnj goto release; 3715168Swnj } 3724890Swnj if (so->so_state & SS_CANTRCVMORE) { 3734890Swnj splx(s); 3744890Swnj goto release; 3754890Swnj } 3765015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3775015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3785015Sroot rcverr(ENOTCONN); 3795388Sroot if (so->so_options & SO_NONBLOCKING) 3805168Swnj rcverr(EWOULDBLOCK); 3814890Swnj sbunlock(&so->so_rcv); 3824971Swnj sbwait(&so->so_rcv); 3835012Swnj splx(s); 3844890Swnj goto restart; 3854786Swnj } 3864829Swnj m = so->so_rcv.sb_mb; 3874786Swnj if (m == 0) 3884786Swnj panic("receive"); 3895039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 3905039Swnj if (m->m_len != sizeof (struct sockaddr)) 3915039Swnj panic("soreceive addr"); 3925039Swnj if (asa) 3935039Swnj bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 3945039Swnj so->so_rcv.sb_cc -= m->m_len; 3955039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 3965018Swnj m = m_free(m); 3974890Swnj if (m == 0) 3984890Swnj panic("receive 2"); 3995018Swnj so->so_rcv.sb_mb = m; 4004890Swnj } 4015423Swnj so->so_state &= ~SS_RCVATMARK; 4025423Swnj if (so->so_oobmark && cnt > so->so_oobmark) 4035423Swnj cnt = so->so_oobmark; 4044786Swnj eor = 0; 4054786Swnj do { 4065423Swnj len = MIN(m->m_len, cnt); 4074786Swnj if (len == m->m_len) { 4084786Swnj eor = (int)m->m_act; 4094890Swnj sbfree(&so->so_rcv, m); 4105358Sroot so->so_rcv.sb_mb = m->m_next; 4114786Swnj } 4124786Swnj splx(s); 4134786Swnj iomove(mtod(m, caddr_t), len, B_READ); 4145423Swnj cnt -= len; 4154786Swnj s = splnet(); 4164786Swnj if (len == m->m_len) { 4174786Swnj MFREE(m, n); 4184786Swnj } else { 4194786Swnj m->m_off += len; 4204786Swnj m->m_len -= len; 4214829Swnj so->so_rcv.sb_cc -= len; 4224786Swnj } 4235423Swnj } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 4244786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4254786Swnj do { 4264786Swnj if (m == 0) 4274890Swnj panic("receive 3"); 4284890Swnj sbfree(&so->so_rcv, m); 4294786Swnj eor = (int)m->m_act; 4304786Swnj so->so_rcv.sb_mb = m->m_next; 4314786Swnj MFREE(m, n); 4324890Swnj m = n; 4334786Swnj } while (eor == 0); 4344890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 4354890Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 4365423Swnj if (so->so_oobmark) { 4375423Swnj so->so_oobmark -= u.u_base - base; 4385423Swnj if (so->so_oobmark == 0) 4395423Swnj so->so_state |= SS_RCVATMARK; 4405423Swnj } 4414890Swnj release: 4424916Swnj sbunlock(&so->so_rcv); 4434890Swnj splx(s); 4444916Swnj return (error); 4454786Swnj } 4464786Swnj 4475423Swnj sohasoutofband(so) 4485423Swnj struct socket *so; 4495423Swnj { 4505423Swnj 4515423Swnj if (so->so_pgrp == 0) 4525423Swnj return; 4535423Swnj if (so->so_pgrp > 0) 4545423Swnj gsignal(so->so_pgrp, SIGURG); 4555429Swnj else { 4565429Swnj struct proc *p = pfind(-so->so_pgrp); 4575429Swnj 4585429Swnj if (p) 4595429Swnj psignal(p, SIGURG); 4605429Swnj } 4615423Swnj } 4625423Swnj 4634916Swnj /*ARGSUSED*/ 4644916Swnj soioctl(so, cmd, cmdp) 4654829Swnj register struct socket *so; 4664829Swnj int cmd; 4674829Swnj register caddr_t cmdp; 4684786Swnj { 4694786Swnj 4704927Swnj COUNT(SOIOCTL); 4715358Sroot switch (cmd) { 4724829Swnj 4735388Sroot case FIONBIO: { 4745388Sroot int nbio; 4755388Sroot if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 4765388Sroot u.u_error = EFAULT; 4775388Sroot return; 4785388Sroot } 4795388Sroot if (nbio) 4805388Sroot so->so_options |= SO_NONBLOCKING; 4815388Sroot else 4825388Sroot so->so_options &= ~SO_NONBLOCKING; 4835388Sroot return; 4845388Sroot } 4855388Sroot 4865388Sroot case FIOASYNC: { 4875388Sroot int async; 4885388Sroot if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 4895388Sroot u.u_error = EFAULT; 4905388Sroot return; 4915388Sroot } 4925388Sroot if (async) 4935388Sroot ; 4945388Sroot else 4955388Sroot ; 4965388Sroot return; 4975388Sroot } 4985388Sroot 4995388Sroot case SIOCSKEEP: { 5005388Sroot int keep; 5015388Sroot if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 5025388Sroot u.u_error = EFAULT; 5035388Sroot return; 5045388Sroot } 5055388Sroot if (keep) 5065388Sroot so->so_options &= ~SO_NOKEEPALIVE; 5075388Sroot else 5085388Sroot so->so_options |= SO_NOKEEPALIVE; 5095388Sroot return; 5105388Sroot } 5115388Sroot 5125388Sroot case SIOCGKEEP: { 5135388Sroot int keep = (so->so_options & SO_NOKEEPALIVE) == 0; 5145388Sroot if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 5155388Sroot u.u_error = EFAULT; 5165388Sroot return; 5175388Sroot } 5185388Sroot 5195388Sroot case SIOCSLINGER: { 5205388Sroot int linger; 5215388Sroot if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 5225388Sroot u.u_error = EFAULT; 5235388Sroot return; 5245388Sroot } 5255388Sroot so->so_linger = linger; 5265388Sroot if (so->so_linger) 5275388Sroot so->so_options &= ~SO_DONTLINGER; 5285388Sroot else 5295388Sroot so->so_options |= SO_DONTLINGER; 5305388Sroot return; 5315388Sroot } 5325388Sroot 5335388Sroot case SIOCGLINGER: { 5345388Sroot int linger = so->so_linger; 5355388Sroot if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 5365388Sroot u.u_error = EFAULT; 5375388Sroot return; 5385388Sroot } 5395388Sroot } 5405423Swnj case SIOCSPGRP: { 5415423Swnj int pgrp; 5425423Swnj if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 5435423Swnj u.u_error = EFAULT; 5445423Swnj return; 5455423Swnj } 5465423Swnj so->so_pgrp = pgrp; 5475423Swnj return; 5485423Swnj } 5495388Sroot 5505423Swnj case SIOCGPGRP: { 5515423Swnj int pgrp = so->so_pgrp; 5525423Swnj if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 5535423Swnj u.u_error = EFAULT; 5545423Swnj return; 5555423Swnj } 5565423Swnj } 5575423Swnj 5585281Sroot case SIOCDONE: { 5595281Sroot int flags; 5605281Sroot if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 5615281Sroot u.u_error = EFAULT; 5625281Sroot return; 5635281Sroot } 5645388Sroot flags++; 5655281Sroot if (flags & FREAD) { 5665281Sroot int s = splimp(); 5675281Sroot socantrcvmore(so); 5685281Sroot sbflush(&so->so_rcv); 5695281Sroot } 5705281Sroot if (flags & FWRITE) 5715404Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 5725281Sroot return; 5734829Swnj } 5745281Sroot 5755423Swnj case SIOCSENDOOB: { 5765423Swnj char oob; 5775423Swnj struct mbuf *m; 5785423Swnj if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 5795423Swnj u.u_error = EFAULT; 5805423Swnj return; 5815423Swnj } 5825423Swnj m = m_get(M_DONTWAIT); 5835423Swnj if (m == 0) { 5845423Swnj u.u_error = ENOBUFS; 5855423Swnj return; 5865423Swnj } 5875423Swnj m->m_off = MMINOFF; 5885423Swnj m->m_len = 1; 5895423Swnj *mtod(m, caddr_t) = oob; 5905423Swnj (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 5915423Swnj return; 5925281Sroot } 5935423Swnj 5945423Swnj case SIOCRCVOOB: { 5955423Swnj struct mbuf *m = m_get(M_DONTWAIT); 5965423Swnj if (m == 0) { 5975423Swnj u.u_error = ENOBUFS; 5985423Swnj return; 5995423Swnj } 6005423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 6015423Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 6025423Swnj if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 6035423Swnj u.u_error = EFAULT; 6045423Swnj return; 6055423Swnj } 6065423Swnj m_free(m); 6075423Swnj return; 6085423Swnj } 6095423Swnj 6105423Swnj case SIOCATMARK: { 6115423Swnj int atmark = (so->so_state&SS_RCVATMARK) != 0; 6125423Swnj if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 6135423Swnj u.u_error = EFAULT; 6145423Swnj return; 6155423Swnj } 6165423Swnj return; 6175423Swnj } 6185445Swnj /* type/protocol specific ioctls */ 6195423Swnj } 6205445Swnj u.u_error = EOPNOTSUPP; 6214786Swnj } 622