--- sys/netpfil/ipfw/ip_fw_nat.c.orig 2014-09-20 01:28:38.000000000 +0700 +++ sys/netpfil/ipfw/ip_fw_nat.c 2014-12-10 02:51:31.000000000 +0700 @@ -31,10 +31,12 @@ __FBSDID("$FreeBSD: stable/9/sys/netpfil #include #include #include +#include #include #include #include #include +#include #define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */ @@ -42,6 +44,7 @@ __FBSDID("$FreeBSD: stable/9/sys/netpfil #include #include +#include #include #include #include @@ -53,6 +56,26 @@ __FBSDID("$FreeBSD: stable/9/sys/netpfil #include /* XXX for in_cksum */ +static VNET_DEFINE(u_int32_t, nat_tag_in); +static VNET_DEFINE(u_int32_t, nat_tag_out); +#define V_nat_tag_in VNET(nat_tag_in) +#define V_nat_tag_out VNET(nat_tag_out) + +#ifdef SYSCTL_NODE + +SYSBEGIN(f3) + +SYSCTL_DECL(_net_inet_ip_fw); + +SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, nat_tag_in, + CTLFLAG_RW, &VNET_NAME(nat_tag_in), 0, "Tag for incoming packets"); +SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, nat_tag_out, + CTLFLAG_RW, &VNET_NAME(nat_tag_out), 0, "Tag for outgoing packets"); + +SYSEND + +#endif /* SYSCTL_NODE */ + static eventhandler_tag ifaddr_event_tag; static void @@ -216,10 +239,12 @@ ipfw_nat(struct ip_fw_args *args, struct struct mbuf *mcl; struct ip *ip; /* XXX - libalias duct tape */ - int ldt, retval, found; + int ldt, retval, found, outgoing; struct ip_fw_chain *chain; + struct m_tag *mtag; char *c; + mtag = NULL; ldt = 0; retval = 0; mcl = m_megapullup(m, m->m_pkthdr.len); @@ -267,9 +292,21 @@ ipfw_nat(struct ip_fw_args *args, struct c = mtod(mcl, char *); +#define INCOMING(a) ((outgoing == 0) || (outgoing < 0 && ((a)->oif == NULL))) + + outgoing = -1; /* autodetect via oif */ + if (V_nat_tag_out && + (mtag = m_tag_locate(mcl, MTAG_IPFW, V_nat_tag_out, NULL))) + outgoing = 1; /* outgoing */ + else if (V_nat_tag_in && + (m_tag_locate(mcl, MTAG_IPFW, V_nat_tag_in, NULL))) + outgoing = 0; /* incoming */ + if (mtag != NULL) + m_tag_delete(mcl, mtag); + /* Check if this is 'global' instance */ if (t == NULL) { - if (args->oif == NULL) { + if (INCOMING(args)) { /* Wrong direction, skip processing */ args->m = mcl; return (IP_FW_NAT); @@ -296,7 +333,7 @@ ipfw_nat(struct ip_fw_args *args, struct return (IP_FW_NAT); } } else { - if (args->oif == NULL) + if (INCOMING(args)) retval = LibAliasIn(t->lib, c, mcl->m_len + M_TRAILINGSPACE(mcl)); else @@ -313,7 +350,7 @@ ipfw_nat(struct ip_fw_args *args, struct * PKT_ALIAS_DENY_INCOMING flag is set. */ if (retval == PKT_ALIAS_ERROR || - (args->oif == NULL && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT || + (INCOMING(args) && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT || (retval == PKT_ALIAS_IGNORED && (t->mode & PKT_ALIAS_DENY_INCOMING) != 0)))) { /* XXX - should i add some logging? */ @@ -378,6 +415,7 @@ ipfw_nat(struct ip_fw_args *args, struct args->m = mcl; return (IP_FW_NAT); } +#undef INCOMING static struct cfg_nat * lookup_nat(struct nat_list *l, int nat_id)