diff options
Diffstat (limited to 'src/object.c')
-rw-r--r-- | src/object.c | 148 |
1 files changed, 102 insertions, 46 deletions
diff --git a/src/object.c b/src/object.c index 4f58272..19cb7d0 100644 --- a/src/object.c +++ b/src/object.c @@ -57,6 +57,8 @@ void nftnl_obj_free(const struct nftnl_obj *obj) xfree(obj->table); if (obj->flags & (1 << NFTNL_OBJ_NAME)) xfree(obj->name); + if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) + xfree(obj->user.data); xfree(obj); } @@ -67,32 +69,60 @@ bool nftnl_obj_is_set(const struct nftnl_obj *obj, uint16_t attr) return obj->flags & (1 << attr); } +EXPORT_SYMBOL(nftnl_obj_unset); +void nftnl_obj_unset(struct nftnl_obj *obj, uint16_t attr) +{ + if (!(obj->flags & (1 << attr))) + return; + + switch (attr) { + case NFTNL_OBJ_TABLE: + xfree(obj->table); + break; + case NFTNL_OBJ_NAME: + xfree(obj->name); + break; + case NFTNL_OBJ_USERDATA: + xfree(obj->user.data); + break; + case NFTNL_OBJ_TYPE: + case NFTNL_OBJ_FAMILY: + case NFTNL_OBJ_USE: + case NFTNL_OBJ_HANDLE: + break; + default: + break; + } + + obj->flags &= ~(1 << attr); +} + static uint32_t nftnl_obj_validate[NFTNL_OBJ_MAX + 1] = { + [NFTNL_OBJ_TYPE] = sizeof(uint32_t), [NFTNL_OBJ_FAMILY] = sizeof(uint32_t), [NFTNL_OBJ_USE] = sizeof(uint32_t), [NFTNL_OBJ_HANDLE] = sizeof(uint64_t), }; EXPORT_SYMBOL(nftnl_obj_set_data); -void nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr, - const void *data, uint32_t data_len) +int nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr, + const void *data, uint32_t data_len) { if (attr < NFTNL_OBJ_MAX) nftnl_assert_validate(data, nftnl_obj_validate, attr, data_len); switch (attr) { case NFTNL_OBJ_TABLE: - xfree(obj->table); - obj->table = strdup(data); + return nftnl_set_str_attr(&obj->table, &obj->flags, + attr, data, data_len); break; case NFTNL_OBJ_NAME: - xfree(obj->name); - obj->name = strdup(data); - break; + return nftnl_set_str_attr(&obj->name, &obj->flags, + attr, data, data_len); case NFTNL_OBJ_TYPE: obj->ops = nftnl_obj_ops_lookup(*((uint32_t *)data)); if (!obj->ops) - return; + return -1; break; case NFTNL_OBJ_FAMILY: memcpy(&obj->family, data, sizeof(obj->family)); @@ -103,12 +133,32 @@ void nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr, case NFTNL_OBJ_HANDLE: memcpy(&obj->handle, data, sizeof(obj->handle)); break; - default: - if (obj->ops) - obj->ops->set(obj, attr, data, data_len); + case NFTNL_OBJ_USERDATA: + if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) + xfree(obj->user.data); + + obj->user.data = malloc(data_len); + if (!obj->user.data) + return -1; + memcpy(obj->user.data, data, data_len); + obj->user.len = data_len; break; + default: + if (!obj->ops || + attr < NFTNL_OBJ_BASE || + attr > obj->ops->nftnl_max_attr || + !obj->ops->attr_policy) + return -1; + + if (obj->ops->attr_policy[attr].maxlen && + obj->ops->attr_policy[attr].maxlen < data_len) + return -1; + + if (obj->ops->set(obj, attr, data, data_len) < 0) + return -1; } obj->flags |= (1 << attr); + return 0; } void nftnl_obj_set(struct nftnl_obj *obj, uint16_t attr, const void *data) __visible; @@ -118,37 +168,37 @@ void nftnl_obj_set(struct nftnl_obj *obj, uint16_t attr, const void *data) } EXPORT_SYMBOL(nftnl_obj_set_u8); -void nftnl_obj_set_u8(struct nftnl_obj *obj, uint16_t attr, uint8_t val) +int nftnl_obj_set_u8(struct nftnl_obj *obj, uint16_t attr, uint8_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint8_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint8_t)); } EXPORT_SYMBOL(nftnl_obj_set_u16); -void nftnl_obj_set_u16(struct nftnl_obj *obj, uint16_t attr, uint16_t val) +int nftnl_obj_set_u16(struct nftnl_obj *obj, uint16_t attr, uint16_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint16_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint16_t)); } EXPORT_SYMBOL(nftnl_obj_set_u32); -void nftnl_obj_set_u32(struct nftnl_obj *obj, uint16_t attr, uint32_t val) +int nftnl_obj_set_u32(struct nftnl_obj *obj, uint16_t attr, uint32_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint32_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint32_t)); } EXPORT_SYMBOL(nftnl_obj_set_u64); -void nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val) +int nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint64_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint64_t)); } EXPORT_SYMBOL(nftnl_obj_set_str); -void nftnl_obj_set_str(struct nftnl_obj *obj, uint16_t attr, const char *str) +int nftnl_obj_set_str(struct nftnl_obj *obj, uint16_t attr, const char *str) { - nftnl_obj_set_data(obj, attr, str, 0); + return nftnl_obj_set_data(obj, attr, str, strlen(str) + 1); } EXPORT_SYMBOL(nftnl_obj_get_data); -const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr, +const void *nftnl_obj_get_data(const struct nftnl_obj *obj, uint16_t attr, uint32_t *data_len) { if (!(obj->flags & (1 << attr))) @@ -174,6 +224,9 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr, case NFTNL_OBJ_HANDLE: *data_len = sizeof(uint64_t); return &obj->handle; + case NFTNL_OBJ_USERDATA: + *data_len = obj->user.len; + return obj->user.data; default: if (obj->ops) return obj->ops->get(obj, attr, data_len); @@ -183,42 +236,42 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr, } EXPORT_SYMBOL(nftnl_obj_get); -const void *nftnl_obj_get(struct nftnl_obj *obj, uint16_t attr) +const void *nftnl_obj_get(const struct nftnl_obj *obj, uint16_t attr) { uint32_t data_len; return nftnl_obj_get_data(obj, attr, &data_len); } EXPORT_SYMBOL(nftnl_obj_get_u8); -uint8_t nftnl_obj_get_u8(struct nftnl_obj *obj, uint16_t attr) +uint8_t nftnl_obj_get_u8(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint8_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_u16); -uint16_t nftnl_obj_get_u16(struct nftnl_obj *obj, uint16_t attr) +uint16_t nftnl_obj_get_u16(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint16_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_u32); -uint32_t nftnl_obj_get_u32(struct nftnl_obj *obj, uint16_t attr) +uint32_t nftnl_obj_get_u32(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint32_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_u64); -uint64_t nftnl_obj_get_u64(struct nftnl_obj *obj, uint16_t attr) +uint64_t nftnl_obj_get_u64(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint64_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_str); -const char *nftnl_obj_get_str(struct nftnl_obj *obj, uint16_t attr) +const char *nftnl_obj_get_str(const struct nftnl_obj *obj, uint16_t attr) { return nftnl_obj_get(obj, attr); } @@ -235,6 +288,8 @@ void nftnl_obj_nlmsg_build_payload(struct nlmsghdr *nlh, mnl_attr_put_u32(nlh, NFTA_OBJ_TYPE, htonl(obj->ops->type)); if (obj->flags & (1 << NFTNL_OBJ_HANDLE)) mnl_attr_put_u64(nlh, NFTA_OBJ_HANDLE, htobe64(obj->handle)); + if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) + mnl_attr_put(nlh, NFTA_OBJ_USERDATA, obj->user.len, obj->user.data); if (obj->ops) { struct nlattr *nest = mnl_attr_nest_start(nlh, NFTA_OBJ_DATA); @@ -269,6 +324,10 @@ static int nftnl_obj_parse_attr_cb(const struct nlattr *attr, void *data) if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) abi_breakage(); break; + case NFTA_OBJ_USERDATA: + if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) + abi_breakage(); + break; } tb[type] = attr; @@ -315,6 +374,11 @@ int nftnl_obj_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_obj *obj) obj->handle = be64toh(mnl_attr_get_u64(tb[NFTA_OBJ_HANDLE])); obj->flags |= (1 << NFTNL_OBJ_HANDLE); } + if (tb[NFTA_OBJ_USERDATA]) { + nftnl_obj_set_data(obj, NFTNL_OBJ_USERDATA, + mnl_attr_get_payload(tb[NFTA_OBJ_USERDATA]), + mnl_attr_get_payload_len(tb[NFTA_OBJ_USERDATA])); + } obj->family = nfg->nfgen_family; obj->flags |= (1 << NFTNL_OBJ_FAMILY); @@ -358,46 +422,38 @@ int nftnl_obj_parse_file(struct nftnl_obj *obj, enum nftnl_parse_type type, return nftnl_obj_do_parse(obj, type, fp, err, NFTNL_PARSE_FILE); } -static int nftnl_obj_snprintf_dflt(char *buf, size_t size, +static int nftnl_obj_snprintf_dflt(char *buf, size_t remain, const struct nftnl_obj *obj, uint32_t type, uint32_t flags) { const char *name = obj->ops ? obj->ops->name : "(unknown)"; - int ret, remain = size, offset = 0; + int ret, offset = 0; - ret = snprintf(buf, size, "table %s name %s use %u [ %s ", + ret = snprintf(buf, remain, "table %s name %s use %u [ %s ", obj->table, obj->name, obj->use, name); SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (obj->ops) { - ret = obj->ops->snprintf(buf + offset, offset, type, flags, - obj); + ret = obj->ops->output(buf + offset, remain, flags, obj); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, offset, "]"); + ret = snprintf(buf + offset, remain, "]"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } -static int nftnl_obj_cmd_snprintf(char *buf, size_t size, +static int nftnl_obj_cmd_snprintf(char *buf, size_t remain, const struct nftnl_obj *obj, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_obj_snprintf_dflt(buf + offset, remain, obj, type, - flags); - break; - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } - SNPRINTF_BUFFER_SIZE(ret, remain, offset); + ret = nftnl_obj_snprintf_dflt(buf + offset, remain, obj, type, flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } |