hack to allow FTP to rebind local addresses
[unix-history] / usr / src / sys / kern / uipc_socket.c
index e6c8667..a0dc797 100644 (file)
@@ -1,4 +1,4 @@
-/*     uipc_socket.c   4.52    82/10/09        */
+/*     uipc_socket.c   4.71    83/01/22        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
  * switching out to the protocol specific routines.
  */
 
  * switching out to the protocol specific routines.
  */
 
-socreate(dom, aso, type, proto, opt)
+/*ARGSUSED*/
+socreate(dom, aso, type, proto)
        struct socket **aso;
        int type, proto;
        struct socket **aso;
        int type, proto;
-       struct socketopt *opt;
 {
        register struct protosw *prp;
        register struct socket *so;
        struct mbuf *m;
 {
        register struct protosw *prp;
        register struct socket *so;
        struct mbuf *m;
-       int pf, error;
+       int error;
 
 
-       pf = dom ? PF_UNIX : PF_INET;           /* should be u.u_protof */
        if (proto)
        if (proto)
-               prp = pffindproto(pf, proto);
+               prp = pffindproto(dom, proto);
        else
        else
-               prp = pffindtype(pf, type);
+               prp = pffindtype(dom, type);
        if (prp == 0)
                return (EPROTONOSUPPORT);
        if (prp->pr_type != type)
                return (EPROTOTYPE);
        if (prp == 0)
                return (EPROTONOSUPPORT);
        if (prp->pr_type != type)
                return (EPROTOTYPE);
-       m = m_getclr(M_WAIT);
+       m = m_getclr(M_WAIT, MT_SOCKET);
        if (m == 0)
                return (ENOBUFS);
        so = mtod(m, struct socket *);
        if (m == 0)
                return (ENOBUFS);
        so = mtod(m, struct socket *);
-       so->so_options = 0;
+       so->so_options = SO_LINGER;
        so->so_state = 0;
        so->so_state = 0;
+       so->so_type = type;
        if (u.u_uid == 0)
                so->so_state = SS_PRIV;
        so->so_proto = prp;
        error = (*prp->pr_usrreq)(so, PRU_ATTACH,
        if (u.u_uid == 0)
                so->so_state = SS_PRIV;
        so->so_proto = prp;
        error = (*prp->pr_usrreq)(so, PRU_ATTACH,
-           (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
+           (struct mbuf *)0, (struct mbuf *)0);
        if (error) {
                so->so_state |= SS_NOFDREF;
                sofree(so);
        if (error) {
                so->so_state |= SS_NOFDREF;
                sofree(so);
@@ -64,17 +64,15 @@ socreate(dom, aso, type, proto, opt)
        return (0);
 }
 
        return (0);
 }
 
-sobind(so, nam, opt)
+sobind(so, nam)
        struct socket *so;
        struct mbuf *nam;
        struct socket *so;
        struct mbuf *nam;
-       struct socketopt *opt;
 {
        int s = splnet();
        int error;
 
        error =
 {
        int s = splnet();
        int error;
 
        error =
-           (*so->so_proto->pr_usrreq)(so, PRU_BIND,
-               (struct mbuf *)0, nam, opt);
+           (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam);
        splx(s);
        return (error);
 }
        splx(s);
        return (error);
 }
@@ -87,7 +85,7 @@ solisten(so, backlog)
        int error;
 
        error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
        int error;
 
        error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
-           (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
+           (struct mbuf *)0, (struct mbuf *)0);
        if (error) {
                splx(s);
                return (error);
        if (error) {
                splx(s);
                return (error);
@@ -99,7 +97,8 @@ solisten(so, backlog)
        }
        if (backlog < 0)
                backlog = 0;
        }
        if (backlog < 0)
                backlog = 0;
-       so->so_qlimit = backlog < 5 ? backlog : 5;
+#define        SOMAXCONN       5
+       so->so_qlimit = MIN(backlog, SOMAXCONN);
        so->so_options |= SO_NEWFDONCONN;
        return (0);
 }
        so->so_options |= SO_NEWFDONCONN;
        return (0);
 }
@@ -130,12 +129,13 @@ soclose(so, exiting)
        int exiting;
 {
        int s = splnet();               /* conservative */
        int exiting;
 {
        int s = splnet();               /* conservative */
+       int error;
 
        if (so->so_options & SO_ACCEPTCONN) {
                while (so->so_q0 != so)
 
        if (so->so_options & SO_ACCEPTCONN) {
                while (so->so_q0 != so)
-                       soclose(so->so_q0, 1);
+                       (void) soabort(so->so_q0);
                while (so->so_q != so)
                while (so->so_q != so)
-                       soclose(so->so_q, 1);
+                       (void) soabort(so->so_q);
        }
        if (so->so_pcb == 0)
                goto discard;
        }
        if (so->so_pcb == 0)
                goto discard;
@@ -143,22 +143,19 @@ soclose(so, exiting)
                so->so_options |= SO_KEEPALIVE;
        if (so->so_state & SS_ISCONNECTED) {
                if ((so->so_state & SS_ISDISCONNECTING) == 0) {
                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);
                                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) &&
                        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);
                        /* should use tsleep here, for at most linger */
                        while (so->so_state & SS_ISCONNECTED)
                                sleep((caddr_t)&so->so_timeo, PZERO+1);
@@ -166,47 +163,66 @@ soclose(so, exiting)
        }
 drop:
        if (so->so_pcb) {
        }
 drop:
        if (so->so_pcb) {
-               u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
-                   (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)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);
                        splx(s);
-                       return;
+                       return (error);
                }
        }
 discard:
                }
        }
 discard:
