1*5423Swnj /* uipc_socket.c 4.25 82/01/17 */ 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. 1044829Swnj */ 1054890Swnj soclose(so) 1064829Swnj register struct socket *so; 1074829Swnj { 1084890Swnj int s = splnet(); /* conservative */ 1094829Swnj 1104927Swnj COUNT(SOCLOSE); 1114890Swnj if (so->so_pcb == 0) 1124890Swnj goto discard; 1134890Swnj if (so->so_state & SS_ISCONNECTED) { 1144890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1154927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1164890Swnj if (u.u_error) { 1174890Swnj splx(s); 1184890Swnj return; 1194890Swnj } 1204890Swnj } 1215388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1225281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1235388Sroot (so->so_options & SO_NONBLOCKING)) { 1245281Sroot u.u_error = EINPROGRESS; 1255281Sroot splx(s); 1265281Sroot return; 1275281Sroot } 1285388Sroot /* should use tsleep here */ 1295281Sroot while (so->so_state & SS_ISCONNECTED) 1305281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1314890Swnj } 1324890Swnj } 1334890Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 1344890Swnj discard: 1354950Swnj so->so_state |= SS_USERGONE; 1364950Swnj sofree(so); 1374890Swnj splx(s); 1384829Swnj } 1394829Swnj 1404927Swnj sosplice(pso, so) 1414927Swnj struct socket *pso, *so; 1424927Swnj { 1434927Swnj 1444927Swnj COUNT(SOSPLICE); 1455168Swnj if (pso->so_proto->pr_family != PF_UNIX) { 1464927Swnj struct socket *tso; 1474927Swnj tso = pso; pso = so; so = tso; 1484927Swnj } 1495168Swnj if (pso->so_proto->pr_family != PF_UNIX) 1504927Swnj return (EOPNOTSUPP); 1514927Swnj /* check types and buffer space */ 1524927Swnj /* merge buffers */ 1534927Swnj return (0); 1544927Swnj } 1554927Swnj 1564916Swnj /*ARGSUSED*/ 1574890Swnj sostat(so, sb) 1584829Swnj struct socket *so; 1594890Swnj struct stat *sb; 1604829Swnj { 1614829Swnj 1624927Swnj COUNT(SOSTAT); 1635303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1645303Sroot return (0); /* XXX */ 1654829Swnj } 1664829Swnj 1674829Swnj /* 1684927Swnj * Accept connection on a socket. 1694927Swnj */ 1704927Swnj soaccept(so, asa) 1714927Swnj struct socket *so; 1724927Swnj struct sockaddr *asa; 1734927Swnj { 1744927Swnj int s = splnet(); 1754927Swnj int error; 1764927Swnj 1774927Swnj COUNT(SOACCEPT); 1784927Swnj if ((so->so_options & SO_ACCEPTCONN) == 0) { 1794927Swnj error = EINVAL; /* XXX */ 1804927Swnj goto bad; 1814927Swnj } 1825265Swnj if ((so->so_state & SS_CONNAWAITING) == 0) { 1835265Swnj error = ENOTCONN; 1845265Swnj goto bad; 1855265Swnj } 1865265Swnj so->so_state &= ~SS_CONNAWAITING; 1874927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 1884927Swnj bad: 1894927Swnj splx(s); 1904927Swnj return (error); 1914927Swnj } 1924927Swnj 1934927Swnj /* 1944890Swnj * Connect socket to a specified address. 1954890Swnj * If already connected or connecting, then avoid 1964890Swnj * the protocol entry, to keep its job simpler. 1974786Swnj */ 1984927Swnj soconnect(so, asa) 1994786Swnj struct socket *so; 2004927Swnj struct sockaddr *asa; 2014786Swnj { 2024890Swnj int s = splnet(); 2034890Swnj int error; 2044786Swnj 2054927Swnj COUNT(SOCONNECT); 2064890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2074890Swnj error = EISCONN; 2084890Swnj goto bad; 2094890Swnj } 2104927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 2114890Swnj bad: 2124890Swnj splx(s); 2134890Swnj return (error); 2144786Swnj } 2154786Swnj 2164786Swnj /* 2174890Swnj * Disconnect from a socket. 2184890Swnj * Address parameter is from system call for later multicast 2194890Swnj * protocols. Check to make sure that connected and no disconnect 2204890Swnj * in progress (for protocol's sake), and then invoke protocol. 2214786Swnj */ 2224927Swnj sodisconnect(so, asa) 2234786Swnj struct socket *so; 2244927Swnj struct sockaddr *asa; 2254786Swnj { 2264890Swnj int s = splnet(); 2274890Swnj int error; 2284786Swnj 2294927Swnj COUNT(SODISCONNECT); 2304890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2314890Swnj error = ENOTCONN; 2324890Swnj goto bad; 2334890Swnj } 2344890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2354890Swnj error = EALREADY; 2364890Swnj goto bad; 2374890Swnj } 2384927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 2394890Swnj bad: 2404890Swnj splx(s); 2414890Swnj return (error); 2424786Swnj } 2434786Swnj 2444786Swnj /* 2454890Swnj * Send on a socket. 2464890Swnj * If send must go all at once and message is larger than 2474890Swnj * send buffering, then hard error. 2484890Swnj * Lock against other senders. 2494890Swnj * If must go all at once and not enough room now, then 2504890Swnj * inform user that this would block and do nothing. 2514786Swnj */ 2524927Swnj sosend(so, asa) 2534786Swnj register struct socket *so; 2544927Swnj struct sockaddr *asa; 2554786Swnj { 2564890Swnj struct mbuf *top = 0; 2574890Swnj register struct mbuf *m, **mp = ⊤ 2584916Swnj register u_int len; 2594916Swnj int error = 0, space, s; 2604786Swnj 2614927Swnj COUNT(SOSEND); 2624890Swnj if (so->so_state & SS_CANTSENDMORE) 2634890Swnj return (EPIPE); 2644890Swnj if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 2654890Swnj return (EMSGSIZE); 2665388Sroot if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_options & SO_NONBLOCKING)) 2674890Swnj return (EWOULDBLOCK); 2684890Swnj sblock(&so->so_snd); 2694890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2704890Swnj 2714890Swnj s = splnet(); 2724890Swnj again: 2735168Swnj if (so->so_error) { 2745168Swnj error = so->so_error; 2755168Swnj so->so_error = 0; 2765168Swnj splx(s); 2775168Swnj goto release; 2785168Swnj } 2794890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2804890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2814890Swnj snderr(ENOTCONN); 2824927Swnj if (asa == 0) 2834890Swnj snderr(EDESTADDRREQ); 2844890Swnj } 2854890Swnj if (top) { 2864927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 2874890Swnj if (error) { 2884890Swnj splx(s); 2894786Swnj goto release; 2904786Swnj } 2914890Swnj top = 0; 2924890Swnj mp = ⊤ 2934786Swnj } 2944979Swnj if (u.u_count == 0) { 2954979Swnj splx(s); 2964979Swnj goto release; 2974979Swnj } 2985018Swnj space = sbspace(&so->so_snd); 2995018Swnj if (space == 0 || sosendallatonce(so) && space < u.u_count) { 3005388Sroot if (so->so_options & SO_NONBLOCKING) 3014890Swnj snderr(EWOULDBLOCK); 3024890Swnj sbunlock(&so->so_snd); 3034890Swnj sbwait(&so->so_snd); 3044890Swnj splx(s); 3054786Swnj goto again; 3064786Swnj } 3074890Swnj splx(s); 3085018Swnj while (u.u_count && space > 0) { 3094890Swnj MGET(m, 1); 3104890Swnj if (m == NULL) { 3114890Swnj error = ENOBUFS; 3124890Swnj m_freem(top); 3134890Swnj goto release; 3144786Swnj } 3155095Swnj if (u.u_count >= CLBYTES && space >= CLBYTES) { 3164890Swnj register struct mbuf *p; 3175095Swnj MCLGET(p, 1); 3184890Swnj if (p == 0) 3194890Swnj goto nopages; 3204890Swnj m->m_off = (int)p - (int)m; 3215095Swnj len = CLBYTES; 3224890Swnj } else { 3234786Swnj nopages: 3244890Swnj m->m_off = MMINOFF; 3254890Swnj len = MIN(MLEN, u.u_count); 3264786Swnj } 3274890Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3284890Swnj m->m_len = len; 3294890Swnj *mp = m; 3304890Swnj mp = &m->m_next; 3315018Swnj space = sbspace(&so->so_snd); 3324786Swnj } 3334890Swnj s = splnet(); 3344890Swnj goto again; 3354890Swnj 3364786Swnj release: 3374890Swnj sbunlock(&so->so_snd); 3384786Swnj return (error); 3394786Swnj } 3404786Swnj 3414927Swnj soreceive(so, asa) 3424786Swnj register struct socket *so; 3434927Swnj struct sockaddr *asa; 3444786Swnj { 3454786Swnj register struct mbuf *m, *n; 3464916Swnj u_int len; 347*5423Swnj int eor, s, error = 0, cnt = u.u_count; 348*5423Swnj caddr_t base = u.u_base; 3494786Swnj 3504927Swnj COUNT(SORECEIVE); 3514890Swnj restart: 3524890Swnj sblock(&so->so_rcv); 3534890Swnj s = splnet(); 3544890Swnj 3554890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3564786Swnj if (so->so_rcv.sb_cc == 0) { 3575168Swnj if (so->so_error) { 3585168Swnj error = so->so_error; 3595168Swnj so->so_error = 0; 3605168Swnj splx(s); 3615168Swnj goto release; 3625168Swnj } 3634890Swnj if (so->so_state & SS_CANTRCVMORE) { 3644890Swnj splx(s); 3654890Swnj goto release; 3664890Swnj } 3675015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3685015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3695015Sroot rcverr(ENOTCONN); 3705388Sroot if (so->so_options & SO_NONBLOCKING) 3715168Swnj rcverr(EWOULDBLOCK); 3724890Swnj sbunlock(&so->so_rcv); 3734971Swnj sbwait(&so->so_rcv); 3745012Swnj splx(s); 3754890Swnj goto restart; 3764786Swnj } 3774829Swnj m = so->so_rcv.sb_mb; 3784786Swnj if (m == 0) 3794786Swnj panic("receive"); 3805039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 3815039Swnj if (m->m_len != sizeof (struct sockaddr)) 3825039Swnj panic("soreceive addr"); 3835039Swnj if (asa) 3845039Swnj bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 3855039Swnj so->so_rcv.sb_cc -= m->m_len; 3865039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 3875018Swnj m = m_free(m); 3884890Swnj if (m == 0) 3894890Swnj panic("receive 2"); 3905018Swnj so->so_rcv.sb_mb = m; 3914890Swnj } 392*5423Swnj so->so_state &= ~SS_RCVATMARK; 393*5423Swnj if (so->so_oobmark && cnt > so->so_oobmark) 394*5423Swnj cnt = so->so_oobmark; 3954786Swnj eor = 0; 3964786Swnj do { 397*5423Swnj len = MIN(m->m_len, cnt); 3984786Swnj if (len == m->m_len) { 3994786Swnj eor = (int)m->m_act; 4004890Swnj sbfree(&so->so_rcv, m); 4015358Sroot so->so_rcv.sb_mb = m->m_next; 4024786Swnj } 4034786Swnj splx(s); 4044786Swnj iomove(mtod(m, caddr_t), len, B_READ); 405*5423Swnj cnt -= len; 4064786Swnj s = splnet(); 4074786Swnj if (len == m->m_len) { 4084786Swnj MFREE(m, n); 4094786Swnj } else { 4104786Swnj m->m_off += len; 4114786Swnj m->m_len -= len; 4124829Swnj so->so_rcv.sb_cc -= len; 4134786Swnj } 414*5423Swnj } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 4154786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4164786Swnj do { 4174786Swnj if (m == 0) 4184890Swnj panic("receive 3"); 4194890Swnj sbfree(&so->so_rcv, m); 4204786Swnj eor = (int)m->m_act; 4214786Swnj so->so_rcv.sb_mb = m->m_next; 4224786Swnj MFREE(m, n); 4234890Swnj m = n; 4244786Swnj } while (eor == 0); 4254890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 4264890Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 427*5423Swnj if (so->so_oobmark) { 428*5423Swnj so->so_oobmark -= u.u_base - base; 429*5423Swnj if (so->so_oobmark == 0) 430*5423Swnj so->so_state |= SS_RCVATMARK; 431*5423Swnj } 4324890Swnj release: 4334916Swnj sbunlock(&so->so_rcv); 4344890Swnj splx(s); 4354916Swnj return (error); 4364786Swnj } 4374786Swnj 438*5423Swnj sohasoutofband(so) 439*5423Swnj struct socket *so; 440*5423Swnj { 441*5423Swnj 442*5423Swnj if (so->so_pgrp == 0) 443*5423Swnj return; 444*5423Swnj if (so->so_pgrp > 0) 445*5423Swnj gsignal(so->so_pgrp, SIGURG); 446*5423Swnj else 447*5423Swnj psignal(-so->so_pgrp, SIGURG); 448*5423Swnj } 449*5423Swnj 4504916Swnj /*ARGSUSED*/ 4514916Swnj soioctl(so, cmd, cmdp) 4524829Swnj register struct socket *so; 4534829Swnj int cmd; 4544829Swnj register caddr_t cmdp; 4554786Swnj { 4564786Swnj 4574927Swnj COUNT(SOIOCTL); 4585358Sroot switch (cmd) { 4594829Swnj 4605388Sroot case FIONBIO: { 4615388Sroot int nbio; 4625388Sroot if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 4635388Sroot u.u_error = EFAULT; 4645388Sroot return; 4655388Sroot } 4665388Sroot if (nbio) 4675388Sroot so->so_options |= SO_NONBLOCKING; 4685388Sroot else 4695388Sroot so->so_options &= ~SO_NONBLOCKING; 4705388Sroot return; 4715388Sroot } 4725388Sroot 4735388Sroot case FIOASYNC: { 4745388Sroot int async; 4755388Sroot if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 4765388Sroot u.u_error = EFAULT; 4775388Sroot return; 4785388Sroot } 4795388Sroot if (async) 4805388Sroot ; 4815388Sroot else 4825388Sroot ; 4835388Sroot return; 4845388Sroot } 4855388Sroot 4865388Sroot case SIOCSKEEP: { 4875388Sroot int keep; 4885388Sroot if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 4895388Sroot u.u_error = EFAULT; 4905388Sroot return; 4915388Sroot } 4925388Sroot if (keep) 4935388Sroot so->so_options &= ~SO_NOKEEPALIVE; 4945388Sroot else 4955388Sroot so->so_options |= SO_NOKEEPALIVE; 4965388Sroot return; 4975388Sroot } 4985388Sroot 4995388Sroot case SIOCGKEEP: { 5005388Sroot int keep = (so->so_options & SO_NOKEEPALIVE) == 0; 5015388Sroot if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 5025388Sroot u.u_error = EFAULT; 5035388Sroot return; 5045388Sroot } 5055388Sroot 5065388Sroot case SIOCSLINGER: { 5075388Sroot int linger; 5085388Sroot if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 5095388Sroot u.u_error = EFAULT; 5105388Sroot return; 5115388Sroot } 5125388Sroot so->so_linger = linger; 5135388Sroot if (so->so_linger) 5145388Sroot so->so_options &= ~SO_DONTLINGER; 5155388Sroot else 5165388Sroot so->so_options |= SO_DONTLINGER; 5175388Sroot return; 5185388Sroot } 5195388Sroot 5205388Sroot case SIOCGLINGER: { 5215388Sroot int linger = so->so_linger; 5225388Sroot if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 5235388Sroot u.u_error = EFAULT; 5245388Sroot return; 5255388Sroot } 5265388Sroot } 527*5423Swnj case SIOCSPGRP: { 528*5423Swnj int pgrp; 529*5423Swnj if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 530*5423Swnj u.u_error = EFAULT; 531*5423Swnj return; 532*5423Swnj } 533*5423Swnj so->so_pgrp = pgrp; 534*5423Swnj return; 535*5423Swnj } 5365388Sroot 537*5423Swnj case SIOCGPGRP: { 538*5423Swnj int pgrp = so->so_pgrp; 539*5423Swnj if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 540*5423Swnj u.u_error = EFAULT; 541*5423Swnj return; 542*5423Swnj } 543*5423Swnj } 544*5423Swnj 5455281Sroot case SIOCDONE: { 5465281Sroot int flags; 5475281Sroot if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 5485281Sroot u.u_error = EFAULT; 5495281Sroot return; 5505281Sroot } 5515388Sroot flags++; 5525281Sroot if (flags & FREAD) { 5535281Sroot int s = splimp(); 5545281Sroot socantrcvmore(so); 5555281Sroot sbflush(&so->so_rcv); 5565281Sroot } 5575281Sroot if (flags & FWRITE) 5585404Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 5595281Sroot return; 5604829Swnj } 5615281Sroot 562*5423Swnj case SIOCSENDOOB: { 563*5423Swnj char oob; 564*5423Swnj struct mbuf *m; 565*5423Swnj if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 566*5423Swnj u.u_error = EFAULT; 567*5423Swnj return; 568*5423Swnj } 569*5423Swnj m = m_get(M_DONTWAIT); 570*5423Swnj if (m == 0) { 571*5423Swnj u.u_error = ENOBUFS; 572*5423Swnj return; 573*5423Swnj } 574*5423Swnj m->m_off = MMINOFF; 575*5423Swnj m->m_len = 1; 576*5423Swnj *mtod(m, caddr_t) = oob; 577*5423Swnj (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 578*5423Swnj return; 5795281Sroot } 580*5423Swnj 581*5423Swnj case SIOCRCVOOB: { 582*5423Swnj struct mbuf *m = m_get(M_DONTWAIT); 583*5423Swnj if (m == 0) { 584*5423Swnj u.u_error = ENOBUFS; 585*5423Swnj return; 586*5423Swnj } 587*5423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 588*5423Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 589*5423Swnj if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 590*5423Swnj u.u_error = EFAULT; 591*5423Swnj return; 592*5423Swnj } 593*5423Swnj m_free(m); 594*5423Swnj return; 595*5423Swnj } 596*5423Swnj 597*5423Swnj case SIOCATMARK: { 598*5423Swnj int atmark = (so->so_state&SS_RCVATMARK) != 0; 599*5423Swnj if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 600*5423Swnj u.u_error = EFAULT; 601*5423Swnj return; 602*5423Swnj } 603*5423Swnj return; 604*5423Swnj } 605*5423Swnj } 6064829Swnj switch (so->so_type) { 6074829Swnj 6084829Swnj case SOCK_STREAM: 6094829Swnj break; 6104829Swnj 6114829Swnj case SOCK_DGRAM: 6124829Swnj break; 6134829Swnj 6144829Swnj case SOCK_RDM: 6154829Swnj break; 6164829Swnj 6174829Swnj case SOCK_RAW: 6184829Swnj break; 6194829Swnj } 6204786Swnj } 621