summaryrefslogtreecommitdiffstats
path: root/sys/contrib/pf
diff options
context:
space:
mode:
authordhartmei <dhartmei@FreeBSD.org>2007-05-21 20:08:59 +0000
committerdhartmei <dhartmei@FreeBSD.org>2007-05-21 20:08:59 +0000
commitf33636c0a214a610c128fd02673596aa082687ff (patch)
treed3dc6cfadd3aed1cc2e9a21af1e45ff777950676 /sys/contrib/pf
parent92efd303a02076f7c1bb177d50edebceb9cd2e8e (diff)
downloadFreeBSD-src-f33636c0a214a610c128fd02673596aa082687ff.zip
FreeBSD-src-f33636c0a214a610c128fd02673596aa082687ff.tar.gz
From OpenBSD, rev. 1.524, 1.528, 1.529
Deal with IPv6 routing headers (see FreeBSD-SA-07:03.ipv6 for background) Block IPv6 packets with routing headers by default, unless 'allow-opts' is specified. Block RH0 unconditionally. Deal with ip6_plen 0. MFC after: 1 week Discussed with: mlaier
Diffstat (limited to 'sys/contrib/pf')
-rw-r--r--sys/contrib/pf/net/pf.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 15cff43..282cbb5 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -6780,7 +6780,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_pdesc pd;
- int off, terminal = 0, dirndx;
+ int off, terminal = 0, dirndx, rh_cnt = 0;
#ifdef __FreeBSD__
PF_LOCK();
@@ -6844,6 +6844,18 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
m = *m0;
h = mtod(m, struct ip6_hdr *);
+#if 1
+ /*
+ * we do not support jumbogram yet. if we keep going, zero ip6_plen
+ * will do something bad, so drop the packet for now.
+ */
+ if (htons(h->ip6_plen) == 0) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_NORM); /*XXX*/
+ goto done;
+ }
+#endif
+
pd.src = (struct pf_addr *)&h->ip6_src;
pd.dst = (struct pf_addr *)&h->ip6_dst;
PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
@@ -6863,9 +6875,38 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
if (action == PF_DROP)
REASON_SET(&reason, PFRES_FRAG);
goto done;
+ case IPPROTO_ROUTING: {
+ struct ip6_rthdr rthdr;
+
+ if (rh_cnt++) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 more than one rthdr\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ goto done;
+ }
+ if (!pf_pull_hdr(m, off, &rthdr, sizeof(rthdr), NULL,
+ &reason, pd.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 short rthdr\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ log = 1;
+ goto done;
+ }
+ if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 rthdr0\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ goto done;
+ }
+ /* fallthrough */
+ }
case IPPROTO_AH:
case IPPROTO_HOPOPTS:
- case IPPROTO_ROUTING:
case IPPROTO_DSTOPTS: {
/* get next header and header length */
struct ip6_ext opt6;
@@ -7032,7 +7073,15 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
}
done:
- /* XXX handle IPv6 options, if not allowed. not implemented. */
+ /* handle dangerous IPv6 extension headers. */
+ if (action == PF_PASS && rh_cnt &&
+ !((s && s->allow_opts) || r->allow_opts)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: dropping packet with dangerous v6 headers\n"));
+ }
if (s && s->tag)
pf_tag_packet(m, pf_get_tag(m), s->tag);
OpenPOWER on IntegriCloud