Index: netinet6/ip6_input.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.77 diff -u -r1.77 ip6_input.c --- netinet6/ip6_input.c 28 May 2007 17:16:39 -0000 1.77 +++ netinet6/ip6_input.c 3 Aug 2007 05:30:32 -0000 @@ -415,10 +415,11 @@ if (in6m) ours = 1; #ifdef MROUTING - else if (!ip6_mforwarding || !ip6_mrouter) { + else if (!ip6_mforwarding || !ip6_mrouter) #else - else { + else #endif + { ip6stat.ip6s_notmember++; if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) ip6stat.ip6s_cantforward++; @@ -724,20 +725,22 @@ struct ip6_rthdr rthdr; struct ip6_ext opt6; u_int8_t proto = ip6->ip6_nxt; - int done = 0, lim, off, rh_cnt = 0; + int done = 0, lim, off, rh_cnt = 0, hbh_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: - if (rh_cnt++) + if (rh_cnt++) { /* more then one rh header present */ return (1); + } - if (off + sizeof(opt6) > lim) + if (off + sizeof(opt6) > lim) { /* packet to short to make sense */ return (1); + } m_copydata(m, off, sizeof(rthdr), (caddr_t)&rthdr); @@ -747,17 +750,33 @@ off += (rthdr.ip6r_len + 1) * 8; proto = rthdr.ip6r_nxt; break; - case IPPROTO_AH: case IPPROTO_HOPOPTS: + if (hbh_cnt++) { + /* more then one hbh header present */ + return (1); + } + + if (off + sizeof(opt6) > lim) { + /* packet to short to make sense */ + return (1); + } + + m_copydata(m, off, sizeof(opt6), (caddr_t)&opt6); + + off += (opt6.ip6e_len + 1) * 8; + proto = opt6.ip6e_nxt; + break; + case IPPROTO_AH: case IPPROTO_DSTOPTS: /* get next header and header length */ - if (off + sizeof(opt6) > lim) + 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); Index: net/pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.551 diff -u -r1.551 pf.c --- net/pf.c 18 Jul 2007 15:39:44 -0000 1.551 +++ net/pf.c 3 Aug 2007 05:30:34 -0000 @@ -5663,6 +5663,7 @@ struct pf_ruleset *ruleset = NULL; struct pf_pdesc pd; int off, terminal = 0, dirndx, rh_cnt = 0; + int hbh_cnt = 0; if (!pf_status.running) return (PF_PASS); @@ -5763,14 +5764,25 @@ log = 1; goto done; } - /* FALLTHROUGH */ + goto common; + } + case IPPROTO_HOPOPTS: { + if (hbh_cnt++) { + DPFPRINTF(PF_DEBUG_MISC, + ("pf: IPv6 more than one hbhhdr\n")); + action = PF_DROP; + REASON_SET(&reason, PFRES_IPOPTIONS); + log = 1; + goto done; + } + goto common; } case IPPROTO_AH: - case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: { /* get next header and header length */ struct ip6_ext opt6; + common: if (!pf_pull_hdr(m, off, &opt6, sizeof(opt6), NULL, &reason, pd.af)) { DPFPRINTF(PF_DEBUG_MISC,