]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Add support for pkttype in meta expresion
authorAna Rey <anarey@gmail.com>
Tue, 5 Aug 2014 18:33:39 +0000 (20:33 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 24 Aug 2014 12:19:18 +0000 (14:19 +0200)
If you want to match the pkttype field of the skbuff, you have to
use the following syntax:

 nft add rule ip filter input meta pkttype PACKET_TYPE

where PACKET_TYPE can be: unicast, broadcast and multicast.

Joint work with Alvaro Neira Ayuso <alvaroneay@gmail.com>

Signed-off-by: Alvaro Neira Ayuso <alvaroneay@gmail.com>
Signed-off-by: Ana Rey <anarey@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/datatype.h
include/linux/netfilter/nf_tables.h
src/meta.c
src/parser.y
src/scanner.l

index 2c66e9d9702f488ac3ba4b641013fa9b96774bae..518226370e540205412a60c5bac2ea00652174d3 100644 (file)
@@ -35,6 +35,7 @@
  * @TYPE_CT_STATUS:    conntrack status (bitmask subtype)
  * @TYPE_ICMP6_TYPE:   ICMPv6 type codes (integer subtype)
  * @TYPE_CT_LABEL:     Conntrack Label (bitmask subtype)
+ * @TYPE_PKTTYPE:      packet type (integer subtype)
  */
 enum datatypes {
        TYPE_INVALID,
@@ -68,6 +69,7 @@ enum datatypes {
        TYPE_CT_STATUS,
        TYPE_ICMP6_TYPE,
        TYPE_CT_LABEL,
+       TYPE_PKTTYPE,
        __TYPE_MAX
 };
 #define TYPE_MAX               (__TYPE_MAX - 1)
index a5f8ec05f8a78cc9b80a7dfb38fe82aaa45550fa..d31bbcf071278e21e4af7c311055929a71a9a9c4 100644 (file)
@@ -535,6 +535,7 @@ enum nft_exthdr_attributes {
  * @NFT_META_L4PROTO: layer 4 protocol number
  * @NFT_META_BRI_IIFNAME: packet input bridge interface name
  * @NFT_META_BRI_OIFNAME: packet output bridge interface name
+ * @NFT_META_PKTTYPE: packet type (skb->pkt_type), special handling for loopback
  */
 enum nft_meta_keys {
        NFT_META_LEN,
@@ -556,6 +557,7 @@ enum nft_meta_keys {
        NFT_META_L4PROTO,
        NFT_META_BRI_IIFNAME,
        NFT_META_BRI_OIFNAME,
+       NFT_META_PKTTYPE,
 };
 
 /**
index 80f88ffbb7ad0ca0163cd8b7b0770b06a0587420..7b75caf7fbd9968a46d485484ae1c0130109cc94 100644 (file)
@@ -20,6 +20,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <linux/pkt_sched.h>
+#include <linux/if_packet.h>
 
 #include <nftables.h>
 #include <expression.h>
@@ -297,6 +298,57 @@ static const struct datatype gid_type = {
        .parse          = gid_type_parse,
 };
 
+static const struct symbol_table pkttype_type_tbl = {
+       .symbols        = {
+               SYMBOL("unicast", PACKET_HOST),
+               SYMBOL("broadcast", PACKET_BROADCAST),
+               SYMBOL("multicast", PACKET_MULTICAST),
+               SYMBOL_LIST_END,
+       },
+};
+
+static void pkttype_type_print(const struct expr *expr)
+{
+       return symbolic_constant_print(&pkttype_type_tbl, expr);
+}
+
+static struct error_record *pkttype_type_parse(const struct expr *sym,
+                                              struct expr **res)
+{
+       struct error_record *erec;
+       const struct symbolic_constant *s;
+
+       for (s = pkttype_type_tbl.symbols; s->identifier != NULL; s++) {
+               if (!strcmp(sym->identifier, s->identifier)) {
+                       *res = constant_expr_alloc(&sym->location, sym->dtype,
+                                                  sym->dtype->byteorder,
+                                                  sym->dtype->size,
+                                                  &s->value);
+                       return NULL;
+               }
+       }
+
+       *res = NULL;
+       erec = sym->dtype->basetype->parse(sym, res);
+       if (erec != NULL)
+               return erec;
+       if (*res)
+               return NULL;
+
+       return symbolic_constant_parse(sym, &pkttype_type_tbl, res);
+}
+
+static const struct datatype pkttype_type = {
+       .type           = TYPE_PKTTYPE,
+       .name           = "pkt_type",
+       .desc           = "packet type",
+       .byteorder      = BYTEORDER_HOST_ENDIAN,
+       .size           = BITS_PER_BYTE,
+       .basetype       = &integer_type,
+       .print          = pkttype_type_print,
+       .parse          = pkttype_type_parse,
+};
+
 static const struct meta_template meta_templates[] = {
        [NFT_META_LEN]          = META_TEMPLATE("length",    &integer_type,
                                                4 * 8, BYTEORDER_HOST_ENDIAN),
@@ -338,6 +390,9 @@ static const struct meta_template meta_templates[] = {
        [NFT_META_BRI_OIFNAME]  = META_TEMPLATE("obriport",  &string_type,
                                                IFNAMSIZ * BITS_PER_BYTE,
                                                BYTEORDER_HOST_ENDIAN),
+       [NFT_META_PKTTYPE]      = META_TEMPLATE("pkttype",  &pkttype_type,
+                                               BITS_PER_BYTE,
+                                               BYTEORDER_HOST_ENDIAN),
 };
 
 static void meta_expr_print(const struct expr *expr)
index 26d28793bd7681d446f1c05e8fdc8d3d6a6050da..f06a26513cc50bec6787267ba1822432220d804b 100644 (file)
@@ -325,6 +325,7 @@ static int monitor_lookup_event(const char *event)
 %token RTCLASSID               "rtclassid"
 %token IBRIPORT                        "ibriport"
 %token OBRIPORT                        "obriport"
+%token PKTTYPE                 "pkttype"
 
 %token CT                      "ct"
 %token DIRECTION               "direction"
@@ -1838,6 +1839,7 @@ meta_key_unqualified      :       MARK            { $$ = NFT_META_MARK; }
                        |       RTCLASSID       { $$ = NFT_META_RTCLASSID; }
                        |       IBRIPORT        { $$ = NFT_META_BRI_IIFNAME; }
                        |       OBRIPORT        { $$ = NFT_META_BRI_OIFNAME; }
+                       |       PKTTYPE         { $$ = NFT_META_PKTTYPE; }
                        ;
 
 meta_stmt              :       META    meta_key        SET     expr
index 4eec92f5f7db10e09b76503cf501db9bd30d6011..ca6db6e1625bd0230a57da25342bd72fa706a186 100644 (file)
@@ -415,6 +415,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "rtclassid"            { return RTCLASSID; }
 "ibriport"             { return IBRIPORT; }
 "obriport"             { return OBRIPORT; }
+"pkttype"              { return PKTTYPE; }
 
 "ct"                   { return CT; }
 "direction"            { return DIRECTION; }