summaryrefslogtreecommitdiffstats
path: root/iptables/nft-shared.c
diff options
context:
space:
mode:
Diffstat (limited to 'iptables/nft-shared.c')
-rw-r--r--iptables/nft-shared.c136
1 files changed, 103 insertions, 33 deletions
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 0a4b85a3..00310a37 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -82,6 +82,24 @@ void add_bitwise_u16(struct nft_rule *r, int mask, int xor)
nft_rule_add_expr(r, expr);
}
+static void add_bitwise(struct nft_rule *r, uint8_t *mask, size_t len)
+{
+ struct nft_rule_expr *expr;
+ uint32_t xor[4] = { 0 };
+
+ expr = nft_rule_expr_alloc("bitwise");
+ if (expr == NULL)
+ return;
+
+ nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_SREG, NFT_REG_1);
+ nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_DREG, NFT_REG_1);
+ nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_LEN, len);
+ nft_rule_expr_set(expr, NFT_EXPR_BITWISE_MASK, mask, len);
+ nft_rule_expr_set(expr, NFT_EXPR_BITWISE_XOR, &xor, len);
+
+ nft_rule_add_expr(r, expr);
+}
+
void add_cmp_ptr(struct nft_rule *r, uint32_t op, void *data, size_t len)
{
struct nft_rule_expr *expr;
@@ -151,11 +169,12 @@ void add_outiface(struct nft_rule *r, char *iface, int invflags)
}
void add_addr(struct nft_rule *r, int offset,
- void *data, size_t len, int invflags)
+ void *data, void *mask, size_t len, int invflags)
{
uint32_t op;
add_payload(r, offset, len);
+ add_bitwise(r, mask, len);
if (invflags & IPT_INV_SRCIP || invflags & IPT_INV_DSTIP)
op = NFT_CMP_NEQ;
@@ -284,7 +303,7 @@ static void *nft_get_data(struct nft_xt_ctx *ctx)
case NFPROTO_IPV6:
return ctx->state.cs;
case NFPROTO_ARP:
- return ctx->state.fw;
+ return ctx->state.cs_arp;
default:
/* Should not happen */
return NULL;
@@ -298,8 +317,8 @@ void nft_parse_target(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
const void *targinfo = nft_rule_expr_get(e, NFT_EXPR_TG_INFO, &tg_len);
struct xtables_target *target;
struct xt_entry_target *t;
- struct nft_family_ops *ops;
size_t size;
+ struct nft_family_ops *ops;
void *data = nft_get_data(ctx);
target = xtables_find_target(targname, XTF_TRY_LOAD);
@@ -365,24 +384,11 @@ void print_proto(uint16_t proto, int invert)
printf("-p %u ", proto);
}
-void get_cmp_data(struct nft_rule_expr_iter *iter,
- void *data, size_t dlen, bool *inv)
+void get_cmp_data(struct nft_rule_expr *e, void *data, size_t dlen, bool *inv)
{
- struct nft_rule_expr *e;
- const char *name;
uint32_t len;
uint8_t op;
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
- return;
- }
-
memcpy(data, nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len), dlen);
op = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_OP);
if (op == NFT_CMP_NEQ)
@@ -393,33 +399,49 @@ void get_cmp_data(struct nft_rule_expr_iter *iter,
void nft_parse_meta(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
{
- uint8_t key = nft_rule_expr_get_u32(e, NFT_EXPR_META_KEY);
- struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
- const char *name;
- void *data = nft_get_data(ctx);
+ ctx->reg = nft_rule_expr_get_u32(e, NFT_EXPR_META_DREG);
+ ctx->meta.key = nft_rule_expr_get_u32(e, NFT_EXPR_META_KEY);
+ ctx->flags |= NFT_XT_CTX_META;
+}
- e = nft_rule_expr_iter_next(ctx->iter);
- if (e == NULL)
- return;
+void nft_parse_payload(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+{
+ ctx->reg = nft_rule_expr_get_u32(e, NFT_EXPR_META_DREG);
+ ctx->payload.offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+ ctx->flags |= NFT_XT_CTX_PAYLOAD;
+}
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
+void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+{
+ uint32_t reg, len;
+ const void *data;
+
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_BITWISE_SREG);
+ if (ctx->reg && reg != ctx->reg)
return;
- }
- ops->parse_meta(e, key, data);
+ data = nft_rule_expr_get(e, NFT_EXPR_BITWISE_XOR, &len);
+ memcpy(ctx->bitwise.xor, data, len);
+ data = nft_rule_expr_get(e, NFT_EXPR_BITWISE_MASK, &len);
+ memcpy(ctx->bitwise.mask, data, len);
+ ctx->flags |= NFT_XT_CTX_BITWISE;
}
-void nft_parse_payload(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
{
struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
- uint32_t offset;
void *data = nft_get_data(ctx);
+ uint32_t reg;
- offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_SREG);
+ if (ctx->reg && reg != ctx->reg)
+ return;
- ops->parse_payload(ctx->iter, offset, data);
+ if (ctx->flags & NFT_XT_CTX_META)
+ ops->parse_meta(ctx, e, data);
+ /* bitwise context is interpreted from payload */
+ if (ctx->flags & NFT_XT_CTX_PAYLOAD)
+ ops->parse_payload(ctx, e, data);
}
void nft_parse_counter(struct nft_rule_expr *e, struct xt_counters *counters)
@@ -486,6 +508,10 @@ void nft_rule_to_iptables_command_state(struct nft_rule *r,
nft_parse_payload(&ctx, expr);
else if (strcmp(name, "meta") == 0)
nft_parse_meta(&ctx, expr);
+ else if (strcmp(name, "bitwise") == 0)
+ nft_parse_bitwise(&ctx, expr);
+ else if (strcmp(name, "cmp") == 0)
+ nft_parse_cmp(&ctx, expr);
else if (strcmp(name, "immediate") == 0)
nft_parse_immediate(&ctx, expr);
else if (strcmp(name, "match") == 0)
@@ -506,6 +532,50 @@ void nft_rule_to_iptables_command_state(struct nft_rule *r,
cs->jumpto = "";
}
+void print_header(unsigned int format, const char *chain, const char *pol,
+ const struct xt_counters *counters, bool basechain,
+ uint32_t refs)
+{
+ printf("Chain %s", chain);
+ if (basechain) {
+ printf(" (policy %s", pol);
+ if (!(format & FMT_NOCOUNTS)) {
+ fputc(' ', stdout);
+ xtables_print_num(counters->pcnt, (format|FMT_NOTABLE));
+ fputs("packets, ", stdout);
+ xtables_print_num(counters->bcnt, (format|FMT_NOTABLE));
+ fputs("bytes", stdout);
+ }
+ printf(")\n");
+ } else {
+ printf(" (%u references)\n", refs);
+ }
+
+ if (format & FMT_LINENUMBERS)
+ printf(FMT("%-4s ", "%s "), "num");
+ if (!(format & FMT_NOCOUNTS)) {
+ if (format & FMT_KILOMEGAGIGA) {
+ printf(FMT("%5s ","%s "), "pkts");
+ printf(FMT("%5s ","%s "), "bytes");
+ } else {
+ printf(FMT("%8s ","%s "), "pkts");
+ printf(FMT("%10s ","%s "), "bytes");
+ }
+ }
+ if (!(format & FMT_NOTARGET))
+ printf(FMT("%-9s ","%s "), "target");
+ fputs(" prot ", stdout);
+ if (format & FMT_OPTIONS)
+ fputs("opt", stdout);
+ if (format & FMT_VIA) {
+ printf(FMT(" %-6s ","%s "), "in");
+ printf(FMT("%-6s ","%s "), "out");
+ }
+ printf(FMT(" %-19s ","%s "), "source");
+ printf(FMT(" %-19s "," %s "), "destination");
+ printf("\n");
+}
+
void print_firewall_details(const struct iptables_command_state *cs,
const char *targname, uint8_t flags,
uint8_t invflags, uint8_t proto,