diff options
author | Patrick McHardy <kaber@trash.net> | 2009-03-31 04:14:26 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-03-31 04:14:26 +0200 |
commit | 53fc2c7a799877c5859298bd16b578711af9cca2 (patch) | |
tree | 6fdfd8a4650fcc3a7164a93f9d05003511595005 /src/netlink.c | |
parent | 9fe2e9d494a229a3f833add44d7242abe46aa156 (diff) |
netlink: move data related functions to netlink.c
Move the data related function to netlink.c as they're going to be needed
outside of rule context for set maintenance.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'src/netlink.c')
-rw-r--r-- | src/netlink.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/netlink.c b/src/netlink.c index 548f4fb8..8ef14011 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -20,6 +20,7 @@ #include <nftables.h> #include <netlink.h> #include <expression.h> +#include <gmputil.h> #include <utils.h> #include <erec.h> @@ -133,6 +134,118 @@ struct nfnl_nft_data *alloc_nft_data(const void *data, unsigned int len) return nld; } +struct nfnl_nft_data *netlink_gen_raw_data(const mpz_t value, + enum byteorder byteorder, + unsigned int len) +{ + unsigned char data[len]; + + mpz_export_data(data, value, byteorder, len); + return alloc_nft_data(data, len); +} + +static struct nfnl_nft_data *netlink_gen_concat_data(const struct expr *expr) +{ + const struct expr *i; + unsigned int len, offset; + + len = 0; + list_for_each_entry(i, &expr->expressions, list) + len += i->len; + + if (1) { + unsigned char data[len / BITS_PER_BYTE]; + + offset = 0; + list_for_each_entry(i, &expr->expressions, list) { + assert(i->ops->type == EXPR_VALUE); + mpz_export_data(data + offset, i->value, i->byteorder, + i->len / BITS_PER_BYTE); + offset += i->len / BITS_PER_BYTE; + } + + return alloc_nft_data(data, len / BITS_PER_BYTE); + } +} + +static struct nfnl_nft_data *netlink_gen_constant_data(const struct expr *expr) +{ + assert(expr->ops->type == EXPR_VALUE); + return netlink_gen_raw_data(expr->value, expr->byteorder, + div_round_up(expr->len, BITS_PER_BYTE)); +} + +static struct nfnl_nft_data *netlink_gen_verdict(const struct expr *expr) +{ + struct nfnl_nft_data *verdict; + + verdict = nfnl_nft_verdict_alloc(); + nfnl_nft_verdict_set_verdict(verdict, expr->verdict); + + switch (expr->verdict) { + case NFT_JUMP: + case NFT_GOTO: + nfnl_nft_verdict_set_chain(verdict, expr->chain); + break; + } + + return verdict; +} + +struct nfnl_nft_data *netlink_gen_data(const struct expr *expr) +{ + switch (expr->ops->type) { + case EXPR_VALUE: + return netlink_gen_constant_data(expr); + case EXPR_CONCAT: + return netlink_gen_concat_data(expr); + case EXPR_VERDICT: + return netlink_gen_verdict(expr); + default: + BUG(); + } +} + +struct expr *netlink_alloc_value(const struct location *loc, + const struct nfnl_nft_data *nld) +{ + return constant_expr_alloc(loc, &invalid_type, BYTEORDER_INVALID, + nfnl_nft_data_get_size(nld) * BITS_PER_BYTE, + nfnl_nft_data_get(nld)); +} + +static struct expr *netlink_alloc_verdict(const struct location *loc, + const struct nfnl_nft_data *nld) +{ + unsigned int code; + char *chain; + + code = nfnl_nft_verdict_get_verdict(nld); + switch (code) { + case NFT_JUMP: + case NFT_GOTO: + chain = xstrdup(nfnl_nft_verdict_get_chain(nld)); + break; + default: + chain = NULL; + break; + } + + return verdict_expr_alloc(loc, code, chain); +} + +struct expr *netlink_alloc_data(const struct location *loc, + const struct nfnl_nft_data *nld, + enum nft_registers dreg) +{ + switch (dreg) { + case NFT_REG_VERDICT: + return netlink_alloc_verdict(loc, nld); + default: + return netlink_alloc_value(loc, nld); + } +} + int netlink_add_rule(struct netlink_ctx *ctx, const struct handle *h, const struct rule *rule) { |