diff options
author | Luiz Souza <luiz@netgate.com> | 2017-08-06 02:02:36 -0500 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2017-08-06 02:07:27 -0500 |
commit | ee3875603445b55d9191175188bffbfb8a127092 (patch) | |
tree | 8448a11f6fb20cd23560ecb7e3756ea48440f272 /sys | |
parent | 0a8287cf6a20663f124fada94131d7136970bbb1 (diff) | |
download | FreeBSD-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.c | 63 |
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) |