From b309f085e0354c885edb3c70e767c18a14905cca Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Fri, 6 May 2016 03:18:51 +0000 Subject: [PATCH] Change the type of objhash_cb_t callback function to be able return an error code. Use it to interrupt the loop in ipfw_objhash_foreach(). Obtained from: Yandex LLC Sponsored by: Yandex LLC --- sys/netpfil/ipfw/ip_fw_iface.c | 6 ++++-- sys/netpfil/ipfw/ip_fw_private.h | 4 ++-- sys/netpfil/ipfw/ip_fw_sockopt.c | 17 +++++++++++------ sys/netpfil/ipfw/ip_fw_table.c | 16 ++++++++++------ sys/netpfil/ipfw/ip_fw_table_algo.c | 10 ++++++---- sys/netpfil/ipfw/ip_fw_table_value.c | 12 +++++++----- 6 files changed, 40 insertions(+), 25 deletions(-) diff --git a/sys/netpfil/ipfw/ip_fw_iface.c b/sys/netpfil/ipfw/ip_fw_iface.c index 07d24de28a3b..b2aa7d3205db 100644 --- a/sys/netpfil/ipfw/ip_fw_iface.c +++ b/sys/netpfil/ipfw/ip_fw_iface.c @@ -249,13 +249,14 @@ vnet_ipfw_iface_init(struct ip_fw_chain *ch) } } -static void +static int destroy_iface(struct namedobj_instance *ii, struct named_object *no, void *arg) { /* Assume all consumers have been already detached */ free(no, M_IPFW); + return (0); } /* @@ -460,7 +461,7 @@ struct dump_iface_args { struct sockopt_data *sd; }; -static void +static int export_iface_internal(struct namedobj_instance *ii, struct named_object *no, void *arg) { @@ -481,6 +482,7 @@ export_iface_internal(struct namedobj_instance *ii, struct named_object *no, i->ifindex = iif->ifindex; i->refcnt = iif->no.refcnt; i->gencnt = iif->gencnt; + return (0); } /* diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 0a722bd2fcbc..52e8a768c40a 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -649,7 +649,7 @@ caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed); } while(0) struct namedobj_instance; -typedef void (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, +typedef int (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, void *arg); typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, const void *key, uint32_t kopt); @@ -675,7 +675,7 @@ int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no); void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no); uint32_t ipfw_objhash_count(struct namedobj_instance *ni); -void ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, +int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg); int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 72d40ca25904..2f41d23fd3a2 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -3009,7 +3009,7 @@ ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) return (0); } -static void +static int export_objhash_ntlv_internal(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3019,8 +3019,9 @@ export_objhash_ntlv_internal(struct namedobj_instance *ni, sd = (struct sockopt_data *)arg; ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); if (ntlv == NULL) - return; + return (ENOMEM); ipfw_export_obj_ntlv(no, ntlv); + return (0); } /* @@ -4249,16 +4250,20 @@ ipfw_objhash_count(struct namedobj_instance *ni) * Runs @func for each found named object. * It is safe to delete objects from callback */ -void +int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg) { struct named_object *no, *no_tmp; - int i; + int i, ret; for (i = 0; i < ni->nn_size; i++) { - TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) - f(ni, no, arg); + TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) { + ret = f(ni, no, arg); + if (ret != 0) + return (ret); + } } + return (0); } /* diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 060fd94f5bda..194be0896e90 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -2119,7 +2119,7 @@ struct dump_table_args { struct sockopt_data *sd; }; -static void +static int export_table_internal(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -2132,6 +2132,7 @@ export_table_internal(struct namedobj_instance *ni, struct named_object *no, KASSERT(i != NULL, ("previously checked buffer is not enough")); export_table_info(dta->ch, (struct table_config *)no, i); + return (0); } /* @@ -3123,7 +3124,7 @@ struct swap_table_args { * Ensure we dispatch each table once by setting/checking ochange * fields. */ -static void +static int swap_table_set(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3134,10 +3135,10 @@ swap_table_set(struct namedobj_instance *ni, struct named_object *no, sta = (struct swap_table_args *)arg; if (no->set != sta->set && (no->set != sta->new_set || sta->mv != 0)) - return; + return (0); if (tc->ochanged != 0) - return; + return (0); tc->ochanged = 1; ipfw_objhash_del(ni, no); @@ -3146,12 +3147,13 @@ swap_table_set(struct namedobj_instance *ni, struct named_object *no, else no->set = sta->set; ipfw_objhash_add(ni, no); + return (0); } /* * Cleans up ochange field for all tables. */ -static void +static int clean_table_set_data(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3162,6 +3164,7 @@ clean_table_set_data(struct namedobj_instance *ni, struct named_object *no, sta = (struct swap_table_args *)arg; tc->ochanged = 0; + return (0); } /* @@ -3318,7 +3321,7 @@ static struct ipfw_sopt_handler scodes[] = { { IP_FW_TABLE_XGETSIZE, 0, HDIR_GET, get_table_size }, }; -static void +static int destroy_table_locked(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3328,6 +3331,7 @@ destroy_table_locked(struct namedobj_instance *ni, struct named_object *no, printf("Error unlinking kidx %d from table %s\n", no->kidx, no->name); free_table_config(ni, (struct table_config *)no); + return (0); } /* diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c index b0ad73d403bb..bd6a54d5b97a 100644 --- a/sys/netpfil/ipfw/ip_fw_table_algo.c +++ b/sys/netpfil/ipfw/ip_fw_table_algo.c @@ -1941,7 +1941,7 @@ static int ta_lookup_ifidx(struct table_info *ti, void *key, uint32_t keylen, static int ta_init_ifidx(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, char *data, uint8_t tflags); static void ta_change_ti_ifidx(void *ta_state, struct table_info *ti); -static void destroy_ifidx_locked(struct namedobj_instance *ii, +static int destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no, void *arg); static void ta_destroy_ifidx(void *ta_state, struct table_info *ti); static void ta_dump_ifidx_tinfo(void *ta_state, struct table_info *ti, @@ -1969,7 +1969,7 @@ static int ta_dump_ifidx_tentry(void *ta_state, struct table_info *ti, void *e, ipfw_obj_tentry *tent); static int ta_find_ifidx_tentry(void *ta_state, struct table_info *ti, ipfw_obj_tentry *tent); -static void foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, +static int foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, void *arg); static void ta_foreach_ifidx(void *ta_state, struct table_info *ti, ta_foreach_f *f, void *arg); @@ -2126,7 +2126,7 @@ ta_change_ti_ifidx(void *ta_state, struct table_info *ti) icfg->ti = ti; } -static void +static int destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no, void *arg) { @@ -2139,6 +2139,7 @@ destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no, ipfw_iface_del_notify(ch, &ife->ic); ipfw_iface_unref(ch, &ife->ic); free(ife, M_IPFW_TBL); + return (0); } @@ -2560,7 +2561,7 @@ struct wa_ifidx { void *arg; }; -static void +static int foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, void *arg) { @@ -2571,6 +2572,7 @@ foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, wa = (struct wa_ifidx *)arg; wa->f(ife, wa->arg); + return (0); } static void diff --git a/sys/netpfil/ipfw/ip_fw_table_value.c b/sys/netpfil/ipfw/ip_fw_table_value.c index 7ca316d1352f..e92a5a979fb8 100644 --- a/sys/netpfil/ipfw/ip_fw_table_value.c +++ b/sys/netpfil/ipfw/ip_fw_table_value.c @@ -147,7 +147,7 @@ get_value_ptrs(struct ip_fw_chain *ch, struct table_config *tc, int vshared, /* * Update pointers to real vaues after @pval change. */ -static void +static int update_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) { struct vdump_args *da; @@ -160,7 +160,7 @@ update_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) pval = da->pval; ptv->pval = &pval[ptv->no.kidx]; ptv->no.name = (char *)&pval[ptv->no.kidx]; - + return (0); } /* @@ -693,7 +693,7 @@ ipfw_export_table_value_v1(struct table_value *v, ipfw_table_value *piv) * Exports real value data into ipfw_table_value structure. * Utilizes "spare1" field to store kernel index. */ -static void +static int dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) { struct vdump_args *da; @@ -707,11 +707,12 @@ dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) /* Out of memory, returning */ if (v == NULL) { da->error = ENOMEM; - return; + return (ENOMEM); } memcpy(v, ptv->pval, sizeof(*v)); v->spare1 = ptv->no.kidx; + return (0); } /* @@ -785,12 +786,13 @@ ipfw_table_value_init(struct ip_fw_chain *ch, int first) IPFW_ADD_SOPT_HANDLER(first, scodes); } -static void +static int destroy_value(struct namedobj_instance *ni, struct named_object *no, void *arg) { free(no, M_IPFW); + return (0); } void