summaryrefslogtreecommitdiffstats
path: root/src/proto.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-05-11 00:21:24 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2016-05-11 23:01:31 +0200
commit16fcc85c283537ea00357e2ca4bbb561c03bc65b (patch)
tree8ab5e756ee08dca26a10c3977679e5423e786d56 /src/proto.c
parent7fbbeb1f0db7718fbfedea4e50f69a54d1bfda70 (diff)
src: add dscp support
This supports both IPv4: # nft --debug=netlink add rule filter forward ip dscp cs1 counter ip filter forward [ payload load 1b @ network header + 1 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x000000fc ) ^ 0x00000000 ] [ cmp neq reg 1 0x00000080 ] [ counter pkts 0 bytes 0 ] And also IPv6, note that in this case we take two bytes from the payload: # nft --debug=netlink add rule ip6 filter input ip6 dscp cs4 counter ip6 filter input [ payload load 2b @ network header + 0 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x0000c00f ) ^ 0x00000000 ] [ cmp eq reg 1 0x00000008 ] [ counter pkts 0 bytes 0 ] Given the DSCP is split in two bytes, the less significant nibble of the first byte and the two most significant 2 bits of the second byte. The 8 bit traffic class in RFC2460 after the version field are used for DSCP (6 bit) and ECN (2 bit). Support for ECN comes in a follow up patch. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/proto.c')
-rw-r--r--src/proto.c48
1 files changed, 45 insertions, 3 deletions
diff --git a/src/proto.c b/src/proto.c
index fb774b16..4c65e1c3 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -512,6 +512,46 @@ const struct proto_desc proto_sctp = {
*/
#include <netinet/ip.h>
+
+static const struct symbol_table dscp_type_tbl = {
+ .symbols = {
+ SYMBOL("cs0", 0x00),
+ SYMBOL("cs1", 0x08),
+ SYMBOL("cs2", 0x10),
+ SYMBOL("cs3", 0x18),
+ SYMBOL("cs4", 0x20),
+ SYMBOL("cs5", 0x28),
+ SYMBOL("cs6", 0x30),
+ SYMBOL("cs7", 0x38),
+ SYMBOL("be", 0x00),
+ SYMBOL("af11", 0x0a),
+ SYMBOL("af12", 0x0c),
+ SYMBOL("af13", 0x0e),
+ SYMBOL("af21", 0x12),
+ SYMBOL("af22", 0x14),
+ SYMBOL("af23", 0x16),
+ SYMBOL("af31", 0x1a),
+ SYMBOL("af32", 0x1c),
+ SYMBOL("af33", 0x1e),
+ SYMBOL("af41", 0x22),
+ SYMBOL("af42", 0x24),
+ SYMBOL("af43", 0x26),
+ SYMBOL("ef", 0x2e),
+ SYMBOL_LIST_END
+ },
+};
+
+static const struct datatype dscp_type = {
+ .type = TYPE_DSCP,
+ .name = "dscp",
+ .desc = "Differentiated Services Code Point",
+ .byteorder = BYTEORDER_BIG_ENDIAN,
+ .size = 6,
+ .basetype = &integer_type,
+ .basefmt = "0x%.2Zx",
+ .sym_tbl = &dscp_type_tbl,
+};
+
#define IPHDR_FIELD(__name, __member) \
HDR_FIELD(__name, struct iphdr, __member)
#define IPHDR_ADDR(__name, __member) \
@@ -536,7 +576,7 @@ const struct proto_desc proto_ip = {
.templates = {
[IPHDR_VERSION] = HDR_BITFIELD("version", &integer_type, 0, 4),
[IPHDR_HDRLENGTH] = HDR_BITFIELD("hdrlength", &integer_type, 4, 4),
- [IPHDR_TOS] = IPHDR_FIELD("tos", tos),
+ [IPHDR_DSCP] = HDR_BITFIELD("dscp", &dscp_type, 8, 6),
[IPHDR_LENGTH] = IPHDR_FIELD("length", tot_len),
[IPHDR_ID] = IPHDR_FIELD("id", id),
[IPHDR_FRAG_OFF] = IPHDR_FIELD("frag-off", frag_off),
@@ -548,7 +588,7 @@ const struct proto_desc proto_ip = {
},
.format = {
.order = {
- IPHDR_SADDR, IPHDR_DADDR, IPHDR_TOS, IPHDR_TTL,
+ IPHDR_SADDR, IPHDR_DADDR, IPHDR_DSCP, IPHDR_TTL,
IPHDR_ID, IPHDR_PROTOCOL, IPHDR_LENGTH,
},
.filter = (1 << IPHDR_VERSION) | (1 << IPHDR_HDRLENGTH) |
@@ -642,6 +682,7 @@ const struct proto_desc proto_ip6 = {
},
.templates = {
[IP6HDR_VERSION] = HDR_BITFIELD("version", &integer_type, 0, 4),
+ [IP6HDR_DSCP] = HDR_BITFIELD("dscp", &dscp_type, 4, 6),
[IP6HDR_FLOWLABEL] = HDR_BITFIELD("flowlabel", &integer_type, 12, 20),
[IP6HDR_LENGTH] = IP6HDR_FIELD("length", payload_len),
[IP6HDR_NEXTHDR] = INET_PROTOCOL("nexthdr", struct ipv6hdr, nexthdr),
@@ -651,7 +692,7 @@ const struct proto_desc proto_ip6 = {
},
.format = {
.order = {
- IP6HDR_SADDR, IP6HDR_DADDR, IP6HDR_PRIORITY,
+ IP6HDR_SADDR, IP6HDR_DADDR, IP6HDR_DSCP,
IP6HDR_HOPLIMIT, IP6HDR_FLOWLABEL, IP6HDR_NEXTHDR,
IP6HDR_LENGTH,
},
@@ -881,4 +922,5 @@ static void __init proto_init(void)
datatype_register(&arpop_type);
datatype_register(&ethertype_type);
datatype_register(&icmp6_type_type);
+ datatype_register(&dscp_type);
}