NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/43959: [dM] sl(4) IPv6 support



>Number:         43959
>Category:       kern
>Synopsis:       [dM] Add IPv6 support to sl(4)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Oct 10 08:35:00 +0000 2010
>Originator:     der Mouse
>Release:        NetBSD 4.0.1
>Organization:
        Dis-
>Environment:
        Any 4.0.1
>Description:
        sl(4) does not support any protocols except IPv4.  This is an
        implementation of an extension of it to support IPv6 as well,
        as outlined in ftp.rodents-montreal.org:/mouse/misc/ipv6-slip.
>How-To-Repeat:
        Want to send v6 over SLIP.  Discover it isn't supported.
>Fix:
        If this is adopted, the document mentioned in "Description"
        probably should be imported somewhere and referenced from
        sl(4).  I'm not sure where would be most appropriate, though,
        so I've made no attempt to do that here.

        --- base/sys/net/if_slvar.h     Wed Jun  7 18:33:43 2006
        +++ live/sys/net/if_slvar.h     Sun Oct 10 04:10:48 2010
        @@ -52,6 +52,7 @@
                struct mbuf *sc_mbuf;           /* input buffer */
                u_int   sc_flags;               /* see below */
                u_int   sc_escape;      /* =1 if last char input was 
FRAME_ESCAPE */
        +       int     sc_af;                  /* AF_INET, AF_INET6, etc - 
input */
                long    sc_lasttime;            /* last time a char arrived */
                long    sc_abortcount;          /* number of abort esacpe chars 
*/
                long    sc_starttime;           /* time of first abort in 
window */

        --- base/sys/net/if_sl.c        Wed Nov 15 20:33:40 2006
        +++ live/sys/net/if_sl.c        Sun Oct 10 04:10:47 2010
        @@ -90,11 +90,16 @@
         #include <net/netisr.h>
         #include <net/route.h>
         
        -#ifdef INET
        +#if defined(INET) || defined(INET6)
         #include <netinet/in.h>
         #include <netinet/in_systm.h>
         #include <netinet/in_var.h>
         #include <netinet/ip.h>
        +#else
        +#error "SLIP with neither INET nor INET6?"
        +#endif
        +#ifdef INET6
        +#include <netinet/ip6.h>
         #endif
         
         #include <net/slcompress.h>
        @@ -186,6 +191,8 @@
         #define FRAME_ESCAPE           0xdb            /* Frame Esc */
         #define TRANS_FRAME_END                0xdc            /* transposed 
frame end */
         #define TRANS_FRAME_ESCAPE     0xdd            /* transposed frame esc 
*/
        +#define TRANS_PKTTYPE_BASE     0x80            /* packet type base */
        +#define PKTTYPE_IPv6           0               /* packet is a v6 
