Hi,

Our IPv6 stack scans all extension headers for routing header type
0 and drops the packet if it finds one.  RFC 5095 demands to handle
a routing header type 0 like an unrecognised routing type.  This
is enough to protect the own machine.

To protect a network as a firewall, we have pf which does the same
full scan in pf_walk_header6().  As pf is enabled by default, nothing
changes for most users.  If you turn off pf on your router, you
should not expect extra protection.

I would like to get rid of the double scanning and the old disabled
code in the IPv6 stack.

ok?

bluhm

Index: netinet6/ip6_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.115
diff -u -p -u -p -r1.115 ip6_input.c
--- netinet6/ip6_input.c        17 Oct 2013 16:27:46 -0000      1.115
+++ netinet6/ip6_input.c        18 Oct 2013 17:21:52 -0000
@@ -122,7 +122,6 @@ struct ifqueue ip6intrq;
 struct ip6stat ip6stat;
 
 void ip6_init2(void *);
-int ip6_check_rh0hdr(struct mbuf *, int *);
 
 int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
 struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
@@ -318,15 +317,6 @@ ip6_input(struct mbuf *m)
        }
 #endif
 
-       if (ip6_check_rh0hdr(m, &off)) {
-               ip6stat.ip6s_badoptions++;
-               in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
-               in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
-               icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, off);
-               /* m is already freed */
-               return;
-       }
-
 #if NPF > 0
         /*
          * Packet filter
@@ -705,74 +695,6 @@ ip6_input(struct mbuf *m)
        return;
  bad:
        m_freem(m);
-}
-
-/* scan packet for RH0 routing header. Mostly stolen from pf.c:pf_test() */
-int
-ip6_check_rh0hdr(struct mbuf *m, int *offp)
-{
-       struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
-       struct ip6_rthdr rthdr;
-       struct ip6_ext opt6;
-       u_int8_t proto = ip6->ip6_nxt;
-       int done = 0, lim, off, rh_cnt = 0;
-
-       off = ((caddr_t)ip6 - m->m_data) + sizeof(struct ip6_hdr);
-       lim = min(m->m_pkthdr.len, ntohs(ip6->ip6_plen) + sizeof(*ip6));
-       do {
-               switch (proto) {
-               case IPPROTO_ROUTING:
-                       *offp = off;
-                       if (rh_cnt++) {
-                               /* more then one rh header present */
-                               return (1);
-                       }
-
-                       if (off + sizeof(rthdr) > lim) {
-                               /* packet to short to make sense */
-                               return (1);
-                       }
-
-                       m_copydata(m, off, sizeof(rthdr), (caddr_t)&rthdr);
-
-                       if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
-                               *offp += offsetof(struct ip6_rthdr, ip6r_type);
-                               return (1);
-                       }
-
-                       off += (rthdr.ip6r_len + 1) * 8;
-                       proto = rthdr.ip6r_nxt;
-                       break;
-               case IPPROTO_AH:
-               case IPPROTO_HOPOPTS:
-               case IPPROTO_DSTOPTS:
-                       /* get next header and header length */
-                       if (off + sizeof(opt6) > lim) {
-                               /*
-                                * Packet to short to make sense, we could
-                                * reject the packet but as a router we 
-                                * should not do that so forward it.
-                                */
-                               return (0);
-                       }
-
-                       m_copydata(m, off, sizeof(opt6), (caddr_t)&opt6);
-
-                       if (proto == IPPROTO_AH)
-                               off += (opt6.ip6e_len + 2) * 4;
-                       else
-                               off += (opt6.ip6e_len + 1) * 8;
-                       proto = opt6.ip6e_nxt;
-                       break;
-               case IPPROTO_FRAGMENT:
-               default:
-                       /* end of header stack */
-                       done = 1;
-                       break;
-               }
-       } while (!done);
-
-       return (0);
 }
 
 /*
Index: netinet6/route6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/route6.c,v
retrieving revision 1.17
diff -u -p -u -p -r1.17 route6.c
--- netinet6/route6.c   11 Jun 2008 19:00:50 -0000      1.17
+++ netinet6/route6.c   18 Oct 2013 17:59:45 -0000
@@ -44,10 +44,6 @@
 
 #include <netinet/icmp6.h>
 
-#if 0
-static int ip6_rthdr0(struct mbuf *, struct ip6_hdr *, struct ip6_rthdr0 *);
-#endif
-
 /*
  * proto is unused
  */
