Page MenuHomeFreeBSD

D23586.id68243.diff
No OneTemporary

D23586.id68243.diff

Index: sbin/ipfw/ipfw2.c
===================================================================
--- sbin/ipfw/ipfw2.c
+++ sbin/ipfw/ipfw2.c
@@ -3934,8 +3934,6 @@
case TOK_NAT:
action->opcode = O_NAT;
- action->len = F_INSN_SIZE(ipfw_insn_nat);
- CHECK_ACTLEN;
if (*av != NULL && _substrcmp(*av, "global") == 0) {
action->arg1 = IP_FW_NAT44_GLOBAL;
av++;
Index: sys/netinet/ip_fw.h
===================================================================
--- sys/netinet/ip_fw.h
+++ sys/netinet/ip_fw.h
@@ -552,12 +552,6 @@
uint32_t redir_cnt; /* number of entry in spool chain */
};
-/* Nat command. */
-typedef struct _ipfw_insn_nat {
- ipfw_insn o;
- struct cfg_nat *nat;
-} ipfw_insn_nat;
-
/* Apply ipv6 mask on ipv6 addr */
#define APPLY_MASK(addr,mask) do { \
(addr)->__u6_addr.__u6_addr32[0] &= (mask)->__u6_addr.__u6_addr32[0]; \
Index: sys/netpfil/ipfw/ip_fw2.c
===================================================================
--- sys/netpfil/ipfw/ip_fw2.c
+++ sys/netpfil/ipfw/ip_fw2.c
@@ -3095,7 +3095,7 @@
* Ensure that we do not invoke NAT handler for
* non IPv4 packets. Libalias expects only IPv4.
*/
- if (!is_ipv4 || !IPFW_NAT_LOADED) {
+ if (!is_ipv4 || chain->nat == NULL) {
retval = IP_FW_DENY;
break;
}
@@ -3110,17 +3110,12 @@
retval = ipfw_nat_ptr(args, NULL, m);
break;
}
- t = ((ipfw_insn_nat *)cmd)->nat;
- if (t == NULL) {
- nat_id = TARG(cmd->arg1, nat);
- t = (*lookup_nat_ptr)(&chain->nat, nat_id);
+ nat_id = TARG(cmd->arg1, nat);
+ t = (*lookup_nat_ptr)(chain->nat, nat_id);
- if (t == NULL) {
- retval = IP_FW_DENY;
- break;
- }
- if (cmd->arg1 != IP_FW_TARG)
- ((ipfw_insn_nat *)cmd)->nat = t;
+ if (t == NULL) {
+ retval = IP_FW_DENY;
+ break;
}
retval = ipfw_nat_ptr(args, t, m);
break;
@@ -3369,9 +3364,6 @@
#endif
#ifdef IPFIREWALL_VERBOSE_LIMIT
V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
-#endif
-#ifdef IPFIREWALL_NAT
- LIST_INIT(&chain->nat);
#endif
/* Init shared services hash table */
Index: sys/netpfil/ipfw/ip_fw_nat.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_nat.c
+++ sys/netpfil/ipfw/ip_fw_nat.c
@@ -95,6 +95,14 @@
char if_name[IF_NAMESIZE]; /* interface name */
};
+/* Nat managment. */
+struct nat_list {
+ LIST_HEAD(cfg_all, cfg_nat) all; /* table of lists of nat entries */
+ struct cfg_nat **byid; /* map id to instance */
+ int size; /* size of of nat lookup table */
+ uint32_t gencnt; /* NAT configuration change count */
+};
+
static eventhandler_tag ifaddr_event_tag;
static void
@@ -113,7 +121,7 @@
chain = &V_layer3_chain;
IPFW_UH_WLOCK(chain);
/* Check every nat entry... */
- LIST_FOREACH(ptr, &chain->nat, _next) {
+ LIST_FOREACH(ptr, &chain->nat->all, _next) {
struct epoch_tracker et;
/* ...using nic 'ifp->if_xname' as dynamic alias address. */
@@ -136,25 +144,7 @@
IPFW_UH_WUNLOCK(chain);
}
-/*
- * delete the pointers for nat entry ix, or all of them if ix < 0
- */
static void
-flush_nat_ptrs(struct ip_fw_chain *chain, const int ix)
-{
- ipfw_insn_nat *cmd;
- int i;
-
- IPFW_WLOCK_ASSERT(chain);
- for (i = 0; i < chain->n_rules; i++) {
- cmd = (ipfw_insn_nat *)ipfw_get_action(chain->map[i]);
- if (cmd->o.opcode == O_NAT && cmd->nat != NULL &&
- (ix < 0 || cmd->nat->id == ix))
- cmd->nat = NULL;
- }
-}
-
-static void
del_redir_spool_cfg(struct cfg_nat *n, struct redir_chain *head)
{
struct cfg_redir *r, *tmp_r;
@@ -358,7 +348,7 @@
chain = &V_layer3_chain;
IPFW_RLOCK_ASSERT(chain);
/* Check every nat entry... */
- LIST_FOREACH(t, &chain->nat, _next) {
+ LIST_FOREACH(t, &chain->nat->all, _next) {
if ((t->mode & PKT_ALIAS_SKIP_GLOBAL) != 0)
continue;
retval = LibAliasOutTry(t->lib, c,
@@ -461,19 +451,15 @@
static struct cfg_nat *
lookup_nat(struct nat_list *l, int nat_id)
{
- struct cfg_nat *res;
+ if (nat_id >= l->size)
+ return NULL;
- LIST_FOREACH(res, l, _next) {
- if (res->id == nat_id)
- break;
- }
- return res;
+ return l->byid[nat_id];
}
static struct cfg_nat *
lookup_nat_name(struct nat_list *l, char *name)
{
- struct cfg_nat *res;
int id;
char *errptr;
@@ -481,11 +467,7 @@
if (id == 0 || *errptr != '\0')
return (NULL);
- LIST_FOREACH(res, l, _next) {
- if (res->id == id)
- break;
- }
- return (res);
+ return lookup_nat(l, id);
}
/* IP_FW3 configuration routines */
@@ -500,8 +482,8 @@
* Find/create nat rule.
*/
IPFW_UH_WLOCK(chain);
- gencnt = chain->gencnt;
- ptr = lookup_nat_name(&chain->nat, ucfg->name);
+ gencnt = chain->nat->gencnt;
+ ptr = lookup_nat_name(chain->nat, ucfg->name);
if (ptr == NULL) {
IPFW_UH_WUNLOCK(chain);
/* New rule: allocate and init new instance. */
@@ -512,7 +494,7 @@
/* Entry already present: temporarily unhook it. */
IPFW_WLOCK(chain);
LIST_REMOVE(ptr, _next);
- flush_nat_ptrs(chain, ptr->id);
+ chain->nat->byid[ptr->id] = NULL;
IPFW_WUNLOCK(chain);
IPFW_UH_WUNLOCK(chain);
}
@@ -544,14 +526,23 @@
/* Extra check to avoid race with another ipfw_nat_cfg() */
tcfg = NULL;
- if (gencnt != chain->gencnt)
- tcfg = lookup_nat_name(&chain->nat, ucfg->name);
+ if (gencnt != chain->nat->gencnt)
+ tcfg = lookup_nat_name(chain->nat, ucfg->name);
IPFW_WLOCK(chain);
if (tcfg != NULL)
LIST_REMOVE(tcfg, _next);
- LIST_INSERT_HEAD(&chain->nat, ptr, _next);
+ LIST_INSERT_HEAD(&chain->nat->all, ptr, _next);
+ if (ptr->id >= chain->nat->size) {
+ chain->nat->size = ptr->id + 1;
+ chain->nat->byid = realloc(chain->nat->byid,
+ chain->nat->size * sizeof(chain->nat->byid[0]),
+ M_IPFW, M_WAITOK);
+ KASSERT(chain->nat->byid != NULL,
+ ("Out of memory allocating NAT entry %d\n", ptr->id));
+ }
+ chain->nat->byid[ptr->id] = ptr;
IPFW_WUNLOCK(chain);
- chain->gencnt++;
+ chain->nat->gencnt++;
IPFW_UH_WUNLOCK(chain);
@@ -635,14 +626,14 @@
return (EINVAL);
IPFW_UH_WLOCK(chain);
- ptr = lookup_nat_name(&chain->nat, ntlv->name);
+ ptr = lookup_nat_name(chain->nat, ntlv->name);
if (ptr == NULL) {
IPFW_UH_WUNLOCK(chain);
return (ESRCH);
}
IPFW_WLOCK(chain);
LIST_REMOVE(ptr, _next);
- flush_nat_ptrs(chain, ptr->id);
+ chain->nat->byid[ptr->id] = NULL;
IPFW_WUNLOCK(chain);
IPFW_UH_WUNLOCK(chain);
@@ -700,7 +691,7 @@
return (EINVAL);
IPFW_UH_RLOCK(chain);
- ptr = lookup_nat_name(&chain->nat, ucfg->name);
+ ptr = lookup_nat_name(chain->nat, ucfg->name);
if (ptr == NULL) {
IPFW_UH_RUNLOCK(chain);
return (ESRCH);
@@ -783,7 +774,7 @@
olh = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*olh));
IPFW_UH_RLOCK(chain);
nat_count = 0;
- LIST_FOREACH(ptr, &chain->nat, _next)
+ LIST_FOREACH(ptr, &chain->nat->all, _next)
nat_count++;
olh->count = nat_count;
@@ -795,7 +786,7 @@
return (ENOMEM);
}
- LIST_FOREACH(ptr, &chain->nat, _next) {
+ LIST_FOREACH(ptr, &chain->nat->all, _next) {
ucfg = (struct nat44_cfg_nat *)ipfw_get_sopt_space(sd,
sizeof(*ucfg));
export_nat_cfg(ptr, ucfg);
@@ -842,7 +833,7 @@
return (EINVAL);
IPFW_UH_RLOCK(chain);
- ptr = lookup_nat_name(&chain->nat, ucfg->name);
+ ptr = lookup_nat_name(chain->nat, ucfg->name);
if (ptr == NULL) {
IPFW_UH_RUNLOCK(chain);
return (ESRCH);
@@ -1002,14 +993,14 @@
sooptcopyin(sopt, &i, sizeof i, sizeof i);
/* XXX validate i */
IPFW_UH_WLOCK(chain);
- ptr = lookup_nat(&chain->nat, i);
+ ptr = lookup_nat(chain->nat, i);
if (ptr == NULL) {
IPFW_UH_WUNLOCK(chain);
return (EINVAL);
}
IPFW_WLOCK(chain);
LIST_REMOVE(ptr, _next);
- flush_nat_ptrs(chain, i);
+ chain->nat->byid[i] = NULL;
IPFW_WUNLOCK(chain);
IPFW_UH_WUNLOCK(chain);
free_nat_instance(ptr);
@@ -1034,9 +1025,9 @@
IPFW_UH_RLOCK(chain);
retry:
- gencnt = chain->gencnt;
+ gencnt = chain->nat->gencnt;
/* Estimate memory amount */
- LIST_FOREACH(n, &chain->nat, _next) {
+ LIST_FOREACH(n, &chain->nat->all, _next) {
nat_cnt++;
len += sizeof(struct cfg_nat_legacy);
LIST_FOREACH(r, &n->redir_chain, _next) {
@@ -1054,12 +1045,12 @@
len = sizeof(nat_cnt);
IPFW_UH_RLOCK(chain);
- if (gencnt != chain->gencnt) {
+ if (gencnt != chain->nat->gencnt) {
free(data, M_TEMP);
goto retry;
}
/* Serialize all the data. */
- LIST_FOREACH(n, &chain->nat, _next) {
+ LIST_FOREACH(n, &chain->nat->all, _next) {
ucfg = (struct cfg_nat_legacy *)&data[len];
ucfg->id = n->id;
ucfg->ip = n->ip;
@@ -1111,7 +1102,7 @@
IPFW_RLOCK(chain);
/* one pass to count, one to copy the data */
i = 0;
- LIST_FOREACH(ptr, &chain->nat, _next) {
+ LIST_FOREACH(ptr, &chain->nat->all, _next) {
if (ptr->lib->logDesc == NULL)
continue;
i++;
@@ -1123,7 +1114,7 @@
return (ENOSPC);
}
i = 0;
- LIST_FOREACH(ptr, &chain->nat, _next) {
+ LIST_FOREACH(ptr, &chain->nat->all, _next) {
if (ptr->lib->logDesc == NULL)
continue;
bcopy(&ptr->id, &data[i], sizeof(int));
@@ -1142,6 +1133,16 @@
{
V_ipfw_nat_ready = 1;
+ struct ip_fw_chain *chain;
+
+ chain = &V_layer3_chain;
+ IPFW_WLOCK(chain);
+ chain->nat = malloc(sizeof(*(chain->nat)), M_IPFW, M_WAITOK | M_ZERO);
+ chain->nat->byid = malloc(sizeof(*(chain->nat->byid)),
+ M_IPFW, M_WAITOK | M_ZERO);
+ chain->nat->size = 1;
+ LIST_INIT(&chain->nat->all);
+ IPFW_WUNLOCK(chain);
return (0);
}
@@ -1154,11 +1155,13 @@
chain = &V_layer3_chain;
IPFW_WLOCK(chain);
V_ipfw_nat_ready = 0;
- LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) {
+ LIST_FOREACH_SAFE(ptr, &chain->nat->all, _next, ptr_temp) {
LIST_REMOVE(ptr, _next);
free_nat_instance(ptr);
}
- flush_nat_ptrs(chain, -1 /* flush all */);
+ free(chain->nat->byid, M_IPFW);
+ free(chain->nat, M_IPFW);
+ chain->nat = NULL;
IPFW_WUNLOCK(chain);
return (0);
}
Index: sys/netpfil/ipfw/ip_fw_private.h
===================================================================
--- sys/netpfil/ipfw/ip_fw_private.h
+++ sys/netpfil/ipfw/ip_fw_private.h
@@ -302,8 +302,7 @@
struct rmlock rwmtx;
#endif
int static_len; /* total len of static rules (v0) */
- uint32_t gencnt; /* NAT generation count */
- LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */
+ struct nat_list *nat; /* nat instances */
struct ip_fw *default_rule;
struct tables_config *tblcfg; /* tables module data */
void *ifcfg; /* interface module data */
Index: sys/netpfil/ipfw/ip_fw_sockopt.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_sockopt.c
+++ sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -2002,9 +2002,8 @@
case O_NAT:
if (!IPFW_NAT_LOADED)
return EINVAL;
- if (cmdlen != F_INSN_SIZE(ipfw_insn_nat))
- goto bad_size;
- goto check_action;
+ else
+ goto check_size;
case O_CHECK_STATE:
ci->object_opcodes++;
/* FALLTHROUGH */

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 22, 12:32 AM (2 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27824913
Default Alt Text
D23586.id68243.diff (10 KB)

Event Timeline