diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index 4e25f9a086d8..5aabde3c44eb 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)