packet */
         
         #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
         void   slnetisr(void);
        @@ -252,6 +259,7 @@
         #if NBPFILTER > 0
                bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
         #endif
        +       sc->sc_af = AF_INET;
                LIST_INSERT_HEAD(&sl_softc_list, sc, sc_iflist);
                return 0;
         }
        @@ -463,16 +471,23 @@
         
                IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
         
        -       /*
        -        * `Cannot happen' (see slioctl).  Someday we will extend
        -        * the line protocol to support other address families.
        -        */
        -       if (dst->sa_family != AF_INET) {
        -               printf("%s: af%d not supported\n", sc->sc_if.if_xname,
        -                   dst->sa_family);
        -               m_freem(m);
        -               sc->sc_if.if_noproto++;
        -               return EAFNOSUPPORT;
        +       switch (dst->sa_family) {
        +#ifdef INET
        +               case AF_INET:
        +                       break;
        +#endif
        +#ifdef INET6
        +               case AF_INET6:
        +                       break;
        +#endif
        +               default:
        +                       /* "can't happen"; slioctl won't set others */
        +                       printf("%s: af%d not supported\n",
        +                               &sc->sc_if.if_xname[0], dst->sa_family);
        +                       m_freem(m);
        +                       sc->sc_if.if_noproto++;
        +                       return EAFNOSUPPORT;
        +                       break;
                }
         
                if (sc->sc_ttyp == NULL) {
        @@ -485,13 +500,24 @@
                        printf("%s: no carrier and not local\n", 
sc->sc_if.if_xname);
                        return EHOSTUNREACH;
                }
        -       ip = mtod(m, struct ip *);
         #ifdef INET
        -       if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) 
{
        -               m_freem(m);
        -               return ENETRESET;               /* XXX ? */
        +       /* XXX really should do likewise for icmp6! */
        +       if (dst->sa_family == AF_INET) {
        +               ip = mtod(m, struct ip *);
        +               if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == 
IPPROTO_ICMP) {
        +                       m_freem(m);
        +                       return ENETRESET;               /* XXX ? */
        +               }
        +               if ((ip->ip_tos & IPTOS_LOWDELAY) != 0)
        +                       ifq = &sc->sc_fastq;
                }
         #endif
        +       M_PREPEND(m,dst->sa_len,M_DONTWAIT);
        +       if (m == 0) {
        +               sc->sc_if.if_oerrors ++;
        +               return(ENOBUFS);
        +       }
        +       bcopy(dst,mtod(m,char *),dst->sa_len);
         
                s = spltty();
                if (sc->sc_oqlen && sc->sc_ttyp->t_outq.c_cc == sc->sc_oqlen) {
        @@ -508,10 +534,6 @@
                splx(s);
         
                s = splnet();
        -#ifdef INET
        -       if ((ip->ip_tos & IPTOS_LOWDELAY) != 0)
        -               ifq = &sc->sc_fastq;
        -#endif
                if ((error = ifq_enqueue2(ifp, ifq, m ALTQ_COMMA
                    ALTQ_DECL(&pktattr))) != 0) {
                        splx(s);
        @@ -660,6 +682,14 @@
                                c = FRAME_END;
                        break;
         
        +       case TRANS_PKTTYPE_BASE + PKTTYPE_IPv6:
        +               if (sc->sc_escape) {
        +                       sc->sc_af = AF_INET6;
        +                       sc->sc_escape = 0;
        +                       return(0);
        +               }
        +               break;
        +
                case FRAME_ESCAPE:
                        sc->sc_escape = 1;
                        return 0;
        @@ -678,6 +708,12 @@
                        if (m == NULL)
                                goto error;
         
        +               M_PREPEND(m,sizeof(int),M_DONTWAIT);
        +               if (m == 0)
        +                       goto error;
        +
        +               bcopy(&sc->sc_af,mtod(m,int *),sizeof(int));
        +
                        IF_ENQUEUE(&sc->sc_inq, m);
         #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                        softintr_schedule(sc->sc_si);
        @@ -705,6 +741,7 @@
                sc->sc_mp = sc->sc_pktstart = (u_char 
*)sc->sc_mbuf->m_ext.ext_buf +
                    BUFOFFSET;
                sc->sc_escape = 0;
        +       sc->sc_af = AF_INET;
         
                return 0;
         }
        @@ -748,6 +785,8 @@
                        struct ip *ip;
         #endif
                        struct mbuf *m2;
        +               struct sockaddr_storage dst;
        +               struct sockaddr *dstp;
         #if NBPFILTER > 0
                        struct mbuf *bpf_m;
         #endif
        @@ -781,6 +820,14 @@
                                break;
         
                        /*
        +                * We know (because we added it ourselves) that the
        +                *  destination address is entirely in the first mbuf.
        +                */
        +               dstp = mtod(m,struct sockaddr *);
        +               bcopy(dstp,&dst,dstp->sa_len);
        +               m_adj(m,dst.ss_len);
        +
        +               /*
                         * We do the header compression here rather than in
                         * sloutput() because the packets will be out of order
                         * if we are using TOS queueing, and the connection
        @@ -802,7 +849,8 @@
                                bpf_m = NULL;
         #endif
         #ifdef INET
        -               if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
        +               if ( (dst.ss_family == AF_INET) &&
        +                    ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) 
) {
                                if (sc->sc_if.if_flags & SC_COMPRESS)
                                        *mtod(m, u_char *) |=
                                            sl_compress_tcp(m, ip, 
&sc->sc_comp, 1);
        @@ -828,6 +876,31 @@
                                (void)putc(FRAME_END, &tp->t_outq);
                        }
         
        +               switch (dst.ss_family) {
        +#ifdef INET
        +                       case AF_INET:
        +                               break;
        +#endif
        +#ifdef INET6
        +                       case AF_INET6:
        +                               if (! putc(FRAME_ESCAPE,&tp->t_outq)) {
        +                                       if (! 
putc(TRANS_PKTTYPE_BASE+PKTTYPE_IPv6,&tp->t_outq)) {
        +                                               sc->sc_if.if_obytes += 
2;
        +                                       } else {
        +                                               unputc(&tp->t_outq);
        +                                       }
        +                               } else {
        +                                       sc->sc_if.if_oerrors ++;
        +                                       m_freem(m);
        +                                       continue;
        +                               }
        +                               break;
        +#endif
        +                       default:
        +                               panic("slstart: impossible 
dst.ss_family");
        +                               break;
        +               }
        +
                        while (m) {
                                u_char *bp, *cp, *ep;
         
        @@ -910,11 +983,16 @@
                 * Input processing loop.
                 */
                for (;;) {
        +               int af;
        +               struct ifqueue *queue;
        +               int isr;
                        s = spltty();
                        IF_DEQUEUE(&sc->sc_inq, m);
                        splx(s);
                        if (m == NULL)
                                break;
        +               bcopy(mtod(m,int *),&af,sizeof(int));
        +               m_adj(m,sizeof(int));
                        pktstart = mtod(m, u_char *);
                        len = m->m_pkthdr.len;
         #if NBPFILTER > 0
        @@ -931,7 +1009,7 @@
                        }
         #endif /* NBPFILTER > 0 */
         #ifdef INET
        -               if ((c = (*pktstart & 0xf0)) != (IPVERSION << 4)) {
        +               if ((af == AF_INET) && ((c = (*pktstart & 0xf0)) != 
(IPVERSION << 4))) {
                                if (c & 0x80)
                                        c = TYPE_COMPRESSED_TCP;
                                else if (c == TYPE_UNCOMPRESSED_TCP)
        @@ -997,24 +1075,43 @@
                        sc->sc_if.if_ipackets++;
                        getbinuptime(&sc->sc_lastpacket);
         
        +               queue = 0;
        +               switch (af) {
        +                       case AF_INET:
         #ifdef INET
        -               s = splnet();
        -               if (IF_QFULL(&ipintrq)) {
        -                       IF_DROP(&ipintrq);
        +                               queue = &ipintrq;
        +                               isr = NETISR_IP;
        +#endif
        +                               break;
        +                       case AF_INET6:
        +#ifdef INET6
        +                               queue = &ip6intrq;
        +                               isr = NETISR_IPV6;
        +#endif
        +                               break;
        +                       default:
        +                               panic("slinput impossible af");
        +                               break;
        +               }
        +               if (queue == 0) {
        +                       /* af not in this kernel! */
        +                       sc->sc_if.if_ierrors ++;
        +                       m_freem(m);
        +               } else if (IF_QFULL(queue)) {
        +                       IF_DROP(queue);
                                sc->sc_if.if_ierrors++;
                                sc->sc_if.if_iqdrops++;
                                m_freem(m);
                        } else {
        -                       IF_ENQUEUE(&ipintrq, m);
        -                       schednetisr(NETISR_IP);
        +                       IF_ENQUEUE(queue, m);
        +                       schednetisr(isr);
                        }
                        splx(s);
        -#endif
                }
         }
         
         /*
        - * Process an ioctl request.
        + * Process a (network interface) ioctl request.
          */
         static int
         slioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        @@ -1029,13 +1126,40 @@
                switch (cmd) {
         
                case SIOCSIFADDR:
        -               if (ifa->ifa_addr->sa_family == AF_INET)
        -                       ifp->if_flags |= IFF_UP;
        -               else
        -                       error = EAFNOSUPPORT;
        +               switch (ifa->ifa_addr->sa_family) {
        +#ifdef INET
        +                       case AF_INET:
        +                               ifp->if_flags |= IFF_UP;
        +                               break;
        +#endif
        +#ifdef INET6
        +                       case AF_INET6:
        +                               ifp->if_flags |= IFF_UP;
        +                               if (sc->sc_if.if_mtu < IPV6_MMTU)
        +                                       sc->sc_if.if_mtu = IPV6_MMTU;
        +                               break;
        +#endif
        +                       default:
        +                               error = EAFNOSUPPORT;
        +                               break;
        +               }
                        break;
         
                case SIOCSIFDSTADDR:
        +               switch (ifa->ifa_addr->sa_family) {
        +#ifdef INET
        +                       case AF_INET:
        +                               break;
        +#endif
        +#ifdef INET6
        +                       case AF_INET6:
        +                               break;
        +#endif
        +                       default:
        +                               error = EAFNOSUPPORT;
        +                               break;
        +               }
        +
                        if (ifa->ifa_addr->sa_family != AF_INET)
                                error = EAFNOSUPPORT;
                        break;
        @@ -1045,6 +1169,20 @@
                            error = EINVAL;
                            break;
                        }
        +#ifdef INET6
        +               if (ifr->ifr_mtu < IPV6_MMTU) {
        +                       /* If we have any v6 address set, reject! */
        +                       struct ifaddr *ifa2;
        +                       for ( ifa2 = sc->sc_if.if_addrlist.tqh_first;
        +                             ifa2;
        +                             ifa2 = ifa2->ifa_list.tqe_next )
        +                               switch (((struct sockaddr 
*)ifa2->ifa_addr)->sa_family) {
        +                                       case AF_INET6:
        +                                               error = EINVAL;
        +                                               goto done; /* break 
switch, for, switch */
        +                               }
        +               }
        +#endif
                        sc->sc_if.if_mtu = ifr->ifr_mtu;
                        break;
         
        @@ -1059,12 +1197,14 @@
                                break;
                        }
                        switch (ifr->ifr_addr.sa_family) {
        -
         #ifdef INET
                        case AF_INET:
                                break;
         #endif
        -
        +#ifdef INET6
        +               case AF_INET6:
        +                       break;
        +#endif
                        default:
                                error = EAFNOSUPPORT;
                                break;
        @@ -1100,6 +1240,9 @@
                default:
                        error = EINVAL;
                }
        +#ifdef INET6
        +done:;
        +#endif
                splx(s);
                return error;
         }

        --- base/share/man/man4/sl.4    Sun Jul  9 05:21:35 2006
        +++ live/share/man/man4/sl.4    Sun Oct 10 04:20:46 2010
        @@ -123,18 +123,24 @@
         device appeared in
         .Nx 1.0 .
         .Sh BUGS
        +Standard
         .Tn SLIP
        -can only transmit
        +can transmit only
         .Tn IPv4
        -packets between preconfigured hosts on an asynchronous serial link.
        -It has no provision for address negotiation,
        -carriage of additional protocols (e.g.
        +packets between preconfigured hosts on an asynchronous serial link; the
        +.Nx
        +implementation has been enhanced to support
        +.Tn IPv6
        +as well.  It has no provision for address negotiation and is not
        +designed for synchronous serial links.  There is no support for other
        +protocols (e.g.
         .Tn XNS ,
         .Tn AppleTalk ,
         .Tn DECNET ) ,
        -and is not designed for synchronous serial links.
        -This is why
        +though they would be relatively easy to add.  These are among the
        +reasons why
         .Tn SLIP
        -has been superseded by the Point-to-Point Protocol
        +has for most applications been superseded by the Point-to-Point
        +Protocol
         .Pq Tn PPP ,
        -which does all of those things, and much more.
        +which does all of those things and much more.



Home | Main Index | Thread Index | Old Index