diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index fedb6c6b6c78..f3bbdcf6859e 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1142,7 +1142,8 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, /* 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 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, 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; } diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c index 11ad498505f4..1cb7a800918f 100644 --- a/sys/netpfil/ipfw/ip_dn_io.c +++ b/sys/netpfil/ipfw/ip_dn_io.c @@ -771,6 +771,7 @@ dummynet_send(struct mbuf *m) switch (dst) { case DIR_OUT: + case DIR_FWD: ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); break ; @@ -784,7 +785,10 @@ dummynet_send(struct mbuf *m) 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 @@ dummynet_io(struct mbuf **m0, struct ip_fw_args *fwa) /* 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) diff --git a/sys/netpfil/ipfw/ip_dn_private.h b/sys/netpfil/ipfw/ip_dn_private.h index cc084f2fcc0d..d8234d8d8afe 100644 --- a/sys/netpfil/ipfw/ip_dn_private.h +++ b/sys/netpfil/ipfw/ip_dn_private.h @@ -384,11 +384,11 @@ struct dn_pkt_tag { * 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 */ diff --git a/sys/netpfil/ipfw/ip_fw_pfil.c b/sys/netpfil/ipfw/ip_fw_pfil.c index 01a44df47180..e966c1c8d191 100644 --- a/sys/netpfil/ipfw/ip_fw_pfil.c +++ b/sys/netpfil/ipfw/ip_fw_pfil.c @@ -129,6 +129,8 @@ ipfw_check_packet(struct mbuf **m0, struct ifnet *ifp, int flags, 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 @@ ipfw_check_packet(struct mbuf **m0, struct ifnet *ifp, int flags, 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; } diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 1440b1a40eee..85513e6e88ab 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -94,7 +94,7 @@ struct ip_fw_args { #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) /*