--- sys/netinet/ipfw/ip_fw_nat.c.orig 2013-06-17 11:20:41.000000000 +0700 +++ sys/netinet/ipfw/ip_fw_nat.c 2014-12-10 03:18:37.000000000 +0700 @@ -31,10 +31,12 @@ __FBSDID("$FreeBSD: stable/8/sys/netinet #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/8/sys/netinet #include #include +#include #include #include #include @@ -52,6 +55,26 @@ __FBSDID("$FreeBSD: stable/8/sys/netinet #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 VNET_DEFINE(eventhandler_tag, ifaddr_event_tag); #define V_ifaddr_event_tag VNET(ifaddr_event_tag) @@ -207,10 +230,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); @@ -258,9 +283,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); @@ -288,7 +325,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 @@ -305,7 +342,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? */ @@ -370,6 +407,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)