1*7507Sroot /* socket.c 4.43 82/07/21 */ 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; 73*7507Sroot if (options & SO_ACCEPTCONN) { 74*7507Sroot so->so_q = so; 75*7507Sroot so->so_q0 = so; 76*7507Sroot so->so_qlimit = (so->so_options & SO_NEWFDONCONN) ? 5 : 1; 77*7507Sroot } 786214Swnj so->so_state = 0; 796214Swnj if (u.u_uid == 0) 806214Swnj so->so_state = SS_PRIV; 814786Swnj 824786Swnj /* 834890Swnj * Attach protocol to socket, initializing 844890Swnj * and reserving resources. 854786Swnj */ 864786Swnj so->so_proto = prp; 874979Swnj error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 884979Swnj if (error) { 89*7507Sroot so->so_state |= SS_NOFDREF; 907180Swnj sofree(so); 914890Swnj return (error); 924786Swnj } 934786Swnj *aso = so; 944786Swnj return (0); 954786Swnj } 964786Swnj 974916Swnj sofree(so) 984916Swnj struct socket *so; 994916Swnj { 1004916Swnj 101*7507Sroot if (so->so_head) { 102*7507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 103*7507Sroot panic("sofree dq"); 104*7507Sroot so->so_head = 0; 105*7507Sroot } 106*7507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1074950Swnj return; 1084950Swnj sbrelease(&so->so_snd); 1094950Swnj sbrelease(&so->so_rcv); 1104971Swnj (void) m_free(dtom(so)); 1114916Swnj } 1124916Swnj 1134786Swnj /* 1144890Swnj * Close a socket on last file table reference removal. 1154890Swnj * Initiate disconnect if connected. 1164890Swnj * Free socket when disconnect complete. 1174829Swnj */ 1185580Sroot soclose(so, exiting) 1194829Swnj register struct socket *so; 1205580Sroot int exiting; 1214829Swnj { 1224890Swnj int s = splnet(); /* conservative */ 123*7507Sroot register struct socket *so2; 1244829Swnj 125*7507Sroot if (so->so_options & SO_ACCEPTCONN) { 126*7507Sroot while (so->so_q0 != so) 127*7507Sroot soclose(so->so_q0, 1); 128*7507Sroot while (so->so_q != so) 129*7507Sroot soclose(so->so_q, 1); 130*7507Sroot } 1314890Swnj if (so->so_pcb == 0) 1324890Swnj goto discard; 1336259Sroot if (exiting) 1346259Sroot so->so_options |= SO_KEEPALIVE; 1354890Swnj if (so->so_state & SS_ISCONNECTED) { 1364890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1374927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1384890Swnj if (u.u_error) { 1395580Sroot if (exiting) 1405580Sroot goto drop; 1414890Swnj splx(s); 1424890Swnj return; 1434890Swnj } 1444890Swnj } 1455388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1465281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1476214Swnj (so->so_state & SS_NBIO) && 1485580Sroot exiting == 0) { 1495281Sroot u.u_error = EINPROGRESS; 1505281Sroot splx(s); 1515281Sroot return; 1525281Sroot } 1535580Sroot /* should use tsleep here, for at most linger */ 1545281Sroot while (so->so_state & SS_ISCONNECTED) 1555281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1564890Swnj } 1574890Swnj } 1585580Sroot drop: 1596880Ssam if (so->so_pcb) { 1606880Ssam u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 1616880Ssam if (exiting == 0 && u.u_error) { 1626880Ssam splx(s); 1636880Ssam return; 1646880Ssam } 1656880Ssam } 1664890Swnj discard: 167*7507Sroot so->so_state |= SS_NOFDREF; 1684950Swnj sofree(so); 1694890Swnj splx(s); 1704829Swnj } 1714829Swnj 1724916Swnj /*ARGSUSED*/ 1734890Swnj sostat(so, sb) 1744829Swnj struct socket *so; 1754890Swnj struct stat *sb; 1764829Swnj { 1774829Swnj 1785303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1795303Sroot return (0); /* XXX */ 1804829Swnj } 1814829Swnj 1824829Swnj /* 1834927Swnj * Accept connection on a socket. 1844927Swnj */ 1854927Swnj soaccept(so, asa) 1864927Swnj struct socket *so; 1874927Swnj struct sockaddr *asa; 1884927Swnj { 1894927Swnj int s = splnet(); 1904927Swnj int error; 1914927Swnj 1924927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 1934927Swnj splx(s); 1944927Swnj return (error); 1954927Swnj } 1964927Swnj 1974927Swnj /* 1984890Swnj * Connect socket to a specified address. 1994890Swnj * If already connected or connecting, then avoid 2004890Swnj * the protocol entry, to keep its job simpler. 2014786Swnj */ 2024927Swnj soconnect(so, asa) 2034786Swnj struct socket *so; 2044927Swnj struct sockaddr *asa; 2054786Swnj { 2064890Swnj int s = splnet(); 2074890Swnj int error; 2084786Swnj 2094890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2104890Swnj error = EISCONN; 2114890Swnj goto bad; 2124890Swnj } 2134927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 2144890Swnj bad: 2154890Swnj splx(s); 2164890Swnj return (error); 2174786Swnj } 2184786Swnj 2194786Swnj /* 2204890Swnj * Disconnect from a socket. 2214890Swnj * Address parameter is from system call for later multicast 2224890Swnj * protocols. Check to make sure that connected and no disconnect 2234890Swnj * in progress (for protocol's sake), and then invoke protocol. 2244786Swnj */ 2254927Swnj sodisconnect(so, asa) 2264786Swnj struct socket *so; 2274927Swnj struct sockaddr *asa; 2284786Swnj { 2294890Swnj int s = splnet(); 2304890Swnj int error; 2314786Swnj 2324890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2334890Swnj error = ENOTCONN; 2344890Swnj goto bad; 2354890Swnj } 2364890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2374890Swnj error = EALREADY; 2384890Swnj goto bad; 2394890Swnj } 2404927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 2414890Swnj bad: 2424890Swnj splx(s); 2434890Swnj return (error); 2444786Swnj } 2454786Swnj 2464786Swnj /* 2474890Swnj * Send on a socket. 2484890Swnj * If send must go all at once and message is larger than 2494890Swnj * send buffering, then hard error. 2504890Swnj * Lock against other senders. 2514890Swnj * If must go all at once and not enough room now, then 2524890Swnj * inform user that this would block and do nothing. 2534786Swnj */ 2544927Swnj sosend(so, asa) 2554786Swnj register struct socket *so; 2564927Swnj struct sockaddr *asa; 2574786Swnj { 2584890Swnj struct mbuf *top = 0; 2594890Swnj register struct mbuf *m, **mp = ⊤ 2604916Swnj register u_int len; 2614916Swnj int error = 0, space, s; 2624786Swnj 2634890Swnj if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 2644890Swnj return (EMSGSIZE); 2656419Sroot #ifdef notdef 2666419Sroot /* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING */ 2676214Swnj if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 2684890Swnj return (EWOULDBLOCK); 2696419Sroot #endif 2706419Sroot restart: 2714890Swnj sblock(&so->so_snd); 2724890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2734890Swnj 2746419Sroot again: 2754890Swnj s = splnet(); 2766419Sroot if (so->so_state & SS_CANTSENDMORE) { 2776419Sroot psignal(u.u_procp, SIGPIPE); 2786419Sroot snderr(EPIPE); 2796419Sroot } 2805168Swnj if (so->so_error) { 2815168Swnj error = so->so_error; 2826419Sroot so->so_error = 0; /* ??? */ 2835168Swnj splx(s); 2845168Swnj goto release; 2855168Swnj } 2864890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2874890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2884890Swnj snderr(ENOTCONN); 2894927Swnj if (asa == 0) 2904890Swnj snderr(EDESTADDRREQ); 2914890Swnj } 2924890Swnj if (top) { 2934927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 2946419Sroot top = 0; 2954890Swnj if (error) { 2964890Swnj splx(s); 2974786Swnj goto release; 2984786Swnj } 2994890Swnj mp = ⊤ 3004786Swnj } 3014979Swnj if (u.u_count == 0) { 3024979Swnj splx(s); 3034979Swnj goto release; 3044979Swnj } 3055018Swnj space = sbspace(&so->so_snd); 3065610Swnj if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 3076214Swnj if (so->so_state & SS_NBIO) 3084890Swnj snderr(EWOULDBLOCK); 3094890Swnj sbunlock(&so->so_snd); 3104890Swnj sbwait(&so->so_snd); 3114890Swnj splx(s); 3126419Sroot goto restart; 3134786Swnj } 3144890Swnj splx(s); 3155018Swnj while (u.u_count && space > 0) { 3164890Swnj MGET(m, 1); 3174890Swnj if (m == NULL) { 3186419Sroot error = ENOBUFS; /* SIGPIPE? */ 3194890Swnj goto release; 3204786Swnj } 3215095Swnj if (u.u_count >= CLBYTES && space >= CLBYTES) { 3224890Swnj register struct mbuf *p; 3235095Swnj MCLGET(p, 1); 3244890Swnj if (p == 0) 3254890Swnj goto nopages; 3264890Swnj m->m_off = (int)p - (int)m; 3275095Swnj len = CLBYTES; 3284890Swnj } else { 3294786Swnj nopages: 3304890Swnj m->m_off = MMINOFF; 3314890Swnj len = MIN(MLEN, u.u_count); 3324786Swnj } 3334890Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3344890Swnj m->m_len = len; 3354890Swnj *mp = m; 3364890Swnj mp = &m->m_next; 3375018Swnj space = sbspace(&so->so_snd); 3384786Swnj } 3394890Swnj goto again; 3404890Swnj 3414786Swnj release: 3424890Swnj sbunlock(&so->so_snd); 3436419Sroot if (top) 3446419Sroot m_freem(top); 3454786Swnj return (error); 3464786Swnj } 3474786Swnj 3484927Swnj soreceive(so, asa) 3494786Swnj register struct socket *so; 3504927Swnj struct sockaddr *asa; 3514786Swnj { 3524786Swnj register struct mbuf *m, *n; 3534916Swnj u_int len; 3545423Swnj int eor, s, error = 0, cnt = u.u_count; 3555423Swnj caddr_t base = u.u_base; 3564786Swnj 3574890Swnj restart: 3584890Swnj sblock(&so->so_rcv); 3594890Swnj s = splnet(); 3604890Swnj 3614890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3624786Swnj if (so->so_rcv.sb_cc == 0) { 3635168Swnj if (so->so_error) { 3645168Swnj error = so->so_error; 3655168Swnj so->so_error = 0; 3665168Swnj splx(s); 3675168Swnj goto release; 3685168Swnj } 3694890Swnj if (so->so_state & SS_CANTRCVMORE) { 3704890Swnj splx(s); 3714890Swnj goto release; 3724890Swnj } 3735015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3745015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3755015Sroot rcverr(ENOTCONN); 3766214Swnj if (so->so_state & SS_NBIO) 3775168Swnj rcverr(EWOULDBLOCK); 3784890Swnj sbunlock(&so->so_rcv); 3794971Swnj sbwait(&so->so_rcv); 3805012Swnj splx(s); 3814890Swnj goto restart; 3824786Swnj } 3834829Swnj m = so->so_rcv.sb_mb; 3844786Swnj if (m == 0) 3854786Swnj panic("receive"); 3865039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 3875039Swnj if (m->m_len != sizeof (struct sockaddr)) 3885039Swnj panic("soreceive addr"); 3895039Swnj if (asa) 3905039Swnj bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 3915039Swnj so->so_rcv.sb_cc -= m->m_len; 3925039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 3935018Swnj m = m_free(m); 3944890Swnj if (m == 0) 3954890Swnj panic("receive 2"); 3965018Swnj so->so_rcv.sb_mb = m; 3974890Swnj } 3985423Swnj so->so_state &= ~SS_RCVATMARK; 3995423Swnj if (so->so_oobmark && cnt > so->so_oobmark) 4005423Swnj cnt = so->so_oobmark; 4014786Swnj eor = 0; 4024786Swnj do { 4035423Swnj len = MIN(m->m_len, cnt); 4044786Swnj splx(s); 4054786Swnj iomove(mtod(m, caddr_t), len, B_READ); 4065423Swnj cnt -= len; 4074786Swnj s = splnet(); 4084786Swnj if (len == m->m_len) { 4096091Sroot eor = (int)m->m_act; 4106091Sroot sbfree(&so->so_rcv, m); 4116091Sroot so->so_rcv.sb_mb = m->m_next; 4124786Swnj MFREE(m, n); 4134786Swnj } else { 4144786Swnj m->m_off += len; 4154786Swnj m->m_len -= len; 4164829Swnj so->so_rcv.sb_cc -= len; 4174786Swnj } 4185423Swnj } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 4194786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4204786Swnj do { 4214786Swnj if (m == 0) 4224890Swnj panic("receive 3"); 4234890Swnj sbfree(&so->so_rcv, m); 4244786Swnj eor = (int)m->m_act; 4254786Swnj so->so_rcv.sb_mb = m->m_next; 4264786Swnj MFREE(m, n); 4274890Swnj m = n; 4284786Swnj } while (eor == 0); 4294890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 4304890Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 4315423Swnj if (so->so_oobmark) { 4325423Swnj so->so_oobmark -= u.u_base - base; 4335423Swnj if (so->so_oobmark == 0) 4345423Swnj so->so_state |= SS_RCVATMARK; 4355423Swnj } 4364890Swnj release: 4374916Swnj sbunlock(&so->so_rcv); 4384890Swnj splx(s); 4394916Swnj return (error); 4404786Swnj } 4414786Swnj 4425423Swnj sohasoutofband(so) 4435423Swnj struct socket *so; 4445423Swnj { 4455423Swnj 4465423Swnj if (so->so_pgrp == 0) 4475423Swnj return; 4485423Swnj if (so->so_pgrp > 0) 4495423Swnj gsignal(so->so_pgrp, SIGURG); 4505429Swnj else { 4515429Swnj struct proc *p = pfind(-so->so_pgrp); 4525429Swnj 4535429Swnj if (p) 4545429Swnj psignal(p, SIGURG); 4555429Swnj } 4565423Swnj } 4575423Swnj 4584916Swnj /*ARGSUSED*/ 4594916Swnj soioctl(so, cmd, cmdp) 4604829Swnj register struct socket *so; 4614829Swnj int cmd; 4624829Swnj register caddr_t cmdp; 4634786Swnj { 4644786Swnj 4655358Sroot switch (cmd) { 4664829Swnj 4675388Sroot case FIONBIO: { 4685388Sroot int nbio; 4695388Sroot if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 4705388Sroot u.u_error = EFAULT; 4715388Sroot return; 4725388Sroot } 4735388Sroot if (nbio) 4746214Swnj so->so_state |= SS_NBIO; 4755388Sroot else 4766214Swnj so->so_state &= ~SS_NBIO; 4775388Sroot return; 4785388Sroot } 4795388Sroot 4805388Sroot case FIOASYNC: { 4815388Sroot int async; 4825388Sroot if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 4835388Sroot u.u_error = EFAULT; 4845388Sroot return; 4855388Sroot } 4865388Sroot if (async) 4876214Swnj so->so_state |= SS_ASYNC; 4885388Sroot else 4896214Swnj so->so_state &= ~SS_ASYNC; 4905388Sroot return; 4915388Sroot } 4925388Sroot 4935388Sroot case SIOCSKEEP: { 4945388Sroot int keep; 4955388Sroot if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 4965388Sroot u.u_error = EFAULT; 4975388Sroot return; 4985388Sroot } 4995388Sroot if (keep) 500*7507Sroot so->so_options &= ~SO_KEEPALIVE; 501*7507Sroot else 5027491Ssam so->so_options |= SO_KEEPALIVE; 5035388Sroot return; 5045388Sroot } 5055388Sroot 5065388Sroot case SIOCGKEEP: { 5076214Swnj int keep = (so->so_options & SO_KEEPALIVE) != 0; 5085388Sroot if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 5095388Sroot u.u_error = EFAULT; 5105388Sroot return; 5115388Sroot } 5125388Sroot 5135388Sroot case SIOCSLINGER: { 5145388Sroot int linger; 5155388Sroot if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 5165388Sroot u.u_error = EFAULT; 5175388Sroot return; 5185388Sroot } 5195388Sroot so->so_linger = linger; 5205388Sroot if (so->so_linger) 5215388Sroot so->so_options &= ~SO_DONTLINGER; 5225388Sroot else 5235388Sroot so->so_options |= SO_DONTLINGER; 5245388Sroot return; 5255388Sroot } 5265388Sroot 5275388Sroot case SIOCGLINGER: { 5285388Sroot int linger = so->so_linger; 5295388Sroot if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 5305388Sroot u.u_error = EFAULT; 5315388Sroot return; 5325388Sroot } 5335388Sroot } 5345423Swnj case SIOCSPGRP: { 5355423Swnj int pgrp; 5365423Swnj if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 5375423Swnj u.u_error = EFAULT; 5385423Swnj return; 5395423Swnj } 5405423Swnj so->so_pgrp = pgrp; 5415423Swnj return; 5425423Swnj } 5435388Sroot 5445423Swnj case SIOCGPGRP: { 5455423Swnj int pgrp = so->so_pgrp; 5465423Swnj if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 5475423Swnj u.u_error = EFAULT; 5485423Swnj return; 5495423Swnj } 5505423Swnj } 5515423Swnj 5525281Sroot case SIOCDONE: { 5535281Sroot int flags; 5545281Sroot if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 5555281Sroot u.u_error = EFAULT; 5565281Sroot return; 5575281Sroot } 5585388Sroot flags++; 5595281Sroot if (flags & FREAD) { 5605281Sroot int s = splimp(); 5615281Sroot socantrcvmore(so); 5625281Sroot sbflush(&so->so_rcv); 5636140Ssam splx(s); 5645281Sroot } 5655281Sroot if (flags & FWRITE) 5665404Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 5675281Sroot return; 5684829Swnj } 5695281Sroot 5705423Swnj case SIOCSENDOOB: { 5715423Swnj char oob; 5725423Swnj struct mbuf *m; 5735423Swnj if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 5745423Swnj u.u_error = EFAULT; 5755423Swnj return; 5765423Swnj } 5775423Swnj m = m_get(M_DONTWAIT); 5785423Swnj if (m == 0) { 5795423Swnj u.u_error = ENOBUFS; 5805423Swnj return; 5815423Swnj } 5825423Swnj m->m_off = MMINOFF; 5835423Swnj m->m_len = 1; 5845423Swnj *mtod(m, caddr_t) = oob; 5855423Swnj (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 5865423Swnj return; 5875281Sroot } 5885423Swnj 5895423Swnj case SIOCRCVOOB: { 5905423Swnj struct mbuf *m = m_get(M_DONTWAIT); 5915423Swnj if (m == 0) { 5925423Swnj u.u_error = ENOBUFS; 5935423Swnj return; 5945423Swnj } 5955423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 5965423Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 5975423Swnj if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 5985423Swnj u.u_error = EFAULT; 5995423Swnj return; 6005423Swnj } 6015423Swnj m_free(m); 6025423Swnj return; 6035423Swnj } 6045423Swnj 6055423Swnj case SIOCATMARK: { 6065423Swnj int atmark = (so->so_state&SS_RCVATMARK) != 0; 6075423Swnj if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 6085423Swnj u.u_error = EFAULT; 6095423Swnj return; 6105423Swnj } 6115423Swnj return; 6125423Swnj } 6136355Ssam 6146355Ssam /* routing table update calls */ 6156355Ssam case SIOCADDRT: 6166355Ssam case SIOCDELRT: 6176355Ssam case SIOCCHGRT: { 6186355Ssam struct rtentry route; 6196355Ssam if (!suser()) 6206355Ssam return; 6216355Ssam if (copyin(cmdp, (caddr_t)&route, sizeof (route))) { 6226355Ssam u.u_error = EFAULT; 6236355Ssam return; 6246355Ssam } 6256355Ssam u.u_error = rtrequest(cmd, &route); 6266355Ssam return; 6276355Ssam } 6286355Ssam 6295445Swnj /* type/protocol specific ioctls */ 6305423Swnj } 6315445Swnj u.u_error = EOPNOTSUPP; 6324786Swnj } 633