Index: sys/netinet6/ip6_output.c =================================================================== --- sys/netinet6/ip6_output.c +++ sys/netinet6/ip6_output.c @@ -1142,7 +1142,8 @@ /* XXX-BZ m->m_pkthdr.csum_flags &= ~ifp->if_hwassist; */ tlen = m->m_pkthdr.len; - if ((opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso) + if ((flags & IPV6_FORWARDING) || + (opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso) dontfrag = 1; else dontfrag = 0; @@ -1291,8 +1292,14 @@ m_freem(exthdrs.ip6e_dest2); /* FALLTHROUGH */ bad: - if (m) - m_freem(m); + if (m != NULL) { + if ((flags & IPV6_FORWARDING) != 0 && + error == EMSGSIZE && V_ip6_forwarding != 0) { + in6_ifstat_inc(ifp, ifs6_out_fragfail); + icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, mtu); + } else + m_freem(m); + } goto done; } Index: sys/netpfil/ipfw/ip_dn_io.c =================================================================== --- sys/netpfil/ipfw/ip_dn_io.c +++ sys/netpfil/ipfw/ip_dn_io.c @@ -771,6 +771,7 @@ switch (dst) { case DIR_OUT: + case DIR_FWD: ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); break ; @@ -784,7 +785,10 @@ break; case DIR_OUT | PROTO_IPV6: - ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL); + case DIR_FWD | PROTO_IPV6: + ip6_output(m, NULL, NULL, + (dst & DIR_FWD) ? IPV6_FORWARDING: 0, + NULL, NULL, NULL); break; #endif @@ -871,6 +875,8 @@ /* XXXGL: convert args to dir */ if (fwa->flags & IPFW_ARGS_IN) dir = DIR_IN; + else if (fwa->flags & IPFW_ARGS_FWD) + dir = DIR_FWD; else dir = DIR_OUT; if (fwa->flags & IPFW_ARGS_ETHER) Index: sys/netpfil/ipfw/ip_dn_private.h =================================================================== --- sys/netpfil/ipfw/ip_dn_private.h +++ sys/netpfil/ipfw/ip_dn_private.h @@ -384,11 +384,11 @@ * and converted to same values ip_fw_args.flags use. */ enum { - DIR_OUT = 0, - DIR_IN = 1, - DIR_FWD = 2, - DIR_DROP = 3, - PROTO_LAYER2 = 0x4, /* set for layer 2 */ + DIR_OUT = 0x00, + DIR_IN = 0x01, + DIR_FWD = 0x02, + DIR_DROP = 0x03, + PROTO_LAYER2 = 0x04, /* set for layer 2 */ PROTO_IPV4 = 0x08, PROTO_IPV6 = 0x10, PROTO_IFB = 0x0c, /* layer2 + ifbridge */ Index: sys/netpfil/ipfw/ip_fw_pfil.c =================================================================== --- sys/netpfil/ipfw/ip_fw_pfil.c +++ sys/netpfil/ipfw/ip_fw_pfil.c @@ -129,6 +129,8 @@ int ipfw; args.flags = (flags & PFIL_IN) ? IPFW_ARGS_IN : IPFW_ARGS_OUT; + if (flags & PFIL_FWD) + args.flags |= IPFW_ARGS_FWD; again: /* * extract and remove the tag if present. If we are left @@ -139,7 +141,7 @@ args.rule = *((struct ipfw_rule_ref *)(tag+1)); m_tag_delete(*m0, tag); if (args.rule.info & IPFW_ONEPASS) - return (0); + return (PFIL_PASS); args.flags |= IPFW_ARGS_REF; } Index: sys/netpfil/ipfw/ip_fw_private.h =================================================================== --- sys/netpfil/ipfw/ip_fw_private.h +++ sys/netpfil/ipfw/ip_fw_private.h @@ -94,7 +94,7 @@ #define IPFW_ARGS_OUT 0x00800000 /* called on output */ #define IPFW_ARGS_IP4 0x01000000 /* belongs to v4 ISR */ #define IPFW_ARGS_IP6 0x02000000 /* belongs to v6 ISR */ -#define IPFW_ARGS_DROP 0x04000000 /* drop it (dummynet) */ +#define IPFW_ARGS_FWD 0x04000000 /* called on forwarding */ #define IPFW_ARGS_LENMASK 0x0000ffff /* length of data in *mem */ #define IPFW_ARGS_LENGTH(f) ((f) & IPFW_ARGS_LENMASK) /*