From 5fdd0b6a0600e66f9ff6d9a1d6b749aa68a3ba99 Mon Sep 17 00:00:00 2001 From: Alvaro Neira Date: Tue, 30 Sep 2014 17:21:40 +0200 Subject: nft: complete reject support This patch allows to use the reject action in rules. For example: nft add rule filter input udp dport 22 reject In this rule, we assume that the reason is network unreachable. Also we can specify the reason with the option "with" and the reason. For example: nft add rule filter input tcp dport 22 reject with icmp type host-unreachable In the bridge tables and inet tables, we can use this action too. For example: nft add rule inet filter input reject with icmp type host-unreachable In this rule above, this generates a meta nfproto dependency to match ipv4 traffic because we use a icmpv4 reason to reject. If the reason is not specified, we infer it from the context. Moreover, we have the new icmpx datatype. You can use this datatype for the bridge and the inet tables to simplify your ruleset. For example: nft add rule inet filter input reject with icmpx type host-unreachable We have four icmpx reason and the mapping is: ICMPX reason | ICMPv6 | ICMPv4 | | admin-prohibited | admin-prohibited | admin-prohibited port-unreachable | port-unreachable | port-unreachable no-route | no-route | net-unreachable host-unreachable | addr-unreachable | host-unreachable Signed-off-by: Alvaro Neira Ayuso Signed-off-by: Pablo Neira Ayuso --- src/netlink_delinearize.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'src/netlink_delinearize.c') 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 #include #include +#include +#include +#include #include #include #include @@ -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; } -- cgit v1.2.3