diff options
Diffstat (limited to 'src/netlink.c')
-rw-r--r-- | src/netlink.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/src/netlink.c b/src/netlink.c index 4cf1a98d..a3407121 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -795,6 +795,10 @@ enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype) static const struct datatype *dtype_map_from_kernel(enum nft_data_types type) { + /* The function always returns ownership of a reference. But for + * &verdict_Type and datatype_lookup(), those are static instances, + * we can omit the datatype_get() call. + */ switch (type) { case NFT_DATA_VERDICT: return &verdict_type; @@ -930,12 +934,14 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, const struct nftnl_udata *ud[NFTNL_UDATA_SET_MAX + 1] = {}; enum byteorder keybyteorder = BYTEORDER_INVALID; enum byteorder databyteorder = BYTEORDER_INVALID; - const struct datatype *keytype, *datatype = NULL; struct expr *typeof_expr_key, *typeof_expr_data; struct setelem_parse_ctx set_parse_ctx; + const struct datatype *datatype = NULL; + const struct datatype *keytype = NULL; + const struct datatype *dtype2 = NULL; + const struct datatype *dtype = NULL; const char *udata, *comment = NULL; uint32_t flags, key, objtype = 0; - const struct datatype *dtype; uint32_t data_interval = 0; bool automerge = false; struct set *set; @@ -987,8 +993,8 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, netlink_io_error(ctx, NULL, "Unknown data type in set key %u", data); - datatype_free(keytype); - return NULL; + set = NULL; + goto out; } } @@ -1026,19 +1032,18 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, if (datatype) { uint32_t dlen; - dtype = set_datatype_alloc(datatype, databyteorder); + dtype2 = set_datatype_alloc(datatype, databyteorder); klen = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE; dlen = data_interval ? klen / 2 : klen; if (set_udata_key_valid(typeof_expr_data, dlen)) { typeof_expr_data->len = klen; - datatype_free(datatype_get(dtype)); set->data = typeof_expr_data; } else { expr_free(typeof_expr_data); set->data = constant_expr_alloc(&netlink_location, - dtype, + dtype2, databyteorder, klen, NULL); @@ -1049,16 +1054,12 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, if (data_interval) set->data->flags |= EXPR_F_INTERVAL; - - if (dtype != datatype) - datatype_free(datatype); } dtype = set_datatype_alloc(keytype, keybyteorder); klen = nftnl_set_get_u32(nls, NFTNL_SET_KEY_LEN) * BITS_PER_BYTE; if (set_udata_key_valid(typeof_expr_key, klen)) { - datatype_free(datatype_get(dtype)); set->key = typeof_expr_key; set->key_typeof_valid = true; } else { @@ -1068,9 +1069,6 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, NULL); } - if (dtype != keytype) - datatype_free(keytype); - set->flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS); set->handle.handle.id = nftnl_set_get_u64(nls, NFTNL_SET_HANDLE); @@ -1098,6 +1096,11 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, } } +out: + datatype_free(datatype); + datatype_free(keytype); + datatype_free(dtype2); + datatype_free(dtype); return set; } |