diff options
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r-- | src/netlink_delinearize.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 796b6327..397b65c0 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -14,6 +14,9 @@ #include <string.h> #include <limits.h> #include <linux/netfilter/nf_tables.h> +#include <arpa/inet.h> +#include <linux/netfilter.h> +#include <net/ethernet.h> #include <netlink.h> #include <rule.h> #include <statement.h> @@ -472,8 +475,15 @@ static void netlink_parse_reject(struct netlink_parse_ctx *ctx, const struct nft_rule_expr *expr) { struct stmt *stmt; + uint8_t icmp_code; stmt = reject_stmt_alloc(loc); + stmt->reject.type = nft_rule_expr_get_u32(expr, NFT_EXPR_REJECT_TYPE); + icmp_code = nft_rule_expr_get_u8(expr, NFT_EXPR_REJECT_CODE); + stmt->reject.icmp_code = icmp_code; + stmt->reject.expr = constant_expr_alloc(loc, &integer_type, + BYTEORDER_HOST_ENDIAN, 8, + &icmp_code); list_add_tail(&stmt->list, &ctx->rule->stmts); } @@ -899,6 +909,60 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, } } +static void stmt_reject_postprocess(struct rule_pp_ctx rctx, struct stmt *stmt) +{ + const struct proto_desc *desc, *base; + int protocol; + + switch (rctx.pctx.family) { + case NFPROTO_IPV4: + stmt->reject.family = rctx.pctx.family; + stmt->reject.expr->dtype = &icmp_code_type; + break; + case NFPROTO_IPV6: + stmt->reject.family = rctx.pctx.family; + stmt->reject.expr->dtype = &icmpv6_code_type; + break; + case NFPROTO_INET: + if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH) + break; + base = rctx.pctx.protocol[PROTO_BASE_LL_HDR].desc; + desc = rctx.pctx.protocol[PROTO_BASE_NETWORK_HDR].desc; + protocol = proto_find_num(base, desc); + switch (protocol) { + case NFPROTO_IPV4: + stmt->reject.expr->dtype = &icmp_code_type; + break; + case NFPROTO_IPV6: + stmt->reject.expr->dtype = &icmpv6_code_type; + break; + } + stmt->reject.family = protocol; + break; + case NFPROTO_BRIDGE: + if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH) + break; + base = rctx.pctx.protocol[PROTO_BASE_LL_HDR].desc; + desc = rctx.pctx.protocol[PROTO_BASE_NETWORK_HDR].desc; + protocol = proto_find_num(base, desc); + switch (protocol) { + case __constant_htons(ETH_P_IP): + stmt->reject.family = NFPROTO_IPV4; + stmt->reject.expr->dtype = &icmp_code_type; + break; + case __constant_htons(ETH_P_IPV6): + stmt->reject.family = NFPROTO_IPV6; + stmt->reject.expr->dtype = &icmpv6_code_type; + break; + default: + break; + } + break; + default: + break; + } +} + static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *rule) { struct rule_pp_ctx rctx; @@ -926,6 +990,9 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r if (stmt->nat.proto != NULL) expr_postprocess(&rctx, stmt, &stmt->nat.proto); break; + case STMT_REJECT: + stmt_reject_postprocess(rctx, stmt); + break; default: break; } |