diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 126 | ||||
-rw-r--r-- | filter/filter.c | 160 |
2 files changed, 213 insertions, 73 deletions
diff --git a/filter/config.Y b/filter/config.Y index 84644370..8b5f01e9 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -109,12 +109,59 @@ f_new_pair_set(int fa, int ta, int fb, int tb) static struct f_tree * f_new_tlv_item(u32 type, u32 v1) { - debug("f_new_tlv_item\n"); struct f_tree *t = f_new_tree(); t->right = t; t->from.type = t->to.type = T_TLV; - // t->from.val.tlv = v1; - // t->to.val.tlv = v1; + struct tlv v; + v.type = type; + switch (type) { + case TLV_UDP_DEST_PORT: + v.u.udp_dest_port = v1; + break; + default: + // FIXME error + break; + } + t->from.val.tlv = v; + t->to.val.tlv = v; + return t; +} + +static struct f_tree * +f_new_tlv_remote_ep(u32 asn, struct f_val ep) +{ + struct f_tree *t = f_new_tree(); + t->right = t; + t->from.type = t->to.type = T_TLV; + struct tlv v; + v.type = TLV_REMOTE_ENDPOINT; + v.u.remote_endpoint.asn = asn; + v.u.remote_endpoint.ip = ep.val.ip; + t->from.val.tlv = v; + t->to.val.tlv = v; + return t; +} + +int wg_key_from_base64(void *key, const char *base64); + +static struct f_tree * +f_new_tlv_encap(u32 type, const char *v1) +{ + struct f_tree *t = f_new_tree(); + t->right = t; + t->from.type = t->to.type = T_TLV; + struct tlv v; + v.type = TLV_ENCAPSULATION; + v.u.tunnel_encap.type = type; + // FIXME base64 decode v1 + int len = 32; + v.u.tunnel_encap.data = cfg_alloc(len); + v.u.tunnel_encap.length = len; + // FIXME + wg_key_from_base64(v.u.tunnel_encap.data, v1); +// memcpy(v.u.tunnel_encap.data, v1, len); + t->from.val.tlv = v; + t->to.val.tlv = v; return t; } @@ -327,62 +374,6 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3) } static inline struct f_inst * -f_generate_tlv(u16 kind, struct f_inst *tv) -{ - struct f_inst *rv = NULL; - struct tlv tlv; - struct f_val *val; - u32 type; - - debug("f_generate_tlv\n"); - - if (tv->fi_code != FI_CONSTANT_INDIRECT) - cf_error("Can't operate with value of non-constant type in TLV: %d", tv->fi_code); - - val = tv->a1.p; - type = val->type; - - switch (kind) { - case TLV_WIREGUARD: { - if (type == T_STRING) { - tlv.u.peer = val->val.s; - } - else - cf_error("Can't operate with value of non-string type in TLV wireguard constructor"); - break; - } - case TLV_REMOTE_ENDPOINT: { - if (type == T_IP) { - tlv.u.remote_endpoint.ip = val->val.ip; - } - else - cf_error("Can't operate with value of non-IP type in TLV remote endpoint constructor"); - break; - } - case TLV_UDP_DEST_PORT: { - if (type == T_INT) { - tlv.u.udp_dest_port = val->val.i; - } - else - cf_error("Can't operate with value of non-integer type in TLV udp dest port constructor"); - break; - } - default: - cf_error("Invalid TLV kind in constructor"); - }; - - { - NEW_F_VAL; - rv = f_new_inst(FI_CONSTANT_INDIRECT); - rv->a1.p = val; - val->type = T_TLV; - val->val.tlv = tlv; - - return rv; - } -} - -static inline struct f_inst * f_generate_path_mask(struct f_path_mask *t) { for (struct f_path_mask *tt = t; tt; tt = tt->next) { @@ -486,6 +477,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH, EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, + TLV, TUNNEL_ENCAP, REMOTE_ENDPOINT, UDP_DEST_PORT, BT_ASSERT, BT_TEST_SUITE, FORMAT) %nonassoc THEN @@ -495,7 +487,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type <fda> dynamic_attr %type <fsa> static_attr %type <f> filter filter_body where_filter -%type <i> type break_command ec_kind tlv_kind +%type <i> type break_command ec_kind %type <i32> cnum %type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body tlv_item %type <trie> fprefix_set @@ -559,6 +551,7 @@ type: | CLIST { $$ = T_CLIST; } | ECLIST { $$ = T_ECLIST; } | LCLIST { $$ = T_LCLIST; } + | TLV { $$ = T_TLV; } | type SET { switch ($1) { case T_INT: @@ -568,6 +561,7 @@ type: case T_LC: case T_RD: case T_IP: + case T_TLV: $$ = T_SET; break; @@ -780,18 +774,16 @@ lc_item: { $$ = f_new_lc_item($2, $10, $4, $12, $6, $14); } ; -tlv_kind: - WIREGUARD { $$ = TLV_WIREGUARD; } - tlv_item: - '(' tlv_kind ',' term ')' { $$ = f_new_tlv_item($2, $4); } - -// | tlv_item + '(' TUNNEL_ENCAP ',' cnum ',' TEXT ')' { $$ = f_new_tlv_encap($4, $6); } + | '(' UDP_DEST_PORT ',' cnum ')' { $$ = f_new_tlv_item(TLV_UDP_DEST_PORT, $4); } + | '(' REMOTE_ENDPOINT ',' NUM ',' fipa ')' { $$ = f_new_tlv_remote_ep($4, $6); } set_item: pair_item | ec_item | lc_item + | tlv_item | set_atom { $$ = f_new_item($1, $1); } | set_atom DDOT set_atom { $$ = f_new_item($1, $3); } ; @@ -800,6 +792,7 @@ switch_item: pair_item | ec_item | lc_item + | tlv_item | switch_atom { $$ = f_new_item($1, $1); } | switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); } ; @@ -884,7 +877,6 @@ constructor: '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); } | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); } | '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); } - | '(' tlv_kind ',' term ')' { $$ = f_generate_tlv($2, $4); } | bgp_path { $$ = f_generate_path_mask($1); } ; diff --git a/filter/filter.c b/filter/filter.c index 299e616e..c2e7a44f 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -622,6 +622,147 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; #define BITFIELD_MASK(what) \ (1u << (what->a2.i >> 24)) + +static int +calc_tunnel_encap(struct f_tree *t, int *type) +{ + if (t == NULL) + return 0; + + if (t->from.type != T_TLV) { + debug("Not tlv %d\n", t->from.type); + return -1; + } + + struct tlv *tlv = &t->from.val.tlv; + int len = 0; + switch (tlv->type) { + case TLV_ENCAPSULATION: + /* + Header: + Tunnel Type (2 Octets) + Length (2 Octets) + Value (Variable) + + TLV: + Sub-TLV Type (1 Octet) + Sub-TLV Length (1 Octet) + Sub-TLV Value (Variable) + */ + len = 4 + 2 + tlv->u.tunnel_encap.length; + *type = tlv->u.tunnel_encap.type; + break; + case TLV_UDP_DEST_PORT: + /* + Sub-TLV Type (1 Octet) + Sub-TLV Length (1 Octet) + Sub-TLV Value (2 Octets) + */ + len = 4; + break; + case TLV_REMOTE_ENDPOINT: + /* + Sub-TLV Type (1 Octet) + Sub-TLV Length (1 Octet) + Sub-TLV Value (10 or 22 Octets) + */ + if (ipa_is_ip4(tlv->u.remote_endpoint.ip)) + len = 2 + 10; + else + len = 2 + 22; + break; + default: + /* Ignore unknown */ + len = 0; + break; + } + + return len + calc_tunnel_encap(t->left, type) + calc_tunnel_encap(t->right, type); +} + +static void * +build_tunnel_encap_rec(void *p, struct f_tree *t) +{ + if (t == NULL) + return p; + + if (t->from.type != T_TLV) { + debug("Not tlv %d\n", t->from.type); + return p; + } + + struct tlv *tlv = &t->from.val.tlv; + switch (tlv->type) { + case TLV_ENCAPSULATION: + /* + TLV: + Sub-TLV Type (1 Octet) + Sub-TLV Length (1 Octet) + Sub-TLV Value (Variable) + */ + put_u8(p, tlv->type); p++; + int len = tlv->u.tunnel_encap.length; + put_u8(p, len); p++; + memcpy(p, tlv->u.tunnel_encap.data, len); p+=len; + break; + case TLV_UDP_DEST_PORT: + /* + Sub-TLV Type (1 Octet) + Sub-TLV Length (1 Octet) + Sub-TLV Value (2 Octets) + */ + put_u8(p, tlv->type); p++; + put_u8(p, 2); p++; + put_u16(p, tlv->u.udp_dest_port); p+=2; + break; + case TLV_REMOTE_ENDPOINT: + /* + Sub-TLV Type (1 Octet) + Sub-TLV Length (1 Octet) + Sub-TLV Value (10 or 22 Octets) + */ + put_u8(p, tlv->type); p++; + if (ipa_is_ip4(tlv->u.remote_endpoint.ip)) { + put_u8(p, 10); p++; + put_u32(p, tlv->u.remote_endpoint.asn); p+=4; + put_u16(p, NET_IP4); p+=2; + put_ip4(p, ipa_to_ip4(tlv->u.remote_endpoint.ip)); p+=4; + } else { + put_u8(p, 22); p++; + put_u32(p, tlv->u.remote_endpoint.asn); p+=4; + put_u16(p, NET_IP6); p+=2; + put_ip6(p, ipa_to_ip6(tlv->u.remote_endpoint.ip)); p+=16; + } + break; + default: + /* Ignore unknown */ + break; + } + + return build_tunnel_encap_rec(build_tunnel_encap_rec(p, t->left), t->right); +} + +static struct adata * +build_tunnel_encap(struct f_tree *t, int type, int len) +{ + struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len); + ad->length = len; + void *p = ad->data; + + /* + Header: + Tunnel Type (2 Octets) + Length (2 Octets) + Value (Variable) + */ + + put_u16(p, type); p += 2; + put_u16(p, len - 4); p += 2; + build_tunnel_encap_rec(p, t); + return ad; +} + + /** * interpret * @what: filter to interpret @@ -1106,7 +1247,7 @@ interpret(struct f_inst *what) break; case EAF_TYPE_TUNNEL_ENCAP: res.type = T_TLV; - runtime("FIXME Tunnel Encapsulation in e,a"); + runtime( "Getting tunnel encap attribute is not supported" ); break; default: bug("Unknown type in e,a"); @@ -1200,11 +1341,18 @@ interpret(struct f_inst *what) l->attrs[0].u.data = 0; break; case EAF_TYPE_TUNNEL_ENCAP: - if (v1.type != T_TLV) - runtime( "Setting tunnel encap attribute to non-tlv value" ); - debug( "FIXME tunnel encapsulation in e,S" ); - l->attrs[0].u.ptr = v1.val.ad; - break; + { + if (v1.type != T_SET) + runtime( "Setting tunnel encap attribute to non-tlv value %d", v1.type ); + int type = 0; + int len = calc_tunnel_encap(v1.val.t, &type); + if (len <= 0) + runtime( "Empty tunnel encapsulation" ); + else if (type <= 0 || type > 65535) + runtime( "Invalid tunnel encapsulation type: %d (0 < type <= 65535)", type ); + l->attrs[0].u.ptr = build_tunnel_encap(v1.val.t, type, len); + break; + } default: bug("Unknown type in e,S"); } |