Extend proto field expression to:
proto_field[{index}:{len}] = {func}
which allows to specify function/value on the part of the field via index
and value length (default is 1 - 1 byte). This rule is optional.
It was needed to keep of proto_field's copies in packet_dyn->fields
instead of original fields which allows to scpecify different functions
on the different parts of same field, also the copy of original
proto_field allows to set custom length/pkt_offset which makes such
field behave as virtual sub-field of the original one with different
length/pkt_offset but point to the same piece of header.
Signed-off-by: Vadim Kochan <[email protected]>
---
trafgen_parser.y | 96 +++++++++++++++++++++++++++++++++++++++++++++++---------
trafgen_proto.c | 27 +++++++---------
trafgen_proto.h | 8 +++--
3 files changed, 98 insertions(+), 33 deletions(-)
diff --git a/trafgen_parser.y b/trafgen_parser.y
index a1b8b0c..4d570e0 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -387,20 +387,30 @@ static void proto_add(enum proto_id pid)
static void proto_field_set(uint32_t fid)
{
+ memset(&field_expr, 0, sizeof(field_expr));
field_expr.field = proto_hdr_field_by_id(hdr, fid);
}
static void proto_field_func_setup(struct proto_field *field, struct
proto_field_func *func)
{
+ struct proto_field *field_copy;
struct packet_dyn *pkt_dyn;
- proto_hdr_field_func_add(field->hdr, field->id, func);
+ field_copy = xmalloc(sizeof(*field));
+ memcpy(field_copy, field, sizeof(*field));
+
+ field_copy->pkt_offset += func->offset;
+ if (func->len)
+ field_copy->len = func->len;
+
+ proto_field_func_add(field_copy, func);
pkt_dyn = &packet_dyn[packetd_last];
pkt_dyn->flen++;
pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
sizeof(struct proto_field *));
- pkt_dyn->fields[pkt_dyn->flen - 1] = field;
+
+ pkt_dyn->fields[pkt_dyn->flen - 1] = field_copy;
}
static void proto_field_expr_eval(void)
@@ -450,6 +460,19 @@ static void proto_field_expr_eval(void)
memset(&field_expr, 0, sizeof(field_expr));
}
+static void field_index_validate(struct proto_field *field, uint16_t index,
size_t len)
+{
+ if (field_expr.field->len <= index) {
+ yyerror("Invalid [index] parameter");
+ panic("Index (%u) is bigger than field's length (%zu)\n",
+ index, field->len);
+ }
+ if (len != 1 && len != 2 && len != 4) {
+ yyerror("Invalid [index:len] parameter");
+ panic("Invalid index length - 1,2 or 4 is only allowed\n");
+ }
+}
+
%}
%union {
@@ -718,6 +741,17 @@ proto
| tcp_proto { }
;
+field_expr
+ : '[' skip_white number skip_white ']'
+ { field_index_validate(field_expr.field, $3, 1);
+ field_expr.val.func.offset = $3;
+ field_expr.val.func.len = 1; }
+ | '[' skip_white number skip_white ':' skip_white number skip_white ']'
+ { field_index_validate(field_expr.field, $3, $7);
+ field_expr.val.func.offset = $3;
+ field_expr.val.func.len = $7; }
+ ;
+
field_value_expr
: number { field_expr.type = FIELD_EXPR_NUMB;
field_expr.val.number = $1; }
@@ -783,7 +817,9 @@ eth_field
| eth_type { proto_field_set(ETH_TYPE); }
eth_expr
- : eth_field skip_white '=' skip_white field_value_expr
+ : eth_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | eth_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
@@ -807,7 +843,9 @@ pause_field
;
pause_expr
- : pause_field skip_white '=' skip_white field_value_expr
+ : pause_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | pause_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
@@ -843,7 +881,9 @@ pfc_field
;
pfc_expr
- : pfc_field skip_white '=' skip_white field_value_expr
+ : pfc_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | pfc_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
@@ -875,7 +915,9 @@ vlan_field
;
vlan_expr
- : vlan_field skip_white '=' skip_white field_value_expr
+ : vlan_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | vlan_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_1Q
{ proto_hdr_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
@@ -910,7 +952,9 @@ mpls_field
;
mpls_expr
- : mpls_field skip_white '=' skip_white field_value_expr
+ : mpls_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | mpls_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
arp_proto
@@ -939,8 +983,13 @@ arp_field
;
arp_expr
- : arp_field skip_white '=' skip_white field_value_expr
+ : arp_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | arp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
+ | K_OPER field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_set(ARP_OPER);
+ proto_field_expr_eval(); }
| K_OPER skip_white '=' skip_white field_value_expr
{ proto_field_set(ARP_OPER);
proto_field_expr_eval(); }
@@ -985,7 +1034,9 @@ ip4_field
;
ip4_expr
- : ip4_field skip_white '=' skip_white field_value_expr
+ : ip4_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | ip4_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_DF { proto_hdr_field_set_be16(hdr, IP4_DF, 1); }
| K_MF { proto_hdr_field_set_be16(hdr, IP4_MF, 1); }
@@ -1022,7 +1073,9 @@ ip6_field
;
ip6_expr
- : ip6_field skip_white '=' skip_white field_value_expr
+ : ip6_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | ip6_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
@@ -1050,7 +1103,9 @@ icmp4_field
;
icmp4_expr
- : icmp4_field skip_white '=' skip_white field_value_expr
+ : icmp4_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | icmp4_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_ECHO_REQUEST
{ proto_hdr_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
@@ -1079,8 +1134,13 @@ icmp6_field
;
icmp6_expr
- : icmp6_field skip_white '=' skip_white field_value_expr
+ : icmp6_field field_expr skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
+ | icmp6_field skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | K_TYPE field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_set(ICMPV6_TYPE);
+ proto_field_expr_eval(); }
| K_TYPE skip_white '=' skip_white field_value_expr
{ proto_field_set(ICMPV6_TYPE);
proto_field_expr_eval(); }
@@ -1115,7 +1175,9 @@ udp_field
;
udp_expr
- : udp_field skip_white '=' skip_white field_value_expr
+ : udp_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | udp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
@@ -1145,7 +1207,9 @@ tcp_field
;
tcp_expr
- : tcp_field skip_white '=' skip_white field_value_expr
+ : tcp_field field_expr skip_white '=' skip_white field_value_expr
+ { proto_field_expr_eval(); }
+ | tcp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_CWR { proto_hdr_field_set_be16(hdr, TCP_CWR, 1); }
| K_ECE { proto_hdr_field_set_be16(hdr, TCP_ECE, 1); }
@@ -1225,6 +1289,10 @@ void cleanup_packets(void)
for (i = 0; i < dlen; ++i) {
free(packet_dyn[i].cnt);
free(packet_dyn[i].rnd);
+
+ for (j = 0; j < packet_dyn[j].flen; j++)
+ xfree(packet_dyn[i].fields[j]);
+
free(packet_dyn[i].fields);
}
diff --git a/trafgen_proto.c b/trafgen_proto.c
index e2b80d4..88e0846 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -532,11 +532,11 @@ static inline uint32_t field_inc(struct proto_field
*field)
static void field_inc_func(struct proto_field *field)
{
if (field->len == 1) {
- proto_hdr_field_set_u8(field->hdr, field->id, field_inc(field));
+ proto_field_set_u8(field, field_inc(field));
} else if (field->len == 2) {
- proto_hdr_field_set_be16(field->hdr, field->id,
field_inc(field));
+ proto_field_set_be16(field, field_inc(field));
} else if (field->len == 4) {
- proto_hdr_field_set_be32(field->hdr, field->id,
field_inc(field));
+ proto_field_set_be32(field, field_inc(field));
} else if (field->len > 4) {
uint8_t *bytes = __proto_field_get_bytes(field);
@@ -554,14 +554,11 @@ static inline uint32_t field_rand(struct proto_field
*field)
static void field_rnd_func(struct proto_field *field)
{
if (field->len == 1) {
- proto_hdr_field_set_u8(field->hdr, field->id,
- (uint8_t) field_rand(field));
+ proto_field_set_u8(field, (uint8_t) field_rand(field));
} else if (field->len == 2) {
- proto_hdr_field_set_be16(field->hdr, field->id,
- (uint16_t) field_rand(field));
+ proto_field_set_be16(field, (uint16_t) field_rand(field));
} else if (field->len == 4) {
- proto_hdr_field_set_be32(field->hdr, field->id,
- (uint32_t) field_rand(field));
+ proto_field_set_be32(field, (uint32_t) field_rand(field));
} else if (field->len > 4) {
uint8_t *bytes = __proto_field_get_bytes(field);
uint32_t i;
@@ -571,11 +568,9 @@ static void field_rnd_func(struct proto_field *field)
}
}
-void proto_hdr_field_func_add(struct proto_hdr *hdr, uint32_t fid,
- struct proto_field_func *func)
+void proto_field_func_add(struct proto_field *field,
+ struct proto_field_func *func)
{
- struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
-
bug_on(!func);
field->func.update_field = func->update_field;
@@ -588,11 +583,11 @@ void proto_hdr_field_func_add(struct proto_hdr *hdr,
uint32_t fid,
if (func->type & PROTO_FIELD_FUNC_MIN)
field->func.val = func->min;
else if (field->len == 1)
- field->func.val = proto_hdr_field_get_u8(hdr, fid);
+ field->func.val = proto_field_get_u8(field);
else if (field->len == 2)
- field->func.val = proto_hdr_field_get_u16(hdr, fid);
+ field->func.val = proto_field_get_u16(field);
else if (field->len == 4)
- field->func.val = proto_hdr_field_get_u32(hdr, fid);
+ field->func.val = proto_field_get_u32(field);
else if (field->len > 4) {
uint8_t *bytes = __proto_field_get_bytes(field);
diff --git a/trafgen_proto.h b/trafgen_proto.h
index d4427e6..29d68db 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -66,7 +66,9 @@ struct proto_field_func {
uint32_t min;
uint32_t max;
int32_t inc;
+ uint16_t offset;
uint32_t val;
+ size_t len;
void (*update_field)(struct proto_field *field);
};
@@ -142,9 +144,6 @@ extern void proto_hdr_field_set_default_dev_ipv6(struct
proto_hdr *hdr, uint32_t
extern void proto_field_dyn_apply(struct proto_field *field);
-extern void proto_hdr_field_func_add(struct proto_hdr *hdr, uint32_t fid,
- struct proto_field_func *func);
-
extern struct proto_field *proto_hdr_field_by_id(struct proto_hdr *hdr,
uint32_t fid);
@@ -157,4 +156,7 @@ extern uint32_t proto_field_get_u32(struct proto_field
*field);
extern void proto_field_set_be16(struct proto_field *field, uint16_t val);
extern void proto_field_set_be32(struct proto_field *field, uint32_t val);
+extern void proto_field_func_add(struct proto_field *field,
+ struct proto_field_func *func);
+
#endif /* TRAFGEN_PROTO_H */
--
2.10.2
--
You received this message because you are subscribed to the Google Groups
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.