diff options
author | Ana Rey <anarey@gmail.com> | 2014-08-05 20:33:39 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-08-24 14:19:18 +0200 |
commit | 97f0ffc9efa7a0c7ecfbbfacf1fb066a2a350ad8 (patch) | |
tree | 5d0ed6f3b7eac8bedf30abb7532c68474e8ccfd1 | |
parent | 6f285f202d6c41db1d9071c0964b5d062a522b4e (diff) |
src: Add support for pkttype in meta expresion
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>
-rw-r--r-- | include/datatype.h | 2 | ||||
-rw-r--r-- | include/linux/netfilter/nf_tables.h | 2 | ||||
-rw-r--r-- | src/meta.c | 55 | ||||
-rw-r--r-- | src/parser.y | 2 | ||||
-rw-r--r-- | src/scanner.l | 1 |
5 files changed, 62 insertions, 0 deletions
diff --git a/include/datatype.h b/include/datatype.h index 2c66e9d9..51822637 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -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) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index a5f8ec05..d31bbcf0 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -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, }; /** @@ -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) diff --git a/src/parser.y b/src/parser.y index 26d28793..f06a2651 100644 --- a/src/parser.y +++ b/src/parser.y @@ -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 diff --git a/src/scanner.l b/src/scanner.l index 4eec92f5..ca6db6e1 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -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; } |