1*6355Ssam /* uipc_socket.c 4.37 82/03/29 */ 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" 19*6355Ssam #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; 414927Swnj COUNT(SOCREATE); 424786Swnj 434786Swnj /* 444890Swnj * Use process standard protocol/protocol family if none 454890Swnj * specified by address argument. 464786Swnj */ 474927Swnj if (asp == 0) { 484890Swnj pf = PF_INET; /* should be u.u_protof */ 494786Swnj proto = 0; 504786Swnj } else { 514927Swnj pf = asp->sp_family; 524927Swnj proto = asp->sp_protocol; 534786Swnj } 544786Swnj 554786Swnj /* 564890Swnj * If protocol specified, look for it, otherwise 574890Swnj * for a protocol of the correct type in the right family. 584890Swnj */ 594890Swnj if (proto) 604890Swnj prp = pffindproto(pf, proto); 614890Swnj else 624890Swnj prp = pffindtype(pf, type); 634890Swnj if (prp == 0) 644890Swnj return (EPROTONOSUPPORT); 654890Swnj 664890Swnj /* 674786Swnj * Get a socket structure. 684786Swnj */ 694890Swnj m = m_getclr(M_WAIT); 704786Swnj if (m == 0) 714786Swnj return (ENOBUFS); 724786Swnj so = mtod(m, struct socket *); 734829Swnj so->so_options = options; 746214Swnj so->so_state = 0; 756214Swnj if (u.u_uid == 0) 766214Swnj so->so_state = SS_PRIV; 774786Swnj 784786Swnj /* 794890Swnj * Attach protocol to socket, initializing 804890Swnj * and reserving resources. 814786Swnj */ 824786Swnj so->so_proto = prp; 834979Swnj error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 844979Swnj if (error) { 854971Swnj (void) m_free(dtom(so)); 864890Swnj return (error); 874786Swnj } 884786Swnj *aso = so; 894786Swnj return (0); 904786Swnj } 914786Swnj 924916Swnj sofree(so) 934916Swnj struct socket *so; 944916Swnj { 954916Swnj 964927Swnj COUNT(SOFREE); 974950Swnj if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) 984950Swnj return; 994950Swnj sbrelease(&so->so_snd); 1004950Swnj sbrelease(&so->so_rcv); 1014971Swnj (void) m_free(dtom(so)); 1024916Swnj } 1034916Swnj 1044786Swnj /* 1054890Swnj * Close a socket on last file table reference removal. 1064890Swnj * Initiate disconnect if connected. 1074890Swnj * Free socket when disconnect complete. 1085580Sroot * 1095580Sroot * THIS IS REALLY A UNIX INTERFACE ROUTINE 1104829Swnj */ 1115580Sroot soclose(so, exiting) 1124829Swnj register struct socket *so; 1135580Sroot int exiting; 1144829Swnj { 1154890Swnj int s = splnet(); /* conservative */ 1164829Swnj 1174927Swnj COUNT(SOCLOSE); 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: 1464890Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 1474890Swnj discard: 1484950Swnj so->so_state |= SS_USERGONE; 1494950Swnj sofree(so); 1504890Swnj splx(s); 1514829Swnj } 1524829Swnj 1534916Swnj /*ARGSUSED*/ 1544890Swnj sostat(so, sb) 1554829Swnj struct socket *so; 1564890Swnj struct stat *sb; 1574829Swnj { 1584829Swnj 1594927Swnj COUNT(SOSTAT); 1605303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1615303Sroot return (0); /* XXX */ 1624829Swnj } 1634829Swnj 1644829Swnj /* 1654927Swnj * Accept connection on a socket. 1664927Swnj */ 1674927Swnj soaccept(so, asa) 1684927Swnj struct socket *so; 1694927Swnj struct sockaddr *asa; 1704927Swnj { 1714927Swnj int s = splnet(); 1724927Swnj int error; 1734927Swnj 1744927Swnj COUNT(SOACCEPT); 1754927Swnj if ((so->so_options & SO_ACCEPTCONN) == 0) { 1764927Swnj error = EINVAL; /* XXX */ 1774927Swnj goto bad; 1784927Swnj } 1795265Swnj if ((so->so_state & SS_CONNAWAITING) == 0) { 1805265Swnj error = ENOTCONN; 1815265Swnj goto bad; 1825265Swnj } 1835265Swnj so->so_state &= ~SS_CONNAWAITING; 1844927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 1854927Swnj bad: 1864927Swnj splx(s); 1874927Swnj return (error); 1884927Swnj } 1894927Swnj 1904927Swnj /* 1914890Swnj * Connect socket to a specified address. 1924890Swnj * If already connected or connecting, then avoid 1934890Swnj * the protocol entry, to keep its job simpler. 1944786Swnj */ 1954927Swnj soconnect(so, asa) 1964786Swnj struct socket *so; 1974927Swnj struct sockaddr *asa; 1984786Swnj { 1994890Swnj int s = splnet(); 2004890Swnj int error; 2014786Swnj 2024927Swnj COUNT(SOCONNECT); 2034890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2044890Swnj error = EISCONN; 2054890Swnj goto bad; 2064890Swnj } 2074927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 2084890Swnj bad: 2094890Swnj splx(s); 2104890Swnj return (error); 2114786Swnj } 2124786Swnj 2134786Swnj /* 2144890Swnj * Disconnect from a socket. 2154890Swnj * Address parameter is from system call for later multicast 2164890Swnj * protocols. Check to make sure that connected and no disconnect 2174890Swnj * in progress (for protocol's sake), and then invoke protocol. 2184786Swnj */ 2194927Swnj sodisconnect(so, asa) 2204786Swnj struct socket *so; 2214927Swnj struct sockaddr *asa; 2224786Swnj { 2234890Swnj int s = splnet(); 2244890Swnj int error; 2254786Swnj 2264927Swnj COUNT(SODISCONNECT); 2274890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2284890Swnj error = ENOTCONN; 2294890Swnj goto bad; 2304890Swnj } 2314890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2324890Swnj error = EALREADY; 2334890Swnj goto bad; 2344890Swnj } 2354927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 2364890Swnj bad: 2374890Swnj splx(s); 2384890Swnj return (error); 2394786Swnj } 2404786Swnj 2414786Swnj /* 2424890Swnj * Send on a socket. 2434890Swnj * If send must go all at once and message is larger than 2444890Swnj * send buffering, then hard error. 2454890Swnj * Lock against other senders. 2464890Swnj * If must go all at once and not enough room now, then 2474890Swnj * inform user that this would block and do nothing. 2484786Swnj */ 2494927Swnj sosend(so, asa) 2504786Swnj register struct socket *so; 2514927Swnj struct sockaddr *asa; 2524786Swnj { 2534890Swnj struct mbuf *top = 0; 2544890Swnj register struct mbuf *m, **mp = ⊤ 2554916Swnj register u_int len; 2564916Swnj int error = 0, space, s; 2574786Swnj 2584927Swnj COUNT(SOSEND); 2595950Swnj if (so->so_state & SS_CANTSENDMORE) { 2605950Swnj psignal(u.u_procp, SIGPIPE); 2614890Swnj return (EPIPE); 2625950Swnj } 2634890Swnj if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 2644890Swnj return (EMSGSIZE); 2656214Swnj if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 2664890Swnj return (EWOULDBLOCK); 2674890Swnj sblock(&so->so_snd); 2684890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2694890Swnj 2704890Swnj s = splnet(); 2714890Swnj again: 2725168Swnj if (so->so_error) { 2735168Swnj error = so->so_error; 2745168Swnj so->so_error = 0; 2755168Swnj splx(s); 2765168Swnj goto release; 2775168Swnj } 2784890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2794890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2804890Swnj snderr(ENOTCONN); 2814927Swnj if (asa == 0) 2824890Swnj snderr(EDESTADDRREQ); 2834890Swnj } 2844890Swnj if (top) { 2854927Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 2864890Swnj if (error) { 2874890Swnj splx(s); 2884786Swnj goto release; 2894786Swnj } 2904890Swnj top = 0; 2914890Swnj mp = ⊤ 2924786Swnj } 2934979Swnj if (u.u_count == 0) { 2944979Swnj splx(s); 2954979Swnj goto release; 2964979Swnj } 2975018Swnj space = sbspace(&so->so_snd); 2985610Swnj if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 2996214Swnj if (so->so_state & SS_NBIO) 3004890Swnj snderr(EWOULDBLOCK); 3014890Swnj sbunlock(&so->so_snd); 3024890Swnj sbwait(&so->so_snd); 3034890Swnj splx(s); 3044786Swnj goto again; 3054786Swnj } 3064890Swnj splx(s); 3075018Swnj while (u.u_count && space > 0) { 3084890Swnj MGET(m, 1); 3094890Swnj if (m == NULL) { 3104890Swnj error = ENOBUFS; 3114890Swnj m_freem(top); 3124890Swnj goto release; 3134786Swnj } 3145095Swnj if (u.u_count >= CLBYTES && space >= CLBYTES) { 3154890Swnj register struct mbuf *p; 3165095Swnj MCLGET(p, 1); 3174890Swnj if (p == 0) 3184890Swnj goto nopages; 3194890Swnj m->m_off = (int)p - (int)m; 3205095Swnj len = CLBYTES; 3214890Swnj } else { 3224786Swnj nopages: 3234890Swnj m->m_off = MMINOFF; 3244890Swnj len = MIN(MLEN, u.u_count); 3254786Swnj } 3264890Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3274890Swnj m->m_len = len; 3284890Swnj *mp = m; 3294890Swnj mp = &m->m_next; 3305018Swnj space = sbspace(&so->so_snd); 3314786Swnj } 3324890Swnj s = splnet(); 3334890Swnj goto again; 3344890Swnj 3354786Swnj release: 3364890Swnj sbunlock(&so->so_snd); 3374786Swnj return (error); 3384786Swnj } 3394786Swnj 3404927Swnj soreceive(so, asa) 3414786Swnj register struct socket *so; 3424927Swnj struct sockaddr *asa; 3434786Swnj { 3444786Swnj register struct mbuf *m, *n; 3454916Swnj u_int len; 3465423Swnj int eor, s, error = 0, cnt = u.u_count; 3475423Swnj caddr_t base = u.u_base; 3484786Swnj 3494927Swnj COUNT(SORECEIVE); 3504890Swnj restart: 3514890Swnj sblock(&so->so_rcv); 3524890Swnj s = splnet(); 3534890Swnj 3544890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3554786Swnj if (so->so_rcv.sb_cc == 0) { 3565168Swnj if (so->so_error) { 3575168Swnj error = so->so_error; 3585168Swnj so->so_error = 0; 3595168Swnj splx(s); 3605168Swnj goto release; 3615168Swnj } 3624890Swnj if (so->so_state & SS_CANTRCVMORE) { 3634890Swnj splx(s); 3644890Swnj goto release; 3654890Swnj } 3665015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 3675015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 3685015Sroot rcverr(ENOTCONN); 3696214Swnj if (so->so_state & SS_NBIO) 3705168Swnj rcverr(EWOULDBLOCK); 3714890Swnj sbunlock(&so->so_rcv); 3724971Swnj sbwait(&so->so_rcv); 3735012Swnj splx(s); 3744890Swnj goto restart; 3754786Swnj } 3764829Swnj m = so->so_rcv.sb_mb; 3774786Swnj if (m == 0) 3784786Swnj panic("receive"); 3795039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 3805039Swnj if (m->m_len != sizeof (struct sockaddr)) 3815039Swnj panic("soreceive addr"); 3825039Swnj if (asa) 3835039Swnj bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 3845039Swnj so->so_rcv.sb_cc -= m->m_len; 3855039Swnj so->so_rcv.sb_mbcnt -= MSIZE; 3865018Swnj m = m_free(m); 3874890Swnj if (m == 0) 3884890Swnj panic("receive 2"); 3895018Swnj so->so_rcv.sb_mb = m; 3904890Swnj } 3915423Swnj so->so_state &= ~SS_RCVATMARK; 3925423Swnj if (so->so_oobmark && cnt > so->so_oobmark) 3935423Swnj cnt = so->so_oobmark; 3944786Swnj eor = 0; 3954786Swnj do { 3965423Swnj len = MIN(m->m_len, cnt); 3974786Swnj splx(s); 3984786Swnj iomove(mtod(m, caddr_t), len, B_READ); 3995423Swnj cnt -= len; 4004786Swnj s = splnet(); 4014786Swnj if (len == m->m_len) { 4026091Sroot eor = (int)m->m_act; 4036091Sroot sbfree(&so->so_rcv, m); 4046091Sroot so->so_rcv.sb_mb = m->m_next; 4054786Swnj MFREE(m, n); 4064786Swnj } else { 4074786Swnj m->m_off += len; 4084786Swnj m->m_len -= len; 4094829Swnj so->so_rcv.sb_cc -= len; 4104786Swnj } 4115423Swnj } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 4124786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4134786Swnj do { 4144786Swnj if (m == 0) 4154890Swnj panic("receive 3"); 4164890Swnj sbfree(&so->so_rcv, m); 4174786Swnj eor = (int)m->m_act; 4184786Swnj so->so_rcv.sb_mb = m->m_next; 4194786Swnj MFREE(m, n); 4204890Swnj m = n; 4214786Swnj } while (eor == 0); 4224890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 4234890Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 4245423Swnj if (so->so_oobmark) { 4255423Swnj so->so_oobmark -= u.u_base - base; 4265423Swnj if (so->so_oobmark == 0) 4275423Swnj so->so_state |= SS_RCVATMARK; 4285423Swnj } 4294890Swnj release: 4304916Swnj sbunlock(&so->so_rcv); 4314890Swnj splx(s); 4324916Swnj return (error); 4334786Swnj } 4344786Swnj 4355423Swnj sohasoutofband(so) 4365423Swnj struct socket *so; 4375423Swnj { 4385423Swnj 4395423Swnj if (so->so_pgrp == 0) 4405423Swnj return; 4415423Swnj if (so->so_pgrp > 0) 4425423Swnj gsignal(so->so_pgrp, SIGURG); 4435429Swnj else { 4445429Swnj struct proc *p = pfind(-so->so_pgrp); 4455429Swnj 4465429Swnj if (p) 4475429Swnj psignal(p, SIGURG); 4485429Swnj } 4495423Swnj } 4505423Swnj 4514916Swnj /*ARGSUSED*/ 4524916Swnj soioctl(so, cmd, cmdp) 4534829Swnj register struct socket *so; 4544829Swnj int cmd; 4554829Swnj register caddr_t cmdp; 4564786Swnj { 4574786Swnj 4584927Swnj COUNT(SOIOCTL); 4595358Sroot switch (cmd) { 4604829Swnj 4615388Sroot case FIONBIO: { 4625388Sroot int nbio; 4635388Sroot if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 4645388Sroot u.u_error = EFAULT; 4655388Sroot return; 4665388Sroot } 4675388Sroot if (nbio) 4686214Swnj so->so_state |= SS_NBIO; 4695388Sroot else 4706214Swnj so->so_state &= ~SS_NBIO; 4715388Sroot return; 4725388Sroot } 4735388Sroot 4745388Sroot case FIOASYNC: { 4755388Sroot int async; 4765388Sroot if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 4775388Sroot u.u_error = EFAULT; 4785388Sroot return; 4795388Sroot } 4805388Sroot if (async) 4816214Swnj so->so_state |= SS_ASYNC; 4825388Sroot else 4836214Swnj so->so_state &= ~SS_ASYNC; 4845388Sroot return; 4855388Sroot } 4865388Sroot 4875388Sroot case SIOCSKEEP: { 4885388Sroot int keep; 4895388Sroot if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 4905388Sroot u.u_error = EFAULT; 4915388Sroot return; 4925388Sroot } 4935388Sroot if (keep) 4946214Swnj so->so_options &= ~SO_KEEPALIVE; 4955388Sroot else 4966214Swnj so->so_options |= SO_KEEPALIVE; 4975388Sroot return; 4985388Sroot } 4995388Sroot 5005388Sroot case SIOCGKEEP: { 5016214Swnj int keep = (so->so_options & SO_KEEPALIVE) != 0; 5025388Sroot if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 5035388Sroot u.u_error = EFAULT; 5045388Sroot return; 5055388Sroot } 5065388Sroot 5075388Sroot case SIOCSLINGER: { 5085388Sroot int linger; 5095388Sroot if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 5105388Sroot u.u_error = EFAULT; 5115388Sroot return; 5125388Sroot } 5135388Sroot so->so_linger = linger; 5145388Sroot if (so->so_linger) 5155388Sroot so->so_options &= ~SO_DONTLINGER; 5165388Sroot else 5175388Sroot so->so_options |= SO_DONTLINGER; 5185388Sroot return; 5195388Sroot } 5205388Sroot 5215388Sroot case SIOCGLINGER: { 5225388Sroot int linger = so->so_linger; 5235388Sroot if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 5245388Sroot u.u_error = EFAULT; 5255388Sroot return; 5265388Sroot } 5275388Sroot } 5285423Swnj case SIOCSPGRP: { 5295423Swnj int pgrp; 5305423Swnj if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 5315423Swnj u.u_error = EFAULT; 5325423Swnj return; 5335423Swnj } 5345423Swnj so->so_pgrp = pgrp; 5355423Swnj return; 5365423Swnj } 5375388Sroot 5385423Swnj case SIOCGPGRP: { 5395423Swnj int pgrp = so->so_pgrp; 5405423Swnj if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 5415423Swnj u.u_error = EFAULT; 5425423Swnj return; 5435423Swnj } 5445423Swnj } 5455423Swnj 5465281Sroot case SIOCDONE: { 5475281Sroot int flags; 5485281Sroot if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 5495281Sroot u.u_error = EFAULT; 5505281Sroot return; 5515281Sroot } 5525388Sroot flags++; 5535281Sroot if (flags & FREAD) { 5545281Sroot int s = splimp(); 5555281Sroot socantrcvmore(so); 5565281Sroot sbflush(&so->so_rcv); 5576140Ssam splx(s); 5585281Sroot } 5595281Sroot if (flags & FWRITE) 5605404Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 5615281Sroot return; 5624829Swnj } 5635281Sroot 5645423Swnj case SIOCSENDOOB: { 5655423Swnj char oob; 5665423Swnj struct mbuf *m; 5675423Swnj if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 5685423Swnj u.u_error = EFAULT; 5695423Swnj return; 5705423Swnj } 5715423Swnj m = m_get(M_DONTWAIT); 5725423Swnj if (m == 0) { 5735423Swnj u.u_error = ENOBUFS; 5745423Swnj return; 5755423Swnj } 5765423Swnj m->m_off = MMINOFF; 5775423Swnj m->m_len = 1; 5785423Swnj *mtod(m, caddr_t) = oob; 5795423Swnj (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 5805423Swnj return; 5815281Sroot } 5825423Swnj 5835423Swnj case SIOCRCVOOB: { 5845423Swnj struct mbuf *m = m_get(M_DONTWAIT); 5855423Swnj if (m == 0) { 5865423Swnj u.u_error = ENOBUFS; 5875423Swnj return; 5885423Swnj } 5895423Swnj m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 5905423Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 5915423Swnj if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 5925423Swnj u.u_error = EFAULT; 5935423Swnj return; 5945423Swnj } 5955423Swnj m_free(m); 5965423Swnj return; 5975423Swnj } 5985423Swnj 5995423Swnj case SIOCATMARK: { 6005423Swnj int atmark = (so->so_state&SS_RCVATMARK) != 0; 6015423Swnj if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 6025423Swnj u.u_error = EFAULT; 6035423Swnj return; 6045423Swnj } 6055423Swnj return; 6065423Swnj } 607*6355Ssam 608*6355Ssam /* routing table update calls */ 609*6355Ssam case SIOCADDRT: 610*6355Ssam case SIOCDELRT: 611*6355Ssam case SIOCCHGRT: { 612*6355Ssam struct rtentry route; 613*6355Ssam #ifdef notdef 614*6355Ssam if (!suser()) 615*6355Ssam return; 616*6355Ssam #endif 617*6355Ssam if (copyin(cmdp, (caddr_t)&route, sizeof (route))) { 618*6355Ssam u.u_error = EFAULT; 619*6355Ssam return; 620*6355Ssam } 621*6355Ssam u.u_error = rtrequest(cmd, &route); 622*6355Ssam return; 623*6355Ssam } 624*6355Ssam 6255445Swnj /* type/protocol specific ioctls */ 6265423Swnj } 6275445Swnj u.u_error = EOPNOTSUPP; 6284786Swnj } 629