+       if (so->so_state & SS_NOFDREF)
+               panic("soclose: NOFDREF");
        so->so_state |= SS_NOFDREF;
        sofree(so);
        splx(s);
        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*/
 }
 
 /*ARGSUSED*/
-sostat(so, sb)
+sostat(so, ub)
        struct socket *so;
        struct socket *so;
-       struct stat *sb;
+       struct stat *ub;
 {
 {
+       struct stat sb;
 
 
-       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 */
 }
 
        return (0);                                     /* XXX */
 }
 
-soaccept(so, nam, opt)
+soaccept(so, nam)
        struct socket *so;
        struct mbuf *nam;
        struct socket *so;
        struct mbuf *nam;
-       struct socketopt *opt;
 {
        int s = splnet();
        int error;
 
 {
        int s = splnet();
        int error;
 
+       if ((so->so_state & SS_NOFDREF) == 0)
+               panic("soaccept: !NOFDREF");
+       so->so_state &= ~SS_NOFDREF;
        error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
        error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
-           (struct mbuf *)0, nam, opt);
+           (struct mbuf *)0, nam);
        splx(s);
        return (error);
 }
 
        splx(s);
        return (error);
 }
 
-soconnect(so, nam, opt)
+soconnect(so, nam)
        struct socket *so;
        struct mbuf *nam;
        struct socket *so;
        struct mbuf *nam;
-       struct socketopt *opt;
 {
        int s = splnet();
        int error;
 {
        int s = splnet();
        int error;
@@ -216,7 +232,7 @@ soconnect(so, nam, opt)
                goto bad;
        }
        error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
                goto bad;
        }
        error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
-           (struct mbuf *)0, nam, opt);
+           (struct mbuf *)0, nam);
 bad:
        splx(s);
        return (error);
 bad:
        splx(s);
        return (error);
@@ -238,7 +254,7 @@ sodisconnect(so, nam)
                goto bad;
        }
        error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
                goto bad;
        }
        error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
-           (struct mbuf *)0, nam, (struct socketopt *)0);
+           (struct mbuf *)0, nam);
 bad:
        splx(s);
        return (error);
 bad:
        splx(s);
        return (error);