@@ -68,43 +64,12 @@ route6_input(struct mbuf **mp, int *offp
        }
 
        switch (rh->ip6r_type) {
-#if 0
-       /*
-        * See http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf
-        * for why IPV6_RTHDR_TYPE_0 is banned here.
-        *
-        * We return ICMPv6 parameter problem so that innocent people
-        * (not an attacker) would notice about the use of IPV6_RTHDR_TYPE_0.
-        * Since there's no amplification, and ICMPv6 error will be rate-
-        * controlled, it shouldn't cause any problem.
-        * If you are concerned about this, you may want to use the following
-        * code fragment:
-        *
-        * case IPV6_RTHDR_TYPE_0:
-        *      m_freem(m);
-        *      return (IPPROTO_DONE);
-        */
        case IPV6_RTHDR_TYPE_0:
-               rhlen = (rh->ip6r_len + 1) << 3;
-               if (rh->ip6r_segleft == 0)
-                       break;  /* Final dst. Just ignore the header. */
                /*
-                * note on option length:
-                * maximum rhlen: 2048
-                * max mbuf m_pulldown can handle: MCLBYTES == usually 2048
-                * so, here we are assuming that m_pulldown can handle
-                * rhlen == 2048 case.  this may not be a good thing to
-                * assume - we may want to avoid pulling it up altogether.
+                * RFC 5095 specifies to handle routing header type 0
+                * the same way as an unrecognised routing type.
                 */
-               IP6_EXTHDR_GET(rh, struct ip6_rthdr *, m, off, rhlen);
-               if (rh == NULL) {
-                       ip6stat.ip6s_tooshort++;
-                       return IPPROTO_DONE;
-               }
-               if (ip6_rthdr0(m, ip6, (struct ip6_rthdr0 *)rh))
-                       return (IPPROTO_DONE);
-               break;
-#endif
+               /* FALLTHROUGH */
        default:
                /* unknown routing type */
                if (rh->ip6r_segleft == 0) {
@@ -120,83 +85,3 @@ route6_input(struct mbuf **mp, int *offp
        *offp += rhlen;
        return (rh->ip6r_nxt);
 }
-
-#if 0
-/*
- * Type0 routing header processing
- *
- * RFC2292 backward compatibility warning: no support for strict/loose bitmap,
- * as it was dropped between RFC1883 and RFC2460.
- */
-static int
-ip6_rthdr0(struct mbuf *m, struct ip6_hdr *ip6, struct ip6_rthdr0 *rh0)
-{
-       int addrs, index;
-       struct in6_addr *nextaddr, tmpaddr;
-
-       if (rh0->ip6r0_segleft == 0)
-               return (0);
-
-       if (rh0->ip6r0_len % 2) {
-               /*
-                * Type 0 routing header can't contain more than 23 addresses.
-                * RFC 2460: this limitation was removed since strict/loose
-                * bitmap field was deleted.
-                */
-               ip6stat.ip6s_badoptions++;
-               icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
-                           (caddr_t)&rh0->ip6r0_len - (caddr_t)ip6);
-               return (-1);
-       }
-
-       if ((addrs = rh0->ip6r0_len / 2) < rh0->ip6r0_segleft) {
-               ip6stat.ip6s_badoptions++;
-               icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
-                           (caddr_t)&rh0->ip6r0_segleft - (caddr_t)ip6);
-               return (-1);
-       }
-
-       index = addrs - rh0->ip6r0_segleft;
-       rh0->ip6r0_segleft--;
-       nextaddr = ((struct in6_addr *)(rh0 + 1)) + index;
-
-       /*
-        * reject invalid addresses.  be proactive about malicious use of
-        * IPv4 mapped/compat address.
-        * XXX need more checks?
-        */
-       if (IN6_IS_ADDR_MULTICAST(nextaddr) ||
-           IN6_IS_ADDR_UNSPECIFIED(nextaddr) ||
-           IN6_IS_ADDR_V4MAPPED(nextaddr) ||
-           IN6_IS_ADDR_V4COMPAT(nextaddr)) {
-               ip6stat.ip6s_badoptions++;
-               goto bad;
-       }
-       if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
-           IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst) ||
-           IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst) ||
-           IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
-               ip6stat.ip6s_badoptions++;
-               goto bad;
-       }
-
-       /*
-        * Swap the IPv6 destination address and nextaddr. Forward the packet.
-        */
-       tmpaddr = *nextaddr;
-       *nextaddr = ip6->ip6_dst;
-       if (IN6_IS_ADDR_LINKLOCAL(nextaddr))
-               nextaddr->s6_addr16[1] = 0;
-       ip6->ip6_dst = tmpaddr;
-       if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
-               ip6->ip6_dst.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
-
-       ip6_forward(m, 1);
-
-       return (-1);                    /* m would be freed in ip6_forward() */
-
-  bad:
-       m_freem(m);
-       return (-1);
-}
-#endif

Reply via email to