summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorLuiz Souza <luiz@netgate.com>2017-08-06 02:02:36 -0500
committerLuiz Souza <luiz@netgate.com>2017-08-06 02:07:27 -0500
commitee3875603445b55d9191175188bffbfb8a127092 (patch)
tree8448a11f6fb20cd23560ecb7e3756ea48440f272 /sys
parent0a8287cf6a20663f124fada94131d7136970bbb1 (diff)
downloadFreeBSD-src-ee3875603445b55d9191175188bffbfb8a127092.zip
FreeBSD-src-ee3875603445b55d9191175188bffbfb8a127092.tar.gz
Fix the match of the "any any" entry in MAC address tables.
(cherry picked from commit 7e2bac9957c7c8da5275b6eb186cabbb36f4584f)
Diffstat (limited to 'sys')
-rw-r--r--sys/netpfil/ipfw/ip_fw_table_algo.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c
index f327afe..dfa80c6 100644
--- a/sys/netpfil/ipfw/ip_fw_table_algo.c
+++ b/sys/netpfil/ipfw/ip_fw_table_algo.c
@@ -4524,13 +4524,10 @@ static __inline int
ta_lookup_find_mhash(struct mhashbhead *head, uint32_t hash2,
struct macdata *mac, uint32_t *val, uint8_t *ea, void **te)
{
- struct macdata any;
struct mhashentry *ent;
- memset(any.addr, 0, sizeof(any.addr));
SLIST_FOREACH(ent, &head[hash2], next) {
- if (memcmp(&ent->mac->addr, any.addr, sizeof(any.addr)) != 0 &&
- memcmp(&ent->mac->addr, mac->addr, sizeof(mac->addr)) != 0)
+ if (memcmp(&ent->mac->addr, mac->addr, sizeof(mac->addr)) != 0)
continue;
*val = ent->mac->value;
if (te != NULL)
@@ -4549,6 +4546,12 @@ ta_lookup_mhash(struct table_info *ti, void *key, uint32_t keylen,
struct mhashbhead *head;
uint32_t hash2, hsize;
+ /* any any always match. */
+ if (ti->xstate != NULL) {
+ *te = ti->xstate;
+ return (1);
+ }
+
/*
* Look three times for a MAC is still faster than looking at whole
* table (128 entries by default).
@@ -4592,6 +4595,7 @@ ta_init_mhash(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
for (i = 0; i < cfg->size; i++)
SLIST_INIT(&cfg->head[i]);
*ta_state = cfg;
+ ti->xstate = NULL;
ti->state = cfg->head;
ti->data = ta_log2(cfg->size);
ti->lookup = ta_lookup_mhash;
@@ -4629,6 +4633,8 @@ ta_foreach_mhash(void *ta_state, struct table_info *ti, ta_foreach_f *f,
cfg = (struct mhash_cfg *)ta_state;
+ if (ti->xstate != NULL)
+ f(ti->xstate, arg);
for (i = 0; i < cfg->size; i++)
SLIST_FOREACH_SAFE(ent, &cfg->head[i], next, ent_next)
f(ent, arg);
@@ -4664,6 +4670,7 @@ ta_find_mhash_tentry(void *ta_state, struct table_info *ti,
struct mhashentry *ent;
struct tentry_info tei;
uint32_t hash2;
+ u_char any[12];
cfg = (struct mhash_cfg *)ta_state;
@@ -4675,6 +4682,14 @@ ta_find_mhash_tentry(void *ta_state, struct table_info *ti,
memcpy(mac.addr, tei.paddr, sizeof(mac.addr) + sizeof(mac.mask));
+ /* any any */
+ memset(any, 0, sizeof(any));
+ if (memcmp(mac.addr, any, sizeof(mac.addr)) == 0 &&
+ ti->xstate != NULL) {
+ ta_dump_mhash_tentry(ta_state, ti, ti->xstate, tent);
+ return (0);
+ }
+
/* Check for existence */
hash2 = hash_mac2(mac.addr, cfg->size);
SLIST_FOREACH(ent, &cfg->head[hash2], next) {
@@ -4733,6 +4748,7 @@ ta_add_mhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
struct mhashentry *ent, *tmp;
struct ta_buf_mhash *tb;
uint32_t hash2, value;
+ u_char any[12];
cfg = (struct mhash_cfg *)ta_state;
tb = (struct ta_buf_mhash *)ta_buf;
@@ -4746,6 +4762,32 @@ ta_add_mhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
if (tei->subtype != AF_LINK)
return (EINVAL);
+ /* any any */
+ memset(any, 0, sizeof(any));
+ if (memcmp(mac->addr, any, sizeof(mac->addr)) == 0) {
+ if (ti->xstate != NULL) {
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
+ return (EEXIST);
+ /* Record already exists. Update value if we're asked to */
+ value = ((struct mhashentry *)ti->xstate)->mac->value;
+ ((struct mhashentry *)ti->xstate)->mac->value = tei->value;
+ tei->value = value;
+ /* Indicate that update has happened instead of addition */
+ tei->flags |= TEI_FLAGS_UPDATED;
+ *pnum = 0;
+ } else {
+ if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
+ return (EFBIG);
+ ti->xstate = ent;
+ tb->ent_ptr = NULL;
+ *pnum = 1;
+
+ /* Update counters */
+ cfg->items++;
+ }
+ return (0);
+ }
+
/* Check for existence */
hash2 = hash_mac2(mac->addr, cfg->size);
SLIST_FOREACH(tmp, &cfg->head[hash2], next) {
@@ -4802,6 +4844,7 @@ ta_del_mhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
struct mhashentry *tmp, *tmp_next;
struct ta_buf_mhash *tb;
uint32_t hash2;
+ u_char any[12];
cfg = (struct mhash_cfg *)ta_state;
tb = (struct ta_buf_mhash *)ta_buf;
@@ -4810,6 +4853,18 @@ ta_del_mhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
if (tei->masklen != ETHER_ADDR_LEN * 8)
return (EINVAL);
+ /* any any */
+ memset(any, 0, sizeof(any));
+ if (memcmp(mac->addr, any, sizeof(mac->addr)) == 0 &&
+ ti->xstate != NULL) {
+ cfg->items--;
+ tb->ent_ptr = ti->xstate;
+ tei->value = ((struct mhashentry *)ti->xstate)->mac->value;
+ ti->xstate = NULL;
+ *pnum = 1;
+ return (0);
+ }
+
hash2 = hash_mac2(mac->addr, cfg->size);
SLIST_FOREACH_SAFE(tmp, &cfg->head[hash2], next, tmp_next) {
if (memcmp(&tmp->mac->addr, &mac->addr, sizeof(mac->addr)) != 0)
OpenPOWER on IntegriCloud