diff options
Diffstat (limited to 'sys/netpfil/ipfw/ip_fw_table.c')
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_table.c | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index ed500b1..ac269cd 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -185,6 +185,66 @@ get_table_value(struct ip_fw_chain *ch, struct table_config *tc, uint32_t kidx) return (&pval[kidx]); } +static int +zero_cnt_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3, + struct sockopt_data *sd) +{ + ipfw_obj_tentry *tent; + ipfw_obj_header *oh; + struct tid_info ti; + struct table_config *tc; + struct table_algo *ta; + struct table_info *kti; + struct namedobj_instance *ni; + int error; + size_t sz; + + /* Check minimum header size */ + sz = sizeof(*oh) + sizeof(*tent); + if (sd->valsize != sz) + return (EINVAL); + + oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz); + tent = (ipfw_obj_tentry *)(oh + 1); + + /* Basic length checks for TLVs */ + if (oh->ntlv.head.length != sizeof(oh->ntlv)) + return (EINVAL); + + objheader_to_ti(oh, &ti); + ti.type = oh->ntlv.type; + ti.uidx = tent->idx; + + IPFW_UH_RLOCK(ch); + ni = CHAIN_TO_NI(ch); + + /* + * Find existing table and check its type . + */ + ta = NULL; + if ((tc = find_table(ni, &ti)) == NULL) { + IPFW_UH_RUNLOCK(ch); + return (ESRCH); + } + + /* check table type */ + if (tc->no.subtype != ti.type) { + IPFW_UH_RUNLOCK(ch); + return (EINVAL); + } + + kti = KIDX_TO_TI(ch, tc->no.kidx); + ta = tc->ta; + + if (ta->zero_cnt_tentry == NULL) + return (ENOTSUP); + + error = ta->zero_cnt_tentry(tc->astate, kti, tent); + IPFW_UH_RUNLOCK(ch); + + return (error); +} + /* * Checks if we're able to insert/update entry @tei into table @@ -1665,13 +1725,37 @@ ipfw_unref_table(struct ip_fw_chain *ch, uint16_t kidx) */ int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, - void *paddr, uint32_t *val) + void *paddr, uint32_t *val, void **te) { struct table_info *ti; ti = KIDX_TO_TI(ch, tbl); - return (ti->lookup(ti, paddr, plen, val)); + return (ti->lookup(ti, paddr, plen, val, te)); +} + +/* + * Update the table entry counter. + */ +void +ipfw_cnt_tentry_update(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, + void *e, int pktlen) +{ + struct namedobj_instance *ni; + struct table_algo *ta; + struct table_config *tc; + struct table_info *ti; + + ni = CHAIN_TO_NI(ch); + tc = (struct table_config *)ipfw_objhash_lookup_kidx(ni, tbl); + if (tc == NULL) + return; + ta = tc->ta; + if (ta->cnt_tentry == NULL) + return; + + ti = KIDX_TO_TI(ch, tbl); + ta->cnt_tentry(tc->astate, ti, plen, e, pktlen); } /* @@ -2013,6 +2097,7 @@ struct dump_args { ta_foreach_f *f; void *farg; ipfw_obj_tentry tent; + time_t boottime; }; static int @@ -2171,6 +2256,7 @@ dump_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct tid_info ti; struct table_config *tc; struct table_algo *ta; + struct timeval boottime; struct dump_args da; uint32_t sz; @@ -2209,6 +2295,8 @@ dump_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3, da.ti = KIDX_TO_TI(ch, tc->no.kidx); da.tc = tc; da.sd = sd; + getboottime(&boottime); + da.boottime = boottime.tv_sec; ta = tc->ta; @@ -2449,6 +2537,9 @@ dump_table_tentry(void *e, void *arg) pval = get_table_value(da->ch, da->tc, tent->v.kidx); ipfw_export_table_value_v1(pval, &tent->v.value); + if (tent->timestamp != 0) + tent->timestamp += da->boottime; + return (0); } @@ -3312,6 +3403,7 @@ static struct ipfw_sopt_handler scodes[] = { { IP_FW_TABLE_XSWAP, 0, HDIR_SET, swap_table }, { IP_FW_TABLES_ALIST, 0, HDIR_GET, list_table_algo }, { IP_FW_TABLE_XGETSIZE, 0, HDIR_GET, get_table_size }, + { IP_FW_TABLE_XZEROCNT, 0, HDIR_SET, zero_cnt_entry }, }; static int |