summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c168
1 files changed, 117 insertions, 51 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 977f6b49..63ba82e3 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1202,12 +1202,124 @@ static int stmt_reject_gen_dependency(struct eval_ctx *ctx, struct stmt *stmt,
return 0;
}
-static int stmt_evaluate_reject_family(struct eval_ctx *ctx, struct stmt *stmt,
- struct expr *expr)
+static int stmt_evaluate_reject_inet_family(struct eval_ctx *ctx,
+ struct stmt *stmt,
+ const struct proto_desc *desc)
{
- const struct proto_desc *desc, *base;
+ const struct proto_desc *base;
int protocol;
+ switch (stmt->reject.type) {
+ case NFT_REJECT_TCP_RST:
+ break;
+ case NFT_REJECT_ICMPX_UNREACH:
+ return stmt_error(ctx, stmt,
+ "conflicting network protocol specified");
+ case NFT_REJECT_ICMP_UNREACH:
+ base = ctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
+ protocol = proto_find_num(base, desc);
+ switch (protocol) {
+ case NFPROTO_IPV4:
+ if (stmt->reject.family == NFPROTO_IPV4)
+ break;
+ return stmt_error(ctx, stmt,
+ "conflicting protocols specified: ip vs ip6");
+ case NFPROTO_IPV6:
+ if (stmt->reject.family == NFPROTO_IPV6)
+ break;
+ return stmt_error(ctx, stmt,
+ "conflicting protocols specified: ip vs ip6");
+ default:
+ BUG("unsupported family");
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int stmt_evaluate_reject_inet(struct eval_ctx *ctx, struct stmt *stmt,
+ struct expr *expr)
+{
+ const struct proto_desc *desc;
+
+ desc = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+ if (desc != NULL &&
+ stmt_evaluate_reject_inet_family(ctx, stmt, desc) < 0)
+ return -1;
+ if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH)
+ return 0;
+ if (stmt_reject_gen_dependency(ctx, stmt, expr) < 0)
+ return -1;
+ return 0;
+}
+
+static int stmt_evaluate_reject_bridge_family(struct eval_ctx *ctx,
+ struct stmt *stmt,
+ const struct proto_desc *desc)
+{
+ const struct proto_desc *base;
+ int protocol;
+
+ switch (stmt->reject.type) {
+ case NFT_REJECT_ICMPX_UNREACH:
+ return stmt_error(ctx, stmt,
+ "conflicting network protocol specified");
+ case NFT_REJECT_TCP_RST:
+ base = ctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
+ protocol = proto_find_num(base, desc);
+ switch (protocol) {
+ case __constant_htons(ETH_P_IP):
+ case __constant_htons(ETH_P_IPV6):
+ break;
+ default:
+ return stmt_error(ctx, stmt,
+ "cannot reject this ether type");
+ }
+ break;
+ case NFT_REJECT_ICMP_UNREACH:
+ base = ctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
+ protocol = proto_find_num(base, desc);
+ switch (protocol) {
+ case __constant_htons(ETH_P_IP):
+ if (NFPROTO_IPV4 == stmt->reject.family)
+ break;
+ return stmt_error(ctx, stmt,
+ "conflicting protocols specified: ip vs ip6");
+ case __constant_htons(ETH_P_IPV6):
+ if (NFPROTO_IPV6 == stmt->reject.family)
+ break;
+ return stmt_error(ctx, stmt,
+ "conflicting protocols specified: ip vs ip6");
+ default:
+ return stmt_error(ctx, stmt,
+ "cannot reject this ether type");
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int stmt_evaluate_reject_bridge(struct eval_ctx *ctx, struct stmt *stmt,
+ struct expr *expr)
+{
+ const struct proto_desc *desc;
+
+ desc = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+ if (desc != NULL &&
+ stmt_evaluate_reject_bridge_family(ctx, stmt, desc) < 0)
+ return -1;
+ if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH)
+ return 0;
+ if (stmt_reject_gen_dependency(ctx, stmt, expr) < 0)
+ return -1;
+ return 0;
+}
+
+static int stmt_evaluate_reject_family(struct eval_ctx *ctx, struct stmt *stmt,
+ struct expr *expr)
+{
switch (ctx->pctx.family) {
case NFPROTO_ARP:
return stmt_error(ctx, stmt, "cannot use reject with arp");
@@ -1229,57 +1341,11 @@ static int stmt_evaluate_reject_family(struct eval_ctx *ctx, struct stmt *stmt,
}
break;
case NFPROTO_BRIDGE:
- base = ctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
- desc = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
- if (desc != NULL) {
- protocol = proto_find_num(base, desc);
- switch (protocol) {
- case __constant_htons(ETH_P_IP):
- if (NFPROTO_IPV4 == stmt->reject.family)
- break;
- return stmt_error(ctx, stmt,
- "conflicting protocols specified: ip vs ip6");
- case __constant_htons(ETH_P_IPV6):
- if (NFPROTO_IPV6 == stmt->reject.family)
- break;
- return stmt_error(ctx, stmt,
- "conflicting protocols specified: ip vs ip6");
- default:
- return stmt_error(ctx, stmt,
- "cannot reject this ether type");
- }
- break;
- }
- if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH)
- break;
- if (stmt_reject_gen_dependency(ctx, stmt, expr) < 0)
+ if (stmt_evaluate_reject_bridge(ctx, stmt, expr) < 0)
return -1;
break;
case NFPROTO_INET:
- base = ctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
- desc = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
- if (desc != NULL) {
- protocol = proto_find_num(base, desc);
- switch (protocol) {
- case NFPROTO_IPV4:
- if (stmt->reject.family == NFPROTO_IPV4)
- break;
- return stmt_error(ctx, stmt,
- "conflicting protocols specified: ip vs ip6");
- break;
- case NFPROTO_IPV6:
- if (stmt->reject.family == NFPROTO_IPV6)
- break;
- return stmt_error(ctx, stmt,
- "conflicting protocols specified: ip vs ip6");
- default:
- BUG("unsupported family");
- }
- break;
- }
- if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH)
- break;
- if (stmt_reject_gen_dependency(ctx, stmt, expr) < 0)
+ if (stmt_evaluate_reject_inet(ctx, stmt, expr) < 0)
return -1;
break;
}