summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/exthdr.h9
-rw-r--r--include/headers.h12
-rw-r--r--src/exthdr.c23
-rw-r--r--src/parser_bison.y26
-rw-r--r--src/scanner.l4
5 files changed, 71 insertions, 3 deletions
diff --git a/include/exthdr.h b/include/exthdr.h
index 06bf6285..32f99c9c 100644
--- a/include/exthdr.h
+++ b/include/exthdr.h
@@ -57,6 +57,14 @@ enum rt2_hdr_fields {
RT2HDR_ADDR,
};
+enum rt4_hdr_fields {
+ RT4HDR_INVALID,
+ RT4HDR_LASTENT,
+ RT4HDR_FLAGS,
+ RT4HDR_TAG,
+ RT4HDR_SID_1,
+};
+
enum frag_hdr_fields {
FRAGHDR_INVALID,
FRAGHDR_NEXTHDR,
@@ -87,6 +95,7 @@ extern const struct exthdr_desc exthdr_hbh;
extern const struct exthdr_desc exthdr_rt;
extern const struct exthdr_desc exthdr_rt0;
extern const struct exthdr_desc exthdr_rt2;
+extern const struct exthdr_desc exthdr_rt4;
extern const struct exthdr_desc exthdr_frag;
extern const struct exthdr_desc exthdr_dst;
extern const struct exthdr_desc exthdr_mh;
diff --git a/include/headers.h b/include/headers.h
index 469d6740..3d564deb 100644
--- a/include/headers.h
+++ b/include/headers.h
@@ -112,6 +112,18 @@ struct ip6_mh {
uint8_t data[0];
};
+/* Type 4 Routing header - well known as srh */
+struct ip6_rt4 {
+ uint8_t ip6r4_nxt; /* next header */
+ uint8_t ip6r4_len; /* length in units of 8 octets */
+ uint8_t ip6r4_type; /* always zero */
+ uint8_t ip6r4_segleft; /* segments left */
+ uint8_t ip6r4_last_entry; /* last entry */
+ uint8_t ip6r4_flags; /* flags */
+ uint16_t ip6r4_tag; /* tag */
+ struct in6_addr ip6r4_segments[0]; /* SID list */
+};
+
/* RFC 3775 */
#define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */
#define IP6_MH_TYPE_HOTI 1 /* HOTI Message */
diff --git a/src/exthdr.c b/src/exthdr.c
index 3757f335..cbe0da86 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -101,6 +101,9 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
case 2:
expr->exthdr.op = NFT_EXTHDR_OP_RT2;
break;
+ case 4:
+ expr->exthdr.op = NFT_EXTHDR_OP_RT4;
+ break;
}
}
return expr;
@@ -165,6 +168,8 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
expr->exthdr.desc = &exthdr_rt0;
else if (op == NFT_EXTHDR_OP_RT2)
expr->exthdr.desc = &exthdr_rt2;
+ else if (op == NFT_EXTHDR_OP_RT4)
+ expr->exthdr.desc = &exthdr_rt4;
else if (type < array_size(exthdr_protocols))
expr->exthdr.desc = exthdr_protocols[type];
@@ -274,6 +279,24 @@ const struct exthdr_desc exthdr_rt0 = {
},
};
+#define RT4_FIELD(__name, __member, __dtype) \
+ HDR_TEMPLATE(__name, __dtype, struct ip6_rt4, __member)
+
+const struct exthdr_desc exthdr_rt4 = {
+ .name = "srh",
+ .type = IPPROTO_ROUTING,
+ .proto_key = 4,
+ .templates = {
+ [RT4HDR_LASTENT] = RT4_FIELD("last-entry", ip6r4_last_entry, &integer_type),
+ [RT4HDR_FLAGS] = RT4_FIELD("flags", ip6r4_flags, &integer_type),
+ [RT4HDR_TAG] = RT4_FIELD("tag", ip6r4_tag, &integer_type),
+ [RT4HDR_SID_1] = RT4_FIELD("sid[1]", ip6r4_segments[0], &ip6addr_type),
+ [RT4HDR_SID_1 + 1] = RT4_FIELD("sid[1]", ip6r4_segments[0], &ip6addr_type),
+ // ...
+ },
+};
+
+
#define RT_FIELD(__name, __member, __dtype) \
HDR_TEMPLATE(__name, __dtype, struct ip6_rthdr, __member)
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 2ccaf9ab..5f84d794 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -364,8 +364,12 @@ int nft_lex(void *, void *, void *);
%token RT "rt"
%token RT0 "rt0"
%token RT2 "rt2"
+%token RT4 "srh"
%token SEG_LEFT "seg-left"
%token ADDR "addr"
+%token LAST_ENT "last-entry"
+%token TAG "tag"
+%token SID "sid"
%token HBH "hbh"
@@ -674,9 +678,9 @@ int nft_lex(void *, void *, void *);
%type <expr> hbh_hdr_expr frag_hdr_expr dst_hdr_expr
%destructor { expr_free($$); } hbh_hdr_expr frag_hdr_expr dst_hdr_expr
%type <val> hbh_hdr_field frag_hdr_field dst_hdr_field
-%type <expr> rt_hdr_expr rt0_hdr_expr rt2_hdr_expr
-%destructor { expr_free($$); } rt_hdr_expr rt0_hdr_expr rt2_hdr_expr
-%type <val> rt_hdr_field rt0_hdr_field rt2_hdr_field
+%type <expr> rt_hdr_expr rt0_hdr_expr rt2_hdr_expr rt4_hdr_expr
+%destructor { expr_free($$); } rt_hdr_expr rt0_hdr_expr rt2_hdr_expr rt4_hdr_expr
+%type <val> rt_hdr_field rt0_hdr_field rt2_hdr_field rt4_hdr_field
%type <expr> mh_hdr_expr
%destructor { expr_free($$); } mh_hdr_expr
%type <val> mh_hdr_field
@@ -3921,6 +3925,7 @@ exthdr_expr : hbh_hdr_expr
| rt_hdr_expr
| rt0_hdr_expr
| rt2_hdr_expr
+ | rt4_hdr_expr
| frag_hdr_expr
| dst_hdr_expr
| mh_hdr_expr
@@ -3969,6 +3974,21 @@ rt2_hdr_expr : RT2 rt2_hdr_field
rt2_hdr_field : ADDR { $$ = RT2HDR_ADDR; }
;
+rt4_hdr_expr : RT4 rt4_hdr_field
+ {
+ $$ = exthdr_expr_alloc(&@$, &exthdr_rt4, $2);
+ }
+ ;
+
+rt4_hdr_field : LAST_ENT { $$ = RT4HDR_LASTENT; }
+ | FLAGS { $$ = RT4HDR_FLAGS; }
+ | TAG { $$ = RT4HDR_TAG; }
+ | SID '[' NUM ']'
+ {
+ $$ = RT4HDR_SID_1 + $3 - 1;
+ }
+ ;
+
frag_hdr_expr : FRAG frag_hdr_field
{
$$ = exthdr_expr_alloc(&@$, &exthdr_frag, $2);
diff --git a/src/scanner.l b/src/scanner.l
index ab10738b..1d8e8ba0 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -456,8 +456,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"rt" { return RT; }
"rt0" { return RT0; }
"rt2" { return RT2; }
+"srh" { return RT4; }
"seg-left" { return SEG_LEFT; }
"addr" { return ADDR; }
+"last-entry" { return LAST_ENT; }
+"tag" { return TAG; }
+"sid" { return SID; }
"hbh" { return HBH; }