From 00c179b4c9f9f9394cc6f79e5f2a68410631fd72 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 3 Aug 2012 17:31:48 +0200 Subject: initial version of libnftables It adds support for table, chain and rule handling. This also includes expression handling for each rule. Signed-off-by: Pablo Neira Ayuso --- src/expr/data_reg.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/expr/data_reg.c (limited to 'src/expr/data_reg.c') diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c new file mode 100644 index 0000000..5b14695 --- /dev/null +++ b/src/expr/data_reg.c @@ -0,0 +1,158 @@ +/* + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This code has been sponsored by Sophos Astaro + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "expr_ops.h" +#include "data_reg.h" +#include "internal.h" + +static int nft_data_parse_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, NFTA_DATA_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_DATA_VALUE: + if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case NFTA_DATA_VERDICT: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static int nft_verdict_parse_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, NFTA_VERDICT_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_VERDICT_CODE: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case NFTA_VERDICT_CHAIN: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static int +nft_parse_verdict(union nft_data_reg *data, const struct nlattr *attr, int *type) +{ + struct nlattr *tb[NFTA_VERDICT_MAX+1]; + + if (mnl_attr_parse_nested(attr, nft_verdict_parse_cb, tb) < 0) { + perror("mnl_attr_parse_nested"); + return -1; + } + + if (!tb[NFTA_VERDICT_CODE]) + return -1; + + data->verdict = ntohl(mnl_attr_get_u32(tb[NFTA_VERDICT_CODE])); + + switch(data->verdict) { + case NF_ACCEPT: + case NF_DROP: + case NF_QUEUE: + case NFT_CONTINUE: + case NFT_BREAK: + case NFT_RETURN: + if (type) + *type = DATA_VERDICT; + data->len = sizeof(data->verdict); + break; + case NFT_JUMP: + case NFT_GOTO: + if (!tb[NFTA_VERDICT_CHAIN]) + return -1; + + data->chain = strdup(mnl_attr_get_str(tb[NFTA_VERDICT_CHAIN])); + if (type) + *type = DATA_CHAIN; + break; + default: + return -1; + } + + return 0; +} + +static int +__nft_parse_data(union nft_data_reg *data, const struct nlattr *attr) +{ + void *orig = mnl_attr_get_payload(attr); + size_t data_len = mnl_attr_get_payload_len(attr); + + if (data_len == 0) + return -1; + + if (data_len > sizeof(uint32_t) * 4) + return -1; + + memcpy(data->val, orig, data_len); + data->len = data_len; + + return 0; +} + +int nft_parse_data(union nft_data_reg *data, struct nlattr *attr, int *type) +{ + struct nlattr *tb[NFTA_DATA_MAX+1] = {}; + int ret = 0; + + if (mnl_attr_parse_nested(attr, nft_data_parse_cb, tb) < 0) { + perror("mnl_attr_parse_nested"); + return -1; + } + if (tb[NFTA_DATA_VALUE]) { + if (type) + *type = DATA_VALUE; + + ret = __nft_parse_data(data, tb[NFTA_DATA_VALUE]); + if (ret < 0) + return ret; + } + if (tb[NFTA_DATA_VERDICT]) + ret = nft_parse_verdict(data, tb[NFTA_DATA_VERDICT], type); + + return ret; +} -- cgit v1.2.3