summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2011-08-20 12:40:17 +0000
committerbz <bz@FreeBSD.org>2011-08-20 12:40:17 +0000
commitbb3e0f18c0249c086c567a4d0d1e2f321587dcb2 (patch)
tree1f68c87586f7e3a223ca18179d8a1eaf688b64df
parent4fe768ed74241f0a8b1c73e565884aaab02a9f33 (diff)
downloadFreeBSD-src-bb3e0f18c0249c086c567a4d0d1e2f321587dcb2.zip
FreeBSD-src-bb3e0f18c0249c086c567a4d0d1e2f321587dcb2.tar.gz
While not explicitly allowed by RFC 2460, in case there is no
translation technology involved (and that section is suggested to be removed by Errata 2843), single packet fragments do not harm. There is another errata under discussion to clarify and allow this. Meanwhile add a sysctl to allow disabling this behaviour again. We will treat single packet fragment (a fragment header added when not needed) as if there was no fragment header. PR: kern/145733 Submitted by: Matthew Luckie (mjl luckie.org.nz) (original version) Tested by: Matthew Luckie (mjl luckie.org.nz) MFC after: 2 weeks Approved by: re (kib)
-rw-r--r--sys/netinet/ipfw/ip_fw2.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index 4e25f9a..5aabde3 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -107,6 +107,9 @@ static VNET_DEFINE(int, ipfw_vnet_ready) = 0;
static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
+static VNET_DEFINE(int, fw_permit_single_frag6) = 1;
+#define V_fw_permit_single_frag6 VNET(fw_permit_single_frag6)
+
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
static int default_to_accept = 1;
#else
@@ -182,6 +185,9 @@ SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_deny_unknown_exthdrs), 0,
"Deny packets with unknown IPv6 Extension Headers");
+SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, permit_single_frag6,
+ CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_permit_single_frag6), 0,
+ "Permit single packet IPv6 fragments");
#endif /* INET6 */
SYSEND
@@ -871,10 +877,14 @@ ipfw_chk(struct ip_fw_args *args)
* we have a fragment at this offset of an IPv4 packet.
* offset == 0 means that (if this is an IPv4 packet)
* this is the first or only fragment.
- * For IPv6 offset == 0 means there is no Fragment Header.
+ * For IPv6 offset == 0 means there is no Fragment Header or there
+ * is a single packet fragement (fragement header added without
+ * needed). We will treat a single packet fragment as if there
+ * was no fragment header (or log/block depending on the
+ * V_fw_permit_single_frag6 sysctl setting).
* If offset != 0 for IPv6 always use correct mask to
- * get the correct offset because we add IP6F_MORE_FRAG
- * to be able to dectect the first fragment which would
+ * get the correct offset because we add IP6F_MORE_FRAG to be able
+ * to dectect the first of multiple fragments which would
* otherwise have offset = 0.
*/
u_short offset = 0;
@@ -1037,10 +1047,11 @@ do { \
offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
IP6F_OFF_MASK;
/* Add IP6F_MORE_FRAG for offset of first
- * fragment to be != 0. */
+ * fragment to be != 0 if there shall be more. */
offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
IP6F_MORE_FRAG;
- if (offset == 0) {
+ if (V_fw_permit_single_frag6 == 0 &&
+ offset == 0) {
printf("IPFW2: IPV6 - Invalid Fragment "
"Header\n");
if (V_fw_deny_unknown_exthdrs)
OpenPOWER on IntegriCloud