1*7491Ssam /* uipc_socket.c 4.43 82/07/22 */ 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" 204786Swnj 214786Swnj /* 224890Swnj * Socket support routines. 234890Swnj * 244890Swnj * DEAL WITH INTERRUPT NOTIFICATION. 254786Swnj */ 264786Swnj 274786Swnj /* 284786Swnj * Create a socket. 294786Swnj */ 304927Swnj socreate(aso, type, asp, asa, options) 314786Swnj struct socket **aso; 324786Swnj int type; 334927Swnj struct sockproto *asp; 344927Swnj struct sockaddr *asa; 354829Swnj int options; 364786Swnj { 374786Swnj register struct protosw *prp; 384786Swnj register struct socket *so; 394786Swnj struct mbuf *m; 404890Swnj int pf, proto, error; 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) { 847180Swnj if (so->so_snd.sb_mbmax || so->so_rcv.sb_mbmax) 857180Swnj panic("socreate"); 867180Swnj so->so_state |= SS_USERGONE; 877180Swnj sofree(so); 884890Swnj return (error); 894786Swnj } 904786Swnj *aso = so; 914786Swnj return (0); 924786Swnj } 934786Swnj 944916Swnj sofree(so) 954916Swnj struct socket *so; 964916Swnj { 974916Swnj 984950Swnj if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) 994950Swnj return; 1004950Swnj sbrelease(&so->so_snd); 1014950Swnj sbrelease(&so->so_rcv); 1024971Swnj (void) m_free(dtom(so)); 1034916Swnj } 1044916Swnj 1054786Swnj /* 1064890Swnj * Close a socket on last file table reference removal. 1074890Swnj * Initiate disconnect if connected. 1084890Swnj * Free socket when disconnect complete. 1095580Sroot * 1105580Sroot * THIS IS REALLY A UNIX INTERFACE ROUTINE 1114829Swnj */ 1125580Sroot soclose(so, exiting) 1134829Swnj register struct socket *so; 1145580Sroot int exiting; 1154829Swnj { 1164890Swnj int s = splnet(); /* conservative */ 1174829Swnj 1184890Swnj if (so->so_pcb == 0) 1194890Swnj goto discard; 1206259Sroot if (exiting) 1216259Sroot so->so_options |= SO_KEEPALIVE; 1224890Swnj if (so->so_state & SS_ISCONNECTED) { 1234890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1244927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1254890Swnj if (u.u_error) { 1265580Sroot if (exiting) 1275580Sroot goto drop; 1284890Swnj splx(s); 1294890Swnj return; 1304890Swnj } 1314890Swnj } 1325388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1335281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1346214Swnj (so->so_state & SS_NBIO) && 1355580Sroot exiting == 0) { 1365281Sroot u.u_error = EINPROGRESS; 1375281Sroot splx(s); 1385281Sroot return; 1395281Sroot } 1405580Sroot /* should use tsleep here, for at most linger */ 1415281Sroot while (so->so_state & SS_ISCONNECTED) 1425281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1434890Swnj } 1444890Swnj } 1455580Sroot drop: 1466880Ssam if (so->so_pcb) { 1476880Ssam u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 1486880Ssam if (exiting == 0 && u.u_error) { 1496880Ssam splx(s); 1506880Ssam return; 1516880Ssam } 1526880Ssam } 1534890Swnj discard: 1544950Swnj so->so_state |= SS_USERGONE; 1554950Swnj sofree(so); 1564890Swnj splx(s); 1574829Swnj } 1584829Swnj 1594916Swnj /*ARGSUSED*/ 1604890Swnj sostat(so, sb) 1614829Swnj struct socket *so; 1624890Swnj struct stat *sb; 1634829Swnj { 1644829Swnj 1655303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1665303Sroot return (0); /* XXX */ 1674829Swnj } 1684829Swnj 1694829Swnj /* 1704927Swnj * Accept connection on a socket. 1714927Swnj */ 1724927Swnj soaccept(so, asa) 1734927Swnj struct socket *so; 1744927Swnj struct sockaddr *asa; 1754927Swnj { 1764927Swnj int s = splnet(); 1774927Swnj int error; 1784927Swnj 1794927Swnj if ((so->so_options & SO_ACCEPTCONN) == 0) { 1804927Swnj error = EINVAL; /* XXX */ 1814927Swnj goto bad; 1824927Swnj } 1835265Swnj if ((so->so_state & SS_CONNAWAITING) == 0) { 1845265Swnj error = ENOTCONN; 1855265Swnj goto bad; 1865265Swnj } 1875265Swnj so->so_state &= ~SS_CONNAWAITING; 1884927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 1894927Swnj bad: 1904927Swnj splx(s); 1914927Swnj return (error); 1924927Swnj } 1934927Swnj 1944927Swnj /* 1954890Swnj * Connect socket to a specified address. 1964890Swnj * If already connected or connecting, then avoid 1974890Swnj * the protocol entry, to keep its job simpler. 1984786Swnj */ 1994927Swnj soconnect(so, asa) 2004786Swnj struct socket *so; 2014927Swnj struct sockaddr *asa; 2024786Swnj { 2034890Swnj int s = splnet(); 2044890Swnj int error; 2054786Swnj 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 2294890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2304890Swnj error = ENOTCONN; 2314890Swnj goto bad; 2324890Swnj } 2334890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2344890Swnj error = EALREADY; 2354890Swnj goto bad; 2364890Swnj } 2374927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 2384890Swnj bad: 2394890Swnj splx(s); 2404890Swnj return (error); 2414786Swnj } 2424786Swnj 2434786Swnj /* 2444890Swnj * Send on a socket. 2454890Swnj * If send must go all at once and message is larger than 2464890Swnj * send buffering, then hard error. 2474890Swnj * Lock against other senders. 2484890Swnj * If must go all at once and not enough room now, then 2494890Swnj * inform user that this would block and do nothing. 2504786Swnj */ 2514927Swnj sosend(so, asa) 2524786Swnj register struct socket *so; 2534927Swnj struct sockaddr *asa; 2544786Swnj { 2554890Swnj struct mbuf *top = 0; 2564890Swnj register struct mbuf *m, **mp = ⊤ 2574916Swnj register u_int len; 2584916Swnj int error = 0, space, s; 2594786Swnj 2604890Swnj if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 2614890Swnj return (EMSGSIZE); 2626419Sroot #ifdef notdef 2636419Sroot /* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING */ 2646214Swnj if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 2654890Swnj return (EWOULDBLOCK); 2666419Sroot #endif 2676419Sroot restart: 2684890Swnj sblock(&so->so_snd); 2694890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2704890Swnj 2716419Sroot again: 2724890Swnj s = splnet(); 2736419Sroot if (so->so_state & SS_CANTSENDMORE) { 2746419Sroot psignal(u.u_procp, SIGPIPE); 2756419Sroot snderr(EPIPE); 2766419Sroot } 2775168Swnj if (so->so_error) { 2785168Swnj error = so->so_error; 2796419Sroot so->so_error = 0; /* ??? */ 2805168Swnj splx(s); 2815168Swnj goto release; 2825168Swnj } 2834890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2844890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2854890Swnj snderr(ENOTCONN); 2864927Swnj if (asa == 0) 2874890Swnj snderr(EDESTADDRREQ); 2884890Swnj } 2894890Swnj if (top) { 2904927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 2916419Sroot top = 0; 2924890Swnj if (error) { 2934890Swnj splx(s); 2944786Swnj goto release; 2954786Swnj } 2964890Swnj mp = ⊤ 2974786Swnj } 2984979Swnj if (u.u_count == 0) { 2994979Swnj splx(s); 3004979Swnj goto release; 3014979Swnj } 3025018Swnj space = sbspace(&so->so_snd); 3035610Swnj if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 3046214Swnj if (so->so_state & SS_NBIO) 3054890Swnj snderr(EWOULDBLOCK); 3064890Swnj sbunlock(&so->so_snd); 3074890Swnj sbwait(&so->so_snd); 3084890Swnj splx(s); 3096419Sroot goto restart; 3104786Swnj } 3114890Swnj splx(s); 3125018Swnj while (u.u_count && space > 0) { 3134890Swnj MGET(m, 1); 3144890Swnj if (m == NULL) { 3156419Sroot error = ENOBUFS; /* SIGPIPE? */ 3164890Swnj goto release; 3174786Swnj } 3185095Swnj if (u.u_count >= CLBYTES && space >= CLBYTES) { 3194890Swnj register struct mbuf *p; 3205095Swnj MCLGET(p, 1); 3214890Swnj if (p == 0) 3224890Swnj goto nopages; 3234890Swnj m->m_off = (int)p - (int)m; 3245095Swnj len = CLBYTES; 3254890Swnj } else { 3264786Swnj nopages: 3274890Swnj m->m_off = MMINOFF; 3284890Swnj len = MIN(MLEN, u.u_count); 3294786Swnj } 3304890Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3314890Swnj m->m_len = len; 3324890Swnj *mp = m; 3334890Swnj mp = &m->m_next; 3345018Swnj space = sbspace(&so->so_snd); 3354786Swnj } 3364890Swnj goto again; 3374890Swnj 3384786Swnj release: 3394890Swnj sbunlock(&so->so_snd); 3406419Sroot if (top) 3416419Sroot m_freem(top); 3424786Swnj return (error); 3434786Swnj } 3444786Swnj 3454927Swnj soreceive(so, asa) 3464786Swnj register struct socket *so; 3474927Swnj struct sockaddr *asa; 3484786Swnj { 3494786Swnj register struct mbuf *m, *n; 3504916Swnj u_int len; 3515423Swnj int eor, s, error = 0, cnt = u.u_count; 3525423Swnj caddr_t base = u.u_base; 3534786Swnj 3544890Swnj restart: 3554890Swnj sblock(&so->so_rcv); 3564890Swnj s = splnet(); 3574890Swnj 3584890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3594786Swnj if (so->so_rcv.sb_cc == 0) { 3605168Swnj if (so->so_error) { 3615168Swnj error = so->so_error; 3625168Swnj so->so_error = 0; 3635168Swnj splx(s); 3645168Swnj goto release; 3655168Swnj } 3664890Swnj if (so->so_state & SS_CANTRCVMORE) { 3674890Swnj splx(s); 3684890Swnj goto release; 3694890Swnj } 3705015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3715015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3725015Sroot rcverr(ENOTCONN); 3736214Swnj if (so->so_state & SS_NBIO) 3745168Swnj rcverr(EWOULDBLOCK); 3754890Swnj sbunlock(&so->so_rcv); 3764971Swnj sbwait(&so->so_rcv); 3775012Swnj splx(s); 3784890Swnj goto restart; 3794786Swnj } 3804829Swnj m = so->so_rcv.sb_mb; 3814786Swnj if (m == 0) 3824786Swnj panic("receive"); 3835039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 3845039Swnj if (m->m_len != sizeof (struct sockaddr)) 3855039Swnj panic("soreceive addr"); 3865039Swnj if (asa) 3875039Swnj bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 3885039Swnj so->so_rcv.sb_cc -= m->m_len; 3895039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 3905018Swnj m = m_free(m); 3914890Swnj if (m == 0) 3924890Swnj panic("receive 2"); 3935018Swnj so->so_rcv.sb_mb = m; 3944890Swnj } 3955423Swnj so->so_state &= ~SS_RCVATMARK; 3965423Swnj if (so->so_oobmark && cnt > so->so_oobmark) 3975423Swnj cnt = so->so_oobmark; 3984786Swnj eor = 0; 3994786Swnj do { 4005423Swnj len = MIN(m->m_len, cnt); 4014786Swnj splx(s); 4024786Swnj iomove(mtod(m, caddr_t), len, B_READ); 4035423Swnj cnt -= len; 4044786Swnj s = splnet(); 4054786Swnj if (len == m->m_len) { 4066091Sroot eor = (int)m->m_act; 4076091Sroot sbfree(&so->so_rcv, m); 4086091Sroot so->so_rcv.sb_mb = m->m_next; 4094786Swnj MFREE(m, n); 4104786Swnj } else { 4114786Swnj m->m_off += len; 4124786Swnj m->m_len -= len; 4134829Swnj so->so_rcv.sb_cc -= len; 4144786Swnj } 4155423Swnj } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 4164786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4174786Swnj do { 4184786Swnj if (m == 0) 4194890Swnj panic("receive 3"); 4204890Swnj sbfree(&so->so_rcv, m); 4214786Swnj eor = (int)m->m_act; 4224786Swnj so->so_rcv.sb_mb = m->m_next; 4234786Swnj MFREE(m, n); 4244890Swnj m = n; 4254786Swnj } while (eor == 0); 4264890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 4274890Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 4285423Swnj if (so->so_oobmark) { 4295423Swnj so->so_oobmark -= u.u_base - base; 4305423Swnj if (so->so_oobmark == 0) 4315423Swnj so->so_state |= SS_RCVATMARK; 4325423Swnj } 4334890Swnj release: 4344916Swnj sbunlock(&so->so_rcv); 4354890Swnj splx(s); 4364916Swnj return (error); 4374786Swnj } 4384786Swnj 4395423Swnj sohasoutofband(so) 4405423Swnj struct socket *so; 4415423Swnj { 4425423Swnj 4435423Swnj if (so->so_pgrp == 0) 4445423Swnj return; 4455423Swnj if (so->so_pgrp > 0) 4465423Swnj gsignal(so->so_pgrp, SIGURG); 4475429Swnj else { 4485429Swnj struct proc *p = pfind(-so->so_pgrp); 4495429Swnj 4505429Swnj if (p) 4515429Swnj psignal(p, SIGURG); 4525429Swnj } 4535423Swnj } 4545423Swnj 4554916Swnj /*ARGSUSED*/ 4564916Swnj soioctl(so, cmd, cmdp) 4574829Swnj register struct socket *so; 4584829Swnj int cmd; 4594829Swnj register caddr_t cmdp; 4604786Swnj { 4614786Swnj 4625358Sroot switch (cmd) { 4634829Swnj 4645388Sroot case FIONBIO: { 4655388Sroot int nbio; 4665388Sroot if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 4675388Sroot u.u_error = EFAULT; 4685388Sroot return; 4695388Sroot } 4705388Sroot if (nbio) 4716214Swnj so->so_state |= SS_NBIO; 4725388Sroot else 4736214Swnj so->so_state &= ~SS_NBIO; 4745388Sroot return; 4755388Sroot } 4765388Sroot 4775388Sroot case FIOASYNC: { 4785388Sroot int async; 4795388Sroot if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 4805388Sroot u.u_error = EFAULT; 4815388Sroot return; 4825388Sroot } 4835388Sroot if (async) 4846214Swnj so->so_state |= SS_ASYNC; 4855388Sroot else 4866214Swnj so->so_state &= ~SS_ASYNC; 4875388Sroot return; 4885388Sroot } 4895388Sroot 4905388Sroot case SIOCSKEEP: { 4915388Sroot int keep; 4925388Sroot if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 4935388Sroot u.u_error = EFAULT; 4945388Sroot return; 4955388Sroot } 4965388Sroot if (keep) 497*7491Ssam so->so_options |= SO_KEEPALIVE; 498*7491Ssam else 4996214Swnj so->so_options &= ~SO_KEEPALIVE; 5005388Sroot return; 5015388Sroot } 5025388Sroot 5035388Sroot case SIOCGKEEP: { 5046214Swnj int keep = (so->so_options & SO_KEEPALIVE) != 0; 5055388Sroot if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 5065388Sroot u.u_error = EFAULT; 5075388Sroot return; 5085388Sroot } 5095388Sroot 5105388Sroot case SIOCSLINGER: { 5115388Sroot int linger; 5125388Sroot if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 5135388Sroot u.u_error = EFAULT; 5145388Sroot return; 5155388Sroot } 5165388Sroot so->so_linger = linger; 5175388Sroot if (so->so_linger) 5185388Sroot so->so_options &= ~SO_DONTLINGER; 5195388Sroot else 5205388Sroot so->so_options |= SO_DONTLINGER; 5215388Sroot return; 5225388Sroot } 5235388Sroot 5245388Sroot case SIOCGLINGER: { 5255388Sroot int linger = so->so_linger; 5265388Sroot if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 5275388Sroot u.u_error = EFAULT; 5285388Sroot return; 5295388Sroot } 5305388Sroot } 5315423Swnj case SIOCSPGRP: { 5325423Swnj int pgrp; 5335423Swnj if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 5345423Swnj u.u_error = EFAULT; 5355423Swnj return; 5365423Swnj } 5375423Swnj so->so_pgrp = pgrp; 5385423Swnj return; 5395423Swnj } 5405388Sroot 5415423Swnj case SIOCGPGRP: { 5425423Swnj int pgrp = so->so_pgrp; 5435423Swnj if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 5445423Swnj u.u_error = EFAULT; 5455423Swnj return; 5465423Swnj } 5475423Swnj } 5485423Swnj 5495281Sroot case SIOCDONE: { 5505281Sroot int flags; 5515281Sroot if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 5525281Sroot u.u_error = EFAULT; 5535281Sroot return; 5545281Sroot } 5555388Sroot flags++; 5565281Sroot if (flags & FREAD) { 5575281Sroot int s = splimp(); 5585281Sroot socantrcvmore(so); 5595281Sroot sbflush(&so->so_rcv); 5606140Ssam splx(s); 5615281Sroot } 5625281Sroot if (flags & FWRITE) 5635404Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 5645281Sroot return; 5654829Swnj } 5665281Sroot 5675423Swnj case SIOCSENDOOB: { 5685423Swnj char oob; 5695423Swnj struct mbuf *m; 5705423Swnj if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 5715423Swnj u.u_error = EFAULT; 5725423Swnj return; 5735423Swnj } 5745423Swnj m = m_get(M_DONTWAIT); 5755423Swnj if (m == 0) { 5765423Swnj u.u_error = ENOBUFS; 5775423Swnj return; 5785423Swnj } 5795423Swnj m->m_off = MMINOFF; 5805423Swnj m->m_len = 1; 5815423Swnj *mtod(m, caddr_t) = oob; 5825423Swnj (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 5835423Swnj return; 5845281Sroot } 5855423Swnj 5865423Swnj case SIOCRCVOOB: { 5875423Swnj struct mbuf *m = m_get(M_DONTWAIT); 5885423Swnj if (m == 0) { 5895423Swnj u.u_error = ENOBUFS; 5905423Swnj return; 5915423Swnj } 5925423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 5935423Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 5945423Swnj if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 5955423Swnj u.u_error = EFAULT; 5965423Swnj return; 5975423Swnj } 5985423Swnj m_free(m); 5995423Swnj return; 6005423Swnj } 6015423Swnj 6025423Swnj case SIOCATMARK: { 6035423Swnj int atmark = (so->so_state&SS_RCVATMARK) != 0; 6045423Swnj if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 6055423Swnj u.u_error = EFAULT; 6065423Swnj return; 6075423Swnj } 6085423Swnj return; 6095423Swnj } 6106355Ssam 6116355Ssam /* routing table update calls */ 6126355Ssam case SIOCADDRT: 6136355Ssam case SIOCDELRT: 6146355Ssam case SIOCCHGRT: { 6156355Ssam struct rtentry route; 6166355Ssam if (!suser()) 6176355Ssam return; 6186355Ssam if (copyin(cmdp, (caddr_t)&route, sizeof (route))) { 6196355Ssam u.u_error = EFAULT; 6206355Ssam return; 6216355Ssam } 6226355Ssam u.u_error = rtrequest(cmd, &route); 6236355Ssam return; 6246355Ssam } 6256355Ssam 6265445Swnj /* type/protocol specific ioctls */ 6275423Swnj } 6285445Swnj u.u_error = EOPNOTSUPP; 6294786Swnj } 630