summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Leblond <eric@regit.org>2013-07-29 00:30:56 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2013-07-31 19:27:25 +0200
commitd0218ea4573837d775c3e605913a45021f1526b9 (patch)
treee22d649f5bb96353d2ab1fda6a78dfae279b774e
parenta320531e78f1bcb12b24da048f34592771392a9a (diff)
src: Add icmpv6 support
This patch adds ICMPv6 support to nftables. It is now possible to write rules such as: nft add rule ip6 filter input icmpv6 type nd-router-advert accept Signed-off-by: Eric Leblond <eric@regit.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/datatype.h2
-rw-r--r--include/payload.h14
-rw-r--r--src/parser.y33
-rw-r--r--src/payload.c59
-rw-r--r--src/scanner.l4
5 files changed, 109 insertions, 3 deletions
diff --git a/include/datatype.h b/include/datatype.h
index 053fbd9..239d5ea 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -32,6 +32,7 @@
* @TYPE_CT_STATE: conntrack state (bitmask subtype)
* @TYPE_CT_DIR: conntrack direction
* @TYPE_CT_STATUS: conntrack status (bitmask subtype)
+ * @TYPE_ICMP6_TYPE: ICMPv6 type codes (integer subtype)
*/
enum datatypes {
TYPE_INVALID,
@@ -62,6 +63,7 @@ enum datatypes {
TYPE_CT_STATE,
TYPE_CT_DIR,
TYPE_CT_STATUS,
+ TYPE_ICMP6_TYPE,
__TYPE_MAX
};
#define TYPE_MAX (__TYPE_MAX - 1)
diff --git a/include/payload.h b/include/payload.h
index 8f5398b..c9cc84f 100644
--- a/include/payload.h
+++ b/include/payload.h
@@ -197,6 +197,18 @@ enum icmp_hdr_fields {
ICMPHDR_MTU,
};
+enum icmp6_hdr_fields {
+ ICMP6HDR_INVALID,
+ ICMP6HDR_TYPE,
+ ICMP6HDR_CODE,
+ ICMP6HDR_CHECKSUM,
+ ICMP6HDR_PPTR,
+ ICMP6HDR_MTU,
+ ICMP6HDR_ID,
+ ICMP6HDR_SEQ,
+ ICMP6HDR_MAXDELAY,
+};
+
enum ip6_hdr_fields {
IP6HDR_INVALID,
IP6HDR_VERSION,
@@ -207,6 +219,7 @@ enum ip6_hdr_fields {
IP6HDR_HOPLIMIT,
IP6HDR_SADDR,
IP6HDR_DADDR,
+ IP6HDR_PROTOCOL,
};
enum ah_hdr_fields {
@@ -278,6 +291,7 @@ extern const struct payload_desc payload_udplite;
extern const struct payload_desc payload_tcp;
extern const struct payload_desc payload_dccp;
extern const struct payload_desc payload_sctp;
+extern const struct payload_desc payload_icmp6;
extern const struct payload_desc payload_ip;
extern const struct payload_desc payload_ip6;
diff --git a/src/parser.y b/src/parser.y
index 91981e9..ff8de47 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -232,6 +232,10 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token NEXTHDR "nexthdr"
%token HOPLIMIT "hoplimit"
+%token ICMP6 "icmpv6"
+%token PPTR "param-problem"
+%token MAXDELAY "max-delay"
+
%token AH "ah"
%token RESERVED "reserved"
%token SPI "spi"
@@ -420,9 +424,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <expr> ip_hdr_expr icmp_hdr_expr
%destructor { expr_free($$); } ip_hdr_expr icmp_hdr_expr
%type <val> ip_hdr_field icmp_hdr_field
-%type <expr> ip6_hdr_expr
-%destructor { expr_free($$); } ip6_hdr_expr
-%type <val> ip6_hdr_field
+%type <expr> ip6_hdr_expr icmp6_hdr_expr
+%destructor { expr_free($$); } ip6_hdr_expr icmp6_hdr_expr
+%type <val> ip6_hdr_field icmp6_hdr_field
%type <expr> auth_hdr_expr esp_hdr_expr comp_hdr_expr
%destructor { expr_free($$); } auth_hdr_expr esp_hdr_expr comp_hdr_expr
%type <val> auth_hdr_field esp_hdr_field comp_hdr_field
@@ -1337,6 +1341,7 @@ payload_expr : payload_raw_expr
| ip_hdr_expr
| icmp_hdr_expr
| ip6_hdr_expr
+ | icmp6_hdr_expr
| auth_hdr_expr
| esp_hdr_expr
| comp_hdr_expr
@@ -1454,6 +1459,28 @@ ip6_hdr_field : VERSION { $$ = IP6HDR_VERSION; }
| SADDR { $$ = IP6HDR_SADDR; }
| DADDR { $$ = IP6HDR_DADDR; }
;
+icmp6_hdr_expr : ICMP6 icmp6_hdr_field
+ {
+ $$ = payload_expr_alloc(&@$, &payload_icmp6, $2);
+ }
+ | ICMP6
+ {
+ uint8_t data = IPPROTO_ICMPV6;
+ $$ = constant_expr_alloc(&@$, &inet_protocol_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(data) * BITS_PER_BYTE, &data);
+ }
+ ;
+
+icmp6_hdr_field : TYPE { $$ = ICMP6HDR_TYPE; }
+ | CODE { $$ = ICMP6HDR_CODE; }
+ | CHECKSUM { $$ = ICMP6HDR_CHECKSUM; }
+ | PPTR { $$ = ICMP6HDR_PPTR; }
+ | MTU { $$ = ICMP6HDR_MTU; }
+ | ID { $$ = ICMP6HDR_ID; }
+ | SEQUENCE { $$ = ICMP6HDR_SEQ; }
+ | MAXDELAY { $$ = ICMP6HDR_MAXDELAY; }
+ ;
auth_hdr_expr : AH auth_hdr_field
{
diff --git a/src/payload.c b/src/payload.c
index 942bc85..bce32fb 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -795,6 +795,63 @@ const struct payload_desc payload_ip = {
};
/*
+ * ICMPv6
+ */
+
+#include <netinet/icmp6.h>
+
+static const struct symbol_table icmp6_type_tbl = {
+ .symbols = {
+ SYMBOL("destination-unreachable", ICMP6_DST_UNREACH),
+ SYMBOL("packet-too-big", ICMP6_PACKET_TOO_BIG),
+ SYMBOL("time-exceeded", ICMP6_TIME_EXCEEDED),
+ SYMBOL("param-problem", ICMP6_PARAM_PROB),
+ SYMBOL("echo-request", ICMP6_ECHO_REQUEST),
+ SYMBOL("echo-reply", ICMP6_ECHO_REPLY),
+ SYMBOL("mld-listener-query", MLD_LISTENER_QUERY),
+ SYMBOL("mld-listener-report", MLD_LISTENER_REPORT),
+ SYMBOL("mld-listener-reduction", MLD_LISTENER_REDUCTION),
+ SYMBOL("nd-router-solicit", ND_ROUTER_SOLICIT),
+ SYMBOL("nd-router-advert", ND_ROUTER_ADVERT),
+ SYMBOL("nd-neighbor-solicit", ND_NEIGHBOR_SOLICIT),
+ SYMBOL("nd-neighbor-advert", ND_NEIGHBOR_ADVERT),
+ SYMBOL("nd-redirect", ND_REDIRECT),
+ SYMBOL("router-renumbering", ICMP6_ROUTER_RENUMBERING),
+ SYMBOL_LIST_END
+ },
+};
+
+static const struct datatype icmp6_type_type = {
+ .type = TYPE_ICMP6_TYPE,
+ .name = "icmpv6_type",
+ .desc = "ICMPv6 type",
+ .byteorder = BYTEORDER_BIG_ENDIAN,
+ .size = BITS_PER_BYTE,
+ .basetype = &integer_type,
+ .sym_tbl = &icmp6_type_tbl,
+};
+
+#define ICMP6HDR_FIELD(__name, __member) \
+ HDR_FIELD(__name, struct icmp6_hdr, __member)
+#define ICMP6HDR_TYPE(__name, __type, __member) \
+ HDR_TYPE(__name, __type, struct icmp6_hdr, __member)
+
+const struct payload_desc payload_icmp6 = {
+ .name = "icmpv6",
+ .base = PAYLOAD_BASE_TRANSPORT_HDR,
+ .templates = {
+ [ICMP6HDR_TYPE] = ICMP6HDR_TYPE("type", &icmp6_type_type, icmp6_type),
+ [ICMP6HDR_CODE] = ICMP6HDR_FIELD("code", icmp6_code),
+ [ICMP6HDR_CHECKSUM] = ICMP6HDR_FIELD("checksum", icmp6_cksum),
+ [ICMP6HDR_PPTR] = ICMP6HDR_FIELD("parameter-problem", icmp6_pptr),
+ [ICMP6HDR_MTU] = ICMP6HDR_FIELD("packet-too-big", icmp6_mtu),
+ [ICMP6HDR_ID] = ICMP6HDR_FIELD("id", icmp6_id),
+ [ICMP6HDR_SEQ] = ICMP6HDR_FIELD("sequence", icmp6_seq),
+ [ICMP6HDR_MAXDELAY] = ICMP6HDR_FIELD("max-delay", icmp6_maxdelay),
+ },
+};
+
+/*
* IPv6
*/
@@ -818,6 +875,7 @@ const struct payload_desc payload_ip6 = {
PAYLOAD_PROTO(IPPROTO_TCP, &payload_tcp),
PAYLOAD_PROTO(IPPROTO_DCCP, &payload_dccp),
PAYLOAD_PROTO(IPPROTO_SCTP, &payload_sctp),
+ PAYLOAD_PROTO(IPPROTO_ICMPV6, &payload_icmp6),
},
.templates = {
[IP6HDR_VERSION] = HDR_BITFIELD("version", &integer_type, 0, 4),
@@ -991,4 +1049,5 @@ static void __init payload_init(void)
datatype_register(&dccp_pkttype_type);
datatype_register(&arpop_type);
datatype_register(&ethertype_type);
+ datatype_register(&icmp6_type_type);
}
diff --git a/src/scanner.l b/src/scanner.l
index 7946e94..59e0aac 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -323,6 +323,10 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"nexthdr" { return NEXTHDR; }
"hoplimit" { return HOPLIMIT; }
+"icmpv6" { return ICMP6; }
+"param-problem" { return PPTR; }
+"max-delay" { return MAXDELAY; }
+
"ah" { return AH; }
"reserved" { return RESERVED; }
"spi" { return SPI; }