summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parser_bison.y3
-rw-r--r--src/payload.c82
-rw-r--r--src/proto.c14
-rw-r--r--src/scanner.l2
4 files changed, 95 insertions, 6 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y
index bfd53ab3..c517dc38 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -422,6 +422,7 @@ int nft_lex(void *, void *, void *);
%token ICMP6 "icmpv6"
%token PPTR "param-problem"
%token MAXDELAY "max-delay"
+%token TADDR "taddr"
%token AH "ah"
%token RESERVED "reserved"
@@ -5746,6 +5747,8 @@ icmp6_hdr_field : TYPE close_scope_type { $$ = ICMP6HDR_TYPE; }
| ID { $$ = ICMP6HDR_ID; }
| SEQUENCE { $$ = ICMP6HDR_SEQ; }
| MAXDELAY { $$ = ICMP6HDR_MAXDELAY; }
+ | TADDR { $$ = ICMP6HDR_TADDR; }
+ | DADDR { $$ = ICMP6HDR_DADDR; }
;
auth_hdr_expr : AH auth_hdr_field close_scope_ah
diff --git a/src/payload.c b/src/payload.c
index 89bb38eb..140ca50a 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -793,11 +793,40 @@ static uint8_t icmp_dep_to_type(enum icmp_hdr_field_type t)
case PROTO_ICMP6_MTU: return ICMP6_PACKET_TOO_BIG;
case PROTO_ICMP6_MGMQ: return MLD_LISTENER_QUERY;
case PROTO_ICMP6_PPTR: return ICMP6_PARAM_PROB;
+ case PROTO_ICMP6_REDIRECT: return ND_REDIRECT;
+ case PROTO_ICMP6_ADDRESS: return ND_NEIGHBOR_SOLICIT;
}
BUG("Missing icmp type mapping");
}
+static bool icmp_dep_type_match(enum icmp_hdr_field_type t, uint8_t type)
+{
+ switch (t) {
+ case PROTO_ICMP_ECHO:
+ return type == ICMP_ECHO || type == ICMP_ECHOREPLY;
+ case PROTO_ICMP6_ECHO:
+ return type == ICMP6_ECHO_REQUEST || type == ICMP6_ECHO_REPLY;
+ case PROTO_ICMP6_ADDRESS:
+ return type == ND_NEIGHBOR_SOLICIT ||
+ type == ND_NEIGHBOR_ADVERT ||
+ type == ND_REDIRECT ||
+ type == MLD_LISTENER_QUERY ||
+ type == MLD_LISTENER_REPORT ||
+ type == MLD_LISTENER_REDUCTION;
+ case PROTO_ICMP_ADDRESS:
+ case PROTO_ICMP_MTU:
+ case PROTO_ICMP6_MTU:
+ case PROTO_ICMP6_MGMQ:
+ case PROTO_ICMP6_PPTR:
+ case PROTO_ICMP6_REDIRECT:
+ return icmp_dep_to_type(t) == type;
+ case PROTO_ICMP_ANY:
+ return true;
+ }
+ BUG("Missing icmp type mapping");
+}
+
static bool payload_may_dependency_kill_icmp(struct payload_dep_ctx *ctx, struct expr *expr)
{
const struct expr *dep = payload_dependency_get(ctx, expr->payload.base);
@@ -810,6 +839,11 @@ static bool payload_may_dependency_kill_icmp(struct payload_dep_ctx *ctx, struct
if (dep->left->payload.desc != expr->payload.desc)
return false;
+ if (expr->payload.tmpl->icmp_dep == PROTO_ICMP_ECHO ||
+ expr->payload.tmpl->icmp_dep == PROTO_ICMP6_ECHO ||
+ expr->payload.tmpl->icmp_dep == PROTO_ICMP6_ADDRESS)
+ return false;
+
return ctx->icmp_type == icmp_dep_to_type(icmp_dep);
}
@@ -995,7 +1029,8 @@ void payload_expr_complete(struct expr *expr, const struct proto_ctx *ctx)
continue;
if (tmpl->icmp_dep && ctx->th_dep.icmp.type &&
- ctx->th_dep.icmp.type != icmp_dep_to_type(tmpl->icmp_dep))
+ !icmp_dep_type_match(tmpl->icmp_dep,
+ ctx->th_dep.icmp.type))
continue;
expr->dtype = tmpl->dtype;
@@ -1130,7 +1165,8 @@ void payload_expr_expand(struct list_head *list, struct expr *expr,
continue;
if (tmpl->icmp_dep && ctx->th_dep.icmp.type &&
- ctx->th_dep.icmp.type != icmp_dep_to_type(tmpl->icmp_dep))
+ !icmp_dep_type_match(tmpl->icmp_dep,
+ ctx->th_dep.icmp.type))
continue;
if (tmpl->len <= expr->len) {
@@ -1287,6 +1323,38 @@ __payload_gen_icmp_echo_dependency(struct eval_ctx *ctx, const struct expr *expr
return expr_stmt_alloc(&dep->location, dep);
}
+static struct stmt *
+__payload_gen_icmp6_addr_dependency(struct eval_ctx *ctx, const struct expr *expr,
+ const struct proto_desc *desc)
+{
+ static const uint8_t icmp_addr_types[] = {
+ MLD_LISTENER_QUERY,
+ MLD_LISTENER_REPORT,
+ MLD_LISTENER_REDUCTION,
+ ND_NEIGHBOR_SOLICIT,
+ ND_NEIGHBOR_ADVERT,
+ ND_REDIRECT
+ };
+ struct expr *left, *right, *dep, *set;
+ size_t i;
+
+ left = payload_expr_alloc(&expr->location, desc, desc->protocol_key);
+
+ set = set_expr_alloc(&expr->location, NULL);
+
+ for (i = 0; i < array_size(icmp_addr_types); ++i) {
+ right = constant_expr_alloc(&expr->location, &icmp6_type_type,
+ BYTEORDER_BIG_ENDIAN, BITS_PER_BYTE,
+ constant_data_ptr(icmp_addr_types[i],
+ BITS_PER_BYTE));
+ right = set_elem_expr_alloc(&expr->location, right);
+ compound_expr_add(set, right);
+ }
+
+ dep = relational_expr_alloc(&expr->location, OP_IMPLICIT, left, set);
+ return expr_stmt_alloc(&dep->location, dep);
+}
+
int payload_gen_icmp_dependency(struct eval_ctx *ctx, const struct expr *expr,
struct stmt **res)
{
@@ -1345,6 +1413,16 @@ int payload_gen_icmp_dependency(struct eval_ctx *ctx, const struct expr *expr,
&icmp6_type_type,
desc);
break;
+ case PROTO_ICMP6_ADDRESS:
+ if (icmp_dep_type_match(PROTO_ICMP6_ADDRESS,
+ pctx->th_dep.icmp.type))
+ goto done;
+ type = ND_NEIGHBOR_SOLICIT;
+ if (pctx->th_dep.icmp.type)
+ goto bad_proto;
+ stmt = __payload_gen_icmp6_addr_dependency(ctx, expr, desc);
+ break;
+ case PROTO_ICMP6_REDIRECT:
case PROTO_ICMP6_MTU:
case PROTO_ICMP6_MGMQ:
case PROTO_ICMP6_PPTR:
diff --git a/src/proto.c b/src/proto.c
index dd84f7c1..553b6a44 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -438,10 +438,10 @@ const struct datatype icmp_type_type = {
.sym_tbl = &icmp_type_tbl,
};
-#define ICMP46HDR_FIELD(__token, __struct, __member, __dep) \
+#define ICMP46HDR_FIELD(__token, __dtype, __struct, __member, __dep) \
{ \
.token = (__token), \
- .dtype = &integer_type, \
+ .dtype = &__dtype, \
.byteorder = BYTEORDER_BIG_ENDIAN, \
.offset = offsetof(__struct, __member) * 8, \
.len = field_sizeof(__struct, __member) * 8, \
@@ -449,7 +449,7 @@ const struct datatype icmp_type_type = {
}
#define ICMPHDR_FIELD(__token, __member, __dep) \
- ICMP46HDR_FIELD(__token, struct icmphdr, __member, __dep)
+ ICMP46HDR_FIELD(__token, integer_type, struct icmphdr, __member, __dep)
#define ICMPHDR_TYPE(__name, __type, __member) \
HDR_TYPE(__name, __type, struct icmphdr, __member)
@@ -913,7 +913,7 @@ const struct datatype icmp6_type_type = {
};
#define ICMP6HDR_FIELD(__token, __member, __dep) \
- ICMP46HDR_FIELD(__token, struct icmp6_hdr, __member, __dep)
+ ICMP46HDR_FIELD(__token, integer_type, struct icmp6_hdr, __member, __dep)
#define ICMP6HDR_TYPE(__name, __type, __member) \
HDR_TYPE(__name, __type, struct icmp6_hdr, __member)
@@ -933,6 +933,12 @@ const struct proto_desc proto_icmp6 = {
[ICMP6HDR_ID] = ICMP6HDR_FIELD("id", icmp6_id, PROTO_ICMP6_ECHO),
[ICMP6HDR_SEQ] = ICMP6HDR_FIELD("sequence", icmp6_seq, PROTO_ICMP6_ECHO),
[ICMP6HDR_MAXDELAY] = ICMP6HDR_FIELD("max-delay", icmp6_maxdelay, PROTO_ICMP6_MGMQ),
+ [ICMP6HDR_TADDR] = ICMP46HDR_FIELD("taddr", ip6addr_type,
+ struct nd_neighbor_solicit, nd_ns_target,
+ PROTO_ICMP6_ADDRESS),
+ [ICMP6HDR_DADDR] = ICMP46HDR_FIELD("daddr", ip6addr_type,
+ struct nd_redirect, nd_rd_dst,
+ PROTO_ICMP6_REDIRECT),
},
};
diff --git a/src/scanner.l b/src/scanner.l
index 15b272ab..88376b7a 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -589,6 +589,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"param-problem" { return PPTR; }
"max-delay" { return MAXDELAY; }
"mtu" { return MTU; }
+ "taddr" { return TADDR; }
+ "daddr" { return DADDR; }
}
<SCANSTATE_EXPR_AH,SCANSTATE_EXPR_ESP,SCANSTATE_ICMP,SCANSTATE_TCP>{
"sequence" { return SEQUENCE; }