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 <vadi...@gmail.com> --- 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 netsniff-ng+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.