X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/de48daf3bbbee88e6b55e97977551f9905ca4c4c..b4a3d4a786dfe3a0855f94815f3388549da78fa8:/usr/src/sys/kern/uipc_socket.c diff --git a/usr/src/sys/kern/uipc_socket.c b/usr/src/sys/kern/uipc_socket.c index b8f1fb8d2e..a0dc797687 100644 --- a/usr/src/sys/kern/uipc_socket.c +++ b/usr/src/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* uipc_socket.c 4.41 82/06/14 */ +/* uipc_socket.c 4.71 83/01/22 */ #include "../h/param.h" #include "../h/systm.h" @@ -14,77 +14,49 @@ #include "../h/socketvar.h" #include "../h/stat.h" #include "../h/ioctl.h" -#include "../net/in.h" -#include "../net/in_systm.h" +#include "../h/uio.h" #include "../net/route.h" /* - * Socket support routines. - * - * DEAL WITH INTERRUPT NOTIFICATION. + * Socket operation routines. + * These routines are called by the routines in + * sys_socket.c or from a system process, and + * implement the semantics of socket operations by + * switching out to the protocol specific routines. */ -/* - * Create a socket. - */ -socreate(aso, type, asp, asa, options) +/*ARGSUSED*/ +socreate(dom, aso, type, proto) struct socket **aso; - int type; - struct sockproto *asp; - struct sockaddr *asa; - int options; + int type, proto; { register struct protosw *prp; register struct socket *so; struct mbuf *m; - int pf, proto, error; -COUNT(SOCREATE); - - /* - * Use process standard protocol/protocol family if none - * specified by address argument. - */ - if (asp == 0) { - pf = PF_INET; /* should be u.u_protof */ - proto = 0; - } else { - pf = asp->sp_family; - proto = asp->sp_protocol; - } + int error; - /* - * If protocol specified, look for it, otherwise - * for a protocol of the correct type in the right family. - */ if (proto) - prp = pffindproto(pf, proto); + prp = pffindproto(dom, proto); else - prp = pffindtype(pf, type); + prp = pffindtype(dom, type); if (prp == 0) return (EPROTONOSUPPORT); - - /* - * Get a socket structure. - */ - m = m_getclr(M_WAIT); + if (prp->pr_type != type) + return (EPROTOTYPE); + m = m_getclr(M_WAIT, MT_SOCKET); if (m == 0) return (ENOBUFS); so = mtod(m, struct socket *); - so->so_options = options; + so->so_options = SO_LINGER; so->so_state = 0; + so->so_type = type; if (u.u_uid == 0) so->so_state = SS_PRIV; - - /* - * Attach protocol to socket, initializing - * and reserving resources. - */ so->so_proto = prp; - error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); + error = (*prp->pr_usrreq)(so, PRU_ATTACH, + (struct mbuf *)0, (struct mbuf *)0); if (error) { - if (so->so_snd.sb_mbmax || so->so_rcv.sb_mbmax) - panic("socreate"); - so->so_state |= SS_USERGONE; + so->so_state |= SS_NOFDREF; sofree(so); return (error); } @@ -92,12 +64,55 @@ COUNT(SOCREATE); return (0); } +sobind(so, nam) + struct socket *so; + struct mbuf *nam; +{ + int s = splnet(); + int error; + + error = + (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam); + splx(s); + return (error); +} + +solisten(so, backlog) + struct socket *so; + int backlog; +{ + int s = splnet(); + int error; + + error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, + (struct mbuf *)0, (struct mbuf *)0); + if (error) { + splx(s); + return (error); + } + if (so->so_q == 0) { + so->so_q = so; + so->so_q0 = so; + so->so_options |= SO_ACCEPTCONN; + } + if (backlog < 0) + backlog = 0; +#define SOMAXCONN 5 + so->so_qlimit = MIN(backlog, SOMAXCONN); + so->so_options |= SO_NEWFDONCONN; + return (0); +} + sofree(so) struct socket *so; { -COUNT(SOFREE); - if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) + if (so->so_head) { + if (!soqremque(so, 0) && !soqremque(so, 1)) + panic("sofree dq"); + so->so_head = 0; + } + if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; sbrelease(&so->so_snd); sbrelease(&so->so_rcv); @@ -108,38 +123,39 @@ COUNT(SOFREE); * Close a socket on last file table reference removal. * Initiate disconnect if connected. * Free socket when disconnect complete. - * - * THIS IS REALLY A UNIX INTERFACE ROUTINE */ soclose(so, exiting) register struct socket *so; int exiting; { int s = splnet(); /* conservative */ + int error; -COUNT(SOCLOSE); + if (so->so_options & SO_ACCEPTCONN) { + while (so->so_q0 != so) + (void) soabort(so->so_q0); + while (so->so_q != so) + (void) soabort(so->so_q); + } if (so->so_pcb == 0) goto discard; if (exiting) so->so_options |= SO_KEEPALIVE; if (so->so_state & SS_ISCONNECTED) { if ((so->so_state & SS_ISDISCONNECTING) == 0) { - u.u_error = sodisconnect(so, (struct sockaddr *)0); - if (u.u_error) { + error = sodisconnect(so, (struct mbuf *)0); + if (error) { if (exiting) goto drop; splx(s); - return; + return (error); } } - if ((so->so_options & SO_DONTLINGER) == 0) { + if (so->so_options & SO_LINGER) { if ((so->so_state & SS_ISDISCONNECTING) && (so->so_state & SS_NBIO) && - exiting == 0) { - u.u_error = EINPROGRESS; - splx(s); - return; - } + exiting == 0) + return (EINPROGRESS); /* should use tsleep here, for at most linger */ while (so->so_state & SS_ISCONNECTED) sleep((caddr_t)&so->so_timeo, PZERO+1); @@ -147,92 +163,88 @@ COUNT(SOCLOSE); } drop: if (so->so_pcb) { - u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); - if (exiting == 0 && u.u_error) { + error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, + (struct mbuf *)0, (struct mbuf *)0); + if (exiting == 0 && error) { splx(s); - return; + return (error); } } discard: - so->so_state |= SS_USERGONE; + if (so->so_state & SS_NOFDREF) + panic("soclose: NOFDREF"); + so->so_state |= SS_NOFDREF; sofree(so); splx(s); + return (0); +} + +/* + * Must be called at splnet... + */ +soabort(so) + struct socket *so; +{ + int error; + + error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, + (struct mbuf *)0, (struct mbuf *)0); + return (error); } /*ARGSUSED*/ -sostat(so, sb) +sostat(so, ub) struct socket *so; - struct stat *sb; + struct stat *ub; { + struct stat sb; -COUNT(SOSTAT); - bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ + bzero((caddr_t)&sb, sizeof (sb)); /* XXX */ + (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */ return (0); /* XXX */ } -/* - * Accept connection on a socket. - */ -soaccept(so, asa) +soaccept(so, nam) struct socket *so; - struct sockaddr *asa; + struct mbuf *nam; { int s = splnet(); int error; -COUNT(SOACCEPT); - if ((so->so_options & SO_ACCEPTCONN) == 0) { - error = EINVAL; /* XXX */ - goto bad; - } - if ((so->so_state & SS_CONNAWAITING) == 0) { - error = ENOTCONN; - goto bad; - } - so->so_state &= ~SS_CONNAWAITING; - error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); -bad: + if ((so->so_state & SS_NOFDREF) == 0) + panic("soaccept: !NOFDREF"); + so->so_state &= ~SS_NOFDREF; + error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, + (struct mbuf *)0, nam); splx(s); return (error); } -/* - * Connect socket to a specified address. - * If already connected or connecting, then avoid - * the protocol entry, to keep its job simpler. - */ -soconnect(so, asa) +soconnect(so, nam) struct socket *so; - struct sockaddr *asa; + struct mbuf *nam; { int s = splnet(); int error; -COUNT(SOCONNECT); if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { error = EISCONN; goto bad; } - error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); + error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, + (struct mbuf *)0, nam); bad: splx(s); return (error); } -/* - * Disconnect from a socket. - * Address parameter is from system call for later multicast - * protocols. Check to make sure that connected and no disconnect - * in progress (for protocol's sake), and then invoke protocol. - */ -sodisconnect(so, asa) +sodisconnect(so, nam) struct socket *so; - struct sockaddr *asa; + struct mbuf *nam; { int s = splnet(); int error; -COUNT(SODISCONNECT); if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; goto bad; @@ -241,7 +253,8 @@ COUNT(SODISCONNECT); error = EALREADY; goto bad; } - error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); + error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, + (struct mbuf *)0, nam); bad: splx(s); return (error); @@ -255,27 +268,27 @@ bad: * If must go all at once and not enough room now, then * inform user that this would block and do nothing. */ -sosend(so, asa) +sosend(so, nam, uio, flags) register struct socket *so; - struct sockaddr *asa; + struct mbuf *nam; + struct uio *uio; + int flags; { struct mbuf *top = 0; register struct mbuf *m, **mp = ⊤ - register u_int len; - int error = 0, space, s; + register int len; + int error = 0, space, s, dontroute; -COUNT(SOSEND); - if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) + if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) return (EMSGSIZE); -#ifdef notdef - /* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING */ - if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) - return (EWOULDBLOCK); -#endif + dontroute = (flags & SOF_DONTROUTE) && + (so->so_options & SO_DONTROUTE) == 0 && + (so->so_proto->pr_flags & PR_ATOMIC); restart: sblock(&so->so_snd); #define snderr(errno) { error = errno; splx(s); goto release; } + u.u_ru.ru_msgsnd++; again: s = splnet(); if (so->so_state & SS_CANTSENDMORE) { @@ -291,11 +304,17 @@ again: if ((so->so_state & SS_ISCONNECTED) == 0) { if (so->so_proto->pr_flags & PR_CONNREQUIRED) snderr(ENOTCONN); - if (asa == 0) + if (nam == 0) snderr(EDESTADDRREQ); } if (top) { - error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); + if (dontroute) + so->so_options |= SO_DONTROUTE; + error = (*so->so_proto->pr_usrreq)(so, + (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, + top, (caddr_t)nam); + if (dontroute) + so->so_options &= ~SO_DONTROUTE; top = 0; if (error) { splx(s); @@ -303,27 +322,41 @@ again: } mp = ⊤ } - if (u.u_count == 0) { + if (uio->uio_resid == 0) { splx(s); goto release; } - space = sbspace(&so->so_snd); - if (space <= 0 || sosendallatonce(so) && space < u.u_count) { - if (so->so_state & SS_NBIO) - snderr(EWOULDBLOCK); - sbunlock(&so->so_snd); - sbwait(&so->so_snd); - splx(s); - goto restart; + if (flags & SOF_OOB) + space = 1024; + else { + space = sbspace(&so->so_snd); + if (space <= 0 || + sosendallatonce(so) && space < uio->uio_resid) { + if (so->so_state & SS_NBIO) + snderr(EWOULDBLOCK); + sbunlock(&so->so_snd); + sbwait(&so->so_snd); + splx(s); + goto restart; + } } splx(s); - while (u.u_count && space > 0) { - MGET(m, 1); + while (uio->uio_resid > 0 && space > 0) { + register struct iovec *iov = uio->uio_iov; + + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("sosend"); + continue; + } + MGET(m, M_WAIT, MT_DATA); if (m == NULL) { error = ENOBUFS; /* SIGPIPE? */ goto release; } - if (u.u_count >= CLBYTES && space >= CLBYTES) { + if (iov->iov_len >= CLBYTES && space >= CLBYTES) { register struct mbuf *p; MCLGET(p, 1); if (p == 0) @@ -332,14 +365,16 @@ again: len = CLBYTES; } else { nopages: - m->m_off = MMINOFF; - len = MIN(MLEN, u.u_count); + len = MIN(MLEN, iov->iov_len); } - iomove(mtod(m, caddr_t), len, B_WRITE); + (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); m->m_len = len; *mp = m; mp = &m->m_next; - space = sbspace(&so->so_snd); + if (flags & SOF_OOB) + space -= len; + else + space = sbspace(&so->so_snd); } goto again; @@ -350,16 +385,38 @@ release: return (error); } -soreceive(so, asa) +soreceive(so, aname, uio, flags) register struct socket *so; - struct sockaddr *asa; + struct mbuf **aname; + struct uio *uio; + int flags; { register struct mbuf *m, *n; - u_int len; - int eor, s, error = 0, cnt = u.u_count; - caddr_t base = u.u_base; + int len; + int eor, s, error = 0, moff, tomark; + + if (flags & SOF_OOB) { + m = m_get(M_WAIT, MT_DATA); + if (m == NULL) + return (ENOBUFS); + error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, + m, (struct mbuf *)0); + if (error) + goto bad; + do { + len = uio->uio_resid; + if (len > m->m_len) + len = m->m_len; + error = + uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); + m = m_free(m); + } while (uio->uio_resid && error == 0 && m); +bad: + if (m) + m_freem(m); + return (error); + } -COUNT(SORECEIVE); restart: sblock(&so->so_rcv); s = splnet(); @@ -386,46 +443,89 @@ restart: splx(s); goto restart; } + u.u_ru.ru_msgrcv++; m = so->so_rcv.sb_mb; if (m == 0) panic("receive"); if (so->so_proto->pr_flags & PR_ADDR) { - if (m->m_len != sizeof (struct sockaddr)) - panic("soreceive addr"); - if (asa) - bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); - so->so_rcv.sb_cc -= m->m_len; - so->so_rcv.sb_mbcnt -= MSIZE; - m = m_free(m); + if ((flags & SOF_PREVIEW) == 0) { + so->so_rcv.sb_cc -= m->m_len; + so->so_rcv.sb_mbcnt -= MSIZE; + } + if (aname) { + if (flags & SOF_PREVIEW) { + *aname = m_copy(m, 0, m->m_len); + if (*aname == NULL) + panic("receive 2"); + } else + *aname = m; + m = m->m_next; + (*aname)->m_next = 0; + } else + if (flags & SOF_PREVIEW) + m = m->m_next; + else + m = m_free(m); if (m == 0) - panic("receive 2"); - so->so_rcv.sb_mb = m; + panic("receive 3"); + if ((flags & SOF_PREVIEW) == 0) + so->so_rcv.sb_mb = m; } - so->so_state &= ~SS_RCVATMARK; - if (so->so_oobmark && cnt > so->so_oobmark) - cnt = so->so_oobmark; eor = 0; + moff = 0; + tomark = so->so_oobmark; do { - len = MIN(m->m_len, cnt); + if (uio->uio_resid <= 0) + break; + len = uio->uio_resid; + so->so_state &= ~SS_RCVATMARK; + if (tomark && len > tomark) + len = tomark; + if (moff+len > m->m_len - moff) + len = m->m_len - moff; splx(s); - iomove(mtod(m, caddr_t), len, B_READ); - cnt -= len; + error = + uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); s = splnet(); if (len == m->m_len) { eor = (int)m->m_act; - sbfree(&so->so_rcv, m); - so->so_rcv.sb_mb = m->m_next; - MFREE(m, n); + if (flags & SOF_PREVIEW) + m = m->m_next; + else { + sbfree(&so->so_rcv, m); + MFREE(m, n); + m = n; + so->so_rcv.sb_mb = m; + } + moff = 0; } else { - m->m_off += len; - m->m_len -= len; - so->so_rcv.sb_cc -= len; + if (flags & SOF_PREVIEW) + moff += len; + else { + m->m_off += len; + m->m_len -= len; + so->so_rcv.sb_cc -= len; + } + } + if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { + so->so_oobmark -= len; + if (so->so_oobmark == 0) { + so->so_state |= SS_RCVATMARK; + break; + } } - } while ((m = so->so_rcv.sb_mb) && cnt && !eor); + if (tomark) { + tomark -= len; + if (tomark == 0) + break; + } + } while (m && error == 0 && !eor); + if (flags & SOF_PREVIEW) + goto release; if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) do { if (m == 0) - panic("receive 3"); + panic("receive 4"); sbfree(&so->so_rcv, m); eor = (int)m->m_act; so->so_rcv.sb_mb = m->m_next; @@ -433,18 +533,98 @@ restart: m = n; } while (eor == 0); if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) - (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); - if (so->so_oobmark) { - so->so_oobmark -= u.u_base - base; - if (so->so_oobmark == 0) - so->so_state |= SS_RCVATMARK; - } + (*so->so_proto->pr_usrreq)(so, PRU_RCVD, + (struct mbuf *)0, (struct mbuf *)0); release: sbunlock(&so->so_rcv); splx(s); return (error); } +soshutdown(so, how) + struct socket *so; + int how; +{ + + how++; + if (how & FREAD) { + int s = splimp(); + socantrcvmore(so); + sbflush(&so->so_rcv); + splx(s); + } + if (how & FWRITE) + return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, + (struct mbuf *)0, (struct mbuf *)0)); + return (0); +} + +sosetopt(so, level, optname, m) + struct socket *so; + int level, optname; + struct mbuf *m; +{ + + if (level != SOL_SOCKET) + return (EINVAL); /* XXX */ + switch (optname) { + + case SO_DEBUG: + case SO_KEEPALIVE: + case SO_DONTROUTE: + case SO_USELOOPBACK: + case SO_REUSEADDR: + so->so_options |= optname; + break; + + case SO_LINGER: + if (m == NULL || m->m_len != sizeof (int)) + return (EINVAL); + so->so_options |= SO_LINGER; + so->so_linger = *mtod(m, int *); + break; + + case SO_DONTLINGER: + so->so_options &= ~SO_LINGER; + so->so_linger = 0; + break; + + default: + return (EINVAL); + } + return (0); +} + +sogetopt(so, level, optname, m) + struct socket *so; + int level, optname; + struct mbuf *m; +{ + + if (level != SOL_SOCKET) + return (EINVAL); /* XXX */ + switch (optname) { + + case SO_USELOOPBACK: + case SO_DONTROUTE: + case SO_DEBUG: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_REUSEADDR: + if ((so->so_options & optname) == 0) + return (ENOPROTOOPT); + if (optname == SO_LINGER && m != NULL) { + *mtod(m, int *) = so->so_linger; + m->m_len = sizeof (so->so_linger); + } + break; + + default: + return (EINVAL); + } + return (0); +} + sohasoutofband(so) struct socket *so; { @@ -462,178 +642,50 @@ sohasoutofband(so) } /*ARGSUSED*/ -soioctl(so, cmd, cmdp) +soioctl(so, cmd, data) register struct socket *so; int cmd; - register caddr_t cmdp; + register char *data; { -COUNT(SOIOCTL); switch (cmd) { - case FIONBIO: { - int nbio; - if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { - u.u_error = EFAULT; - return; - } - if (nbio) + case FIONBIO: + if (*(int *)data) so->so_state |= SS_NBIO; else so->so_state &= ~SS_NBIO; - return; - } + break; - case FIOASYNC: { - int async; - if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { - u.u_error = EFAULT; - return; - } - if (async) + case FIOASYNC: + if (*(int *)data) so->so_state |= SS_ASYNC; else so->so_state &= ~SS_ASYNC; - return; - } - - case SIOCSKEEP: { - int keep; - if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { - u.u_error = EFAULT; - return; - } - if (keep) - so->so_options &= ~SO_KEEPALIVE; - else - so->so_options |= SO_KEEPALIVE; - return; - } + break; - case SIOCGKEEP: { - int keep = (so->so_options & SO_KEEPALIVE) != 0; - if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) - u.u_error = EFAULT; - return; - } - - case SIOCSLINGER: { - int linger; - if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { - u.u_error = EFAULT; - return; - } - so->so_linger = linger; - if (so->so_linger) - so->so_options &= ~SO_DONTLINGER; - else - so->so_options |= SO_DONTLINGER; - return; - } + case SIOCSPGRP: + so->so_pgrp = *(int *)data; + break; - case SIOCGLINGER: { - int linger = so->so_linger; - if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { - u.u_error = EFAULT; - return; - } - } - case SIOCSPGRP: { - int pgrp; - if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { - u.u_error = EFAULT; - return; - } - so->so_pgrp = pgrp; - return; - } + case SIOCGPGRP: + *(int *)data = so->so_pgrp; + break; - case SIOCGPGRP: { - int pgrp = so->so_pgrp; - if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { - u.u_error = EFAULT; - return; - } - } - - case SIOCDONE: { - int flags; - if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { - u.u_error = EFAULT; - return; - } - flags++; - if (flags & FREAD) { - int s = splimp(); - socantrcvmore(so); - sbflush(&so->so_rcv); - splx(s); - } - if (flags & FWRITE) - u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); - return; - } - - case SIOCSENDOOB: { - char oob; - struct mbuf *m; - if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { - u.u_error = EFAULT; - return; - } - m = m_get(M_DONTWAIT); - if (m == 0) { - u.u_error = ENOBUFS; - return; - } - m->m_off = MMINOFF; - m->m_len = 1; - *mtod(m, caddr_t) = oob; - (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); - return; - } - - case SIOCRCVOOB: { - struct mbuf *m = m_get(M_DONTWAIT); - if (m == 0) { - u.u_error = ENOBUFS; - return; - } - m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; - (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); - if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { - u.u_error = EFAULT; - return; - } - m_free(m); - return; - } - - case SIOCATMARK: { - int atmark = (so->so_state&SS_RCVATMARK) != 0; - if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { - u.u_error = EFAULT; - return; - } - return; - } + case SIOCATMARK: + *(int *)data = (so->so_state&SS_RCVATMARK) != 0; + break; /* routing table update calls */ case SIOCADDRT: case SIOCDELRT: - case SIOCCHGRT: { - struct rtentry route; if (!suser()) - return; - if (copyin(cmdp, (caddr_t)&route, sizeof (route))) { - u.u_error = EFAULT; - return; - } - u.u_error = rtrequest(cmd, &route); - return; - } + return (u.u_error); + return (rtrequest(cmd, (struct rtentry *)data)); /* type/protocol specific ioctls */ + default: + return (ENOTTY); /* XXX */ } - u.u_error = EOPNOTSUPP; + return (0); }