]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Add icmpv6 support
authorEric Leblond <eric@regit.org>
Sun, 28 Jul 2013 22:30:56 +0000 (00:30 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 31 Jul 2013 17:27:25 +0000 (19:27 +0200)
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>
include/datatype.h
include/payload.h
src/parser.y
src/payload.c
src/scanner.l

index 053fbd938e90edba6eb02266be0abd6832d87dc6..239d5ea5718bcf1540abea45495d6255494f2837 100644 (file)
@@ -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)
index 8f5398b7ceaf8f737f7607e9bd722c961196c70e..c9cc84f3d7a2904ea0fcc2d554c7fa9fb0989313 100644 (file)
@@ -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;
index 91981e9a0d73373693de85a4c21d0846815ddc53..ff8de47f8b7a02c1ada0b899f415cf5980720191 100644 (file)
@@ -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
                        {
index 942bc8574aa16f3730a1d9ec1824572ad4a2a6c6..bce32fbc850e04aac715ac52fa0c54897794ca2c 100644 (file)
@@ -794,6 +794,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);
 }
index 7946e94fa777a6d23fdd97d6400eadf9e74d6b71..59e0aac734d4b39d91e4419f325159289d504f0e 100644 (file)
@@ -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; }