@@ -260,11 +276,14 @@ sosend(so, nam, uio, flags)
 {
        struct mbuf *top = 0;
        register struct mbuf *m, **mp = &top;
 {
        struct mbuf *top = 0;
        register struct mbuf *m, **mp = &top;
-       register u_int len;
-       int error = 0, space, s;
+       register int len;
+       int error = 0, space, s, dontroute;
 
        if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
                return (EMSGSIZE);
 
        if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
                return (EMSGSIZE);
+       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; }
 restart:
        sblock(&so->so_snd);
 #define        snderr(errno)   { error = errno; splx(s); goto release; }
@@ -289,9 +308,13 @@ again:
                        snderr(EDESTADDRREQ);
        }
        if (top) {
                        snderr(EDESTADDRREQ);
        }
        if (top) {
+               if (dontroute)
+                       so->so_options |= SO_DONTROUTE;
                error = (*so->so_proto->pr_usrreq)(so,
                    (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND,
                error = (*so->so_proto->pr_usrreq)(so,
                    (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND,
-                   top, (caddr_t)nam, (struct socketopt *)0);
+                   top, (caddr_t)nam);
+               if (dontroute)
+                       so->so_options &= ~SO_DONTROUTE;
                top = 0;
                if (error) {
                        splx(s);
                top = 0;
                if (error) {
                        splx(s);
@@ -328,7 +351,7 @@ again:
                                panic("sosend");
                        continue;
                }
                                panic("sosend");
                        continue;
                }
-               MGET(m, 1);
+               MGET(m, M_WAIT, MT_DATA);
                if (m == NULL) {
                        error = ENOBUFS;                        /* SIGPIPE? */
                        goto release;
                if (m == NULL) {
                        error = ENOBUFS;                        /* SIGPIPE? */
                        goto release;
@@ -344,7 +367,7 @@ again:
 nopages:
                        len = MIN(MLEN, iov->iov_len);
                }
 nopages:
                        len = MIN(MLEN, iov->iov_len);
                }
-               uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
+               (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
                m->m_len = len;
                *mp = m;
                mp = &m->m_next;
                m->m_len = len;
                *mp = m;
                mp = &m->m_next;
@@ -368,26 +391,30 @@ soreceive(so, aname, uio, flags)
        struct uio *uio;
        int flags;
 {
        struct uio *uio;
        int flags;
 {
-       register struct iovec *iov;
        register struct mbuf *m, *n;
        register struct mbuf *m, *n;
-       u_int len;
+       int len;
        int eor, s, error = 0, moff, tomark;
 
        if (flags & SOF_OOB) {
        int eor, s, error = 0, moff, tomark;
 
        if (flags & SOF_OOB) {
-               struct mbuf *m = m_get(M_WAIT);
-
-               (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
-                   m, (struct mbuf *)0, (struct socketopt *)0);
-               len = uio->uio_resid;
+               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 {
                do {
+                       len = uio->uio_resid;
                        if (len > m->m_len)
                                len = m->m_len;
                        if (len > m->m_len)
                                len = m->m_len;
-                       uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
+                       error =
+                           uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
                        m = m_free(m);
                        m = m_free(m);
-               } while (uio->uio_resid && u.u_error == 0 && m);
+               } while (uio->uio_resid && error == 0 && m);
+bad:
                if (m)
                if (m)
-                       (void) m_freem(m);
-               return;
+                       m_freem(m);
+               return (error);
        }
 
 restart:
        }
 
 restart:
@@ -426,9 +453,11 @@ restart:
                        so->so_rcv.sb_mbcnt -= MSIZE;
                }
                if (aname) {
                        so->so_rcv.sb_mbcnt -= MSIZE;
                }
                if (aname) {
-                       if (flags & SOF_PREVIEW)
+                       if (flags & SOF_PREVIEW) {
                                *aname = m_copy(m, 0, m->m_len);
                                *aname = m_copy(m, 0, m->m_len);
-                       else
+                               if (*aname == NULL)
+                                       panic("receive 2");
+                       } else
                                *aname = m;
                        m = m->m_next;
                        (*aname)->m_next = 0;
                                *aname = m;
                        m = m->m_next;
                        (*aname)->m_next = 0;
@@ -438,7 +467,9 @@ restart:
                        else
                                m = m_free(m);
                if (m == 0)
                        else
                                m = m_free(m);
                if (m == 0)
-                       panic("receive 2");
+                       panic("receive 3");
+               if ((flags & SOF_PREVIEW) == 0)
+                       so->so_rcv.sb_mb = m;
        }
        eor = 0;
        moff = 0;
        }
        eor = 0;
        moff = 0;
@@ -450,10 +481,11 @@ restart:
                so->so_state &= ~SS_RCVATMARK;
                if (tomark && len > tomark)
                        len = tomark;
                so->so_state &= ~SS_RCVATMARK;
                if (tomark && len > tomark)
                        len = tomark;
-               if (len > m->m_len - moff)
+               if (moff+len > m->m_len - moff)
                        len = m->m_len - moff;
                splx(s);
                        len = m->m_len - moff;
                splx(s);
-               uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
+               error =
+                   uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
                s = splnet();
                if (len == m->m_len) {
                        eor = (int)m->m_act;
                s = splnet();
                if (len == m->m_len) {
                        eor = (int)m->m_act;
@@ -463,6 +495,7 @@ restart:
                                sbfree(&so->so_rcv, m);
                                MFREE(m, n);
                                m = n;
                                sbfree(&so->so_rcv, m);
                                MFREE(m, n);
                                m = n;
+                               so->so_rcv.sb_mb = m;
                        }
                        moff = 0;
                } else {
                        }
                        moff = 0;
                } else {
@@ -486,14 +519,13 @@ restart:
                        if (tomark == 0)
                                break;
                }
                        if (tomark == 0)
                                break;
                }
-       } while (m && !eor);
+       } while (m && error == 0 && !eor);
        if (flags & SOF_PREVIEW)
                goto release;
        if (flags & SOF_PREVIEW)
                goto release;
-       so->so_rcv.sb_mb = m;
        if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
                do {
                        if (m == 0)
        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;
                        sbfree(&so->so_rcv, m);
                        eor = (int)m->m_act;
                        so->so_rcv.sb_mb = m->m_next;
@@ -502,13 +534,97 @@ restart:
                } while (eor == 0);
        if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
                (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
                } while (eor == 0);
        if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
                (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
-                   (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
+                   (struct mbuf *)0, (struct mbuf *)0);
 release:
        sbunlock(&so->so_rcv);
        splx(s);
        return (error);
 }
 
 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;
 {
 sohasoutofband(so)
        struct socket *so;
 {
@@ -539,106 +655,37 @@ soioctl(so, cmd, data)
                        so->so_state |= SS_NBIO;
                else
                        so->so_state &= ~SS_NBIO;
                        so->so_state |= SS_NBIO;
                else
                        so->so_state &= ~SS_NBIO;
-               return;
+               break;
 
        case FIOASYNC:
                if (*(int *)data)
                        so->so_state |= SS_ASYNC;
                else
                        so->so_state &= ~SS_ASYNC;
 
        case FIOASYNC:
                if (*(int *)data)
                        so->so_state |= SS_ASYNC;
                else
                        so->so_state &= ~SS_ASYNC;
-               return;
-
-       case SIOCSKEEP:
-               if (*(int *)data)
-                       so->so_options &= ~SO_KEEPALIVE;
-               else
-                       so->so_options |= SO_KEEPALIVE;
-               return;
-
-       case SIOCGKEEP:
-               *(int *)data = (so->so_options & SO_KEEPALIVE) != 0;
-               return;
-
-       case SIOCSLINGER:
-               so->so_linger = *(int *)data;
-               if (so->so_linger)
-                       so->so_options &= ~SO_DONTLINGER;
-               else
-                       so->so_options |= SO_DONTLINGER;
-               return;
-
-       case SIOCGLINGER:
-               *(int *)data = so->so_linger;
-               return;
+               break;
 
        case SIOCSPGRP:
                so->so_pgrp = *(int *)data;
 
        case SIOCSPGRP:
                so->so_pgrp = *(int *)data;
-               return;
+               break;
 
        case SIOCGPGRP:
                *(int *)data = so->so_pgrp;
 
        case SIOCGPGRP:
                *(int *)data = so->so_pgrp;
-               return;
-
-       case SIOCDONE: {
-               int flags = *(int *)data;
-
-               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, (struct mbuf *)0,
-                           (struct socketopt *)0);
-               return;
-       }
-
-       case SIOCSENDOOB: {
-               char oob = *(char *)data;
-               struct mbuf *m = m_get(M_DONTWAIT);
-
-               if (m == 0) {
-                       u.u_error = ENOBUFS;
-                       return;
-               }
-               m->m_len = 1;
-               *mtod(m, char *) = oob;
-               (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB,
-                   m, (struct mbuf *)0, (struct socketopt *)0);
-               return;
-       }
-
-       case SIOCRCVOOB: {
-               struct mbuf *m = m_get(M_WAIT);
-
-               if (m == 0) {
-                       u.u_error = ENOBUFS;
-                       return;
-               }
-               *mtod(m, caddr_t) = 0;
-               (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
-                   m, (struct mbuf *)0, (struct socketopt *)0);
-               *(char *)data = *mtod(m, char *);
-               (void) m_free(m);
-               return;
-       }
+               break;
 
        case SIOCATMARK:
                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
 
        case SIOCATMARK:
                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
-               return;
+               break;
 
        /* routing table update calls */
        case SIOCADDRT:
        case SIOCDELRT:
                if (!suser())
 
        /* routing table update calls */
        case SIOCADDRT:
        case SIOCDELRT:
                if (!suser())
-                       return;
-               u.u_error = rtrequest(cmd, (struct rtentry *)data);
-               return;
+                       return (u.u_error);
+               return (rtrequest(cmd, (struct rtentry *)data));
 
        /* type/protocol specific ioctls */
 
        /* type/protocol specific ioctls */
+       default:
+               return (ENOTTY);                /* XXX */
        }
        }
-       u.u_error = EOPNOTSUPP;
+       return (0);
 }
 }