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
This commit is contained in:
parent
bf5a3266f7
commit
67debc100c
@ -6780,7 +6780,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
|
|||||||
struct pf_state *s = NULL;
|
struct pf_state *s = NULL;
|
||||||
struct pf_ruleset *ruleset = NULL;
|
struct pf_ruleset *ruleset = NULL;
|
||||||
struct pf_pdesc pd;
|
struct pf_pdesc pd;
|
||||||
int off, terminal = 0, dirndx;
|
int off, terminal = 0, dirndx, rh_cnt = 0;
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
PF_LOCK();
|
PF_LOCK();
|
||||||
@ -6844,6 +6844,18 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
|
|||||||
m = *m0;
|
m = *m0;
|
||||||
h = mtod(m, struct ip6_hdr *);
|
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.src = (struct pf_addr *)&h->ip6_src;
|
||||||
pd.dst = (struct pf_addr *)&h->ip6_dst;
|
pd.dst = (struct pf_addr *)&h->ip6_dst;
|
||||||
PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
|
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)
|
if (action == PF_DROP)
|
||||||
REASON_SET(&reason, PFRES_FRAG);
|
REASON_SET(&reason, PFRES_FRAG);
|
||||||
goto done;
|
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_AH:
|
||||||
case IPPROTO_HOPOPTS:
|
case IPPROTO_HOPOPTS:
|
||||||
case IPPROTO_ROUTING:
|
|
||||||
case IPPROTO_DSTOPTS: {
|
case IPPROTO_DSTOPTS: {
|
||||||
/* get next header and header length */
|
/* get next header and header length */
|
||||||
struct ip6_ext opt6;
|
struct ip6_ext opt6;
|
||||||
@ -7032,7 +7073,15 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
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)
|
if (s && s->tag)
|
||||||
pf_tag_packet(m, pf_get_tag(m), s->tag);
|
pf_tag_packet(m, pf_get_tag(m), s->tag);
|
||||||
|
Loading…
Reference in New Issue
Block a user