diff options
-rw-r--r-- | trafgen_lexer.l | 24 | ||||
-rw-r--r-- | trafgen_parser.y | 193 |
2 files changed, 217 insertions, 0 deletions
diff --git a/trafgen_lexer.l b/trafgen_lexer.l index cf67c74..da072e1 100644 --- a/trafgen_lexer.l +++ b/trafgen_lexer.l @@ -239,6 +239,29 @@ ip6_addr ({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60}) "win"|"window" { return K_WINDOW; } "urgptr" { return K_URG_PTR; } + /* DNS */ +"qr" { return K_QR; } +"aa"|"aanswer" { return K_AANSWER; } +"trunc" { return K_TRUNC; } +"ravail" { return K_RAVAIL; } +"rdesired" { return K_RDESIRED; } +"zero" { return K_ZERO; } +"rc"|"rcode" { return K_RCODE; } +"qdcount" { return K_QDCOUNT; } +"ancount" { return K_ANCOUNT; } +"nscount" { return K_NSCOUNT; } +"arcount" { return K_ARCOUNT; } +"name" { return K_NAME; } +"class" { return K_CLASS; } +"data" { return K_DATA; } +"qry"|"query" { return K_QUERY; } +"ans"|"answer" { return K_ANSWER; } +"auth" { return K_AUTH; } +"add" { return K_ADD; } +"ns" { return K_NS; } +"cname" { return K_CNAME; } +"ptr" { return K_PTR; } + "eth" { return K_ETH; } "pause" { return K_PAUSE; } "pfc" { return K_PFC; } @@ -251,6 +274,7 @@ ip6_addr ({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60}) "icmp6"|"icmpv6" { return K_ICMP6; } "udp" { return K_UDP; } "tcp" { return K_TCP; } +"dns" { return K_DNS; } [ ]*"-"[ ]* { return '-'; } [ ]*"+"[ ]* { return '+'; } diff --git a/trafgen_parser.y b/trafgen_parser.y index b4eedea..656c4f6 100644 --- a/trafgen_parser.y +++ b/trafgen_parser.y @@ -31,6 +31,7 @@ #include "trafgen_l2.h" #include "trafgen_l3.h" #include "trafgen_l4.h" +#include "trafgen_l7.h" #include "built_in.h" #include "die.h" #include "str.h" @@ -80,6 +81,8 @@ enum field_expr_type_t { FIELD_EXPR_INC = 1 << 4, FIELD_EXPR_RND = 1 << 5, FIELD_EXPR_OFFSET = 1 << 6, + FIELD_EXPR_STRING = 1 << 7, + FIELD_EXPR_FQDN = 1 << 8, }; struct proto_field_expr { @@ -91,6 +94,7 @@ struct proto_field_expr { struct in6_addr ip6_addr; long long int number; uint8_t mac[256]; + char *str; struct proto_field_func func; } val; }; @@ -434,6 +438,14 @@ static void proto_field_expr_eval(void) panic("Invalid value length %zu, can be 1,2 or 4\n", field->len); } else if (field_expr.type & FIELD_EXPR_MAC) { proto_field_set_bytes(field, field_expr.val.mac, 6); + } else if (field_expr.type & FIELD_EXPR_FQDN) { + char *fqdn = str2fqdn(field_expr.val.str); + proto_field_set_bytes(field, (uint8_t *) fqdn, strlen(fqdn) + 1); + xfree(field_expr.val.str); + xfree(fqdn); + } else if (field_expr.type & FIELD_EXPR_STRING) { + proto_field_set_string(field, field_expr.val.str); + xfree(field_expr.val.str); } else if (field_expr.type & FIELD_EXPR_IP4_ADDR) { proto_field_set_u32(field, field_expr.val.ip4_addr.s_addr); } else if (field_expr.type & FIELD_EXPR_IP6_ADDR) { @@ -472,6 +484,19 @@ static void field_index_validate(struct proto_field *field, uint16_t index, size } } +static void proto_push_sub_hdr(uint32_t id) +{ + hdr = proto_hdr_push_sub_header(hdr, id); +} + +static void proto_pop_sub_hdr(void) +{ + if (hdr->ops->header_finish) + hdr->ops->header_finish(hdr); + + hdr = hdr->parent; +} + %} %union { @@ -498,6 +523,10 @@ static void field_index_validate(struct proto_field *field, uint16_t index, size %token K_ADDR K_MTU +%token K_QR K_AANSWER K_TRUNC K_RAVAIL K_RDESIRED K_ZERO K_RCODE K_QDCOUNT K_ANCOUNT K_NSCOUNT K_ARCOUNT +%token K_QUERY K_ANSWER K_AUTH K_ADD +%token K_NAME K_CLASS K_DATA K_NS K_CNAME K_PTR + %token K_ETH %token K_PAUSE %token K_PFC @@ -506,6 +535,7 @@ static void field_index_validate(struct proto_field *field, uint16_t index, size %token K_IP4 K_IP6 %token K_ICMP4 K_ICMP6 %token K_UDP K_TCP +%token K_DNS %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^' @@ -738,6 +768,7 @@ proto | icmpv6_proto { } | udp_proto { } | tcp_proto { } + | dns_proto { } ; field_expr @@ -758,6 +789,9 @@ field_value_expr field_expr.val.number = $1; } | mac { field_expr.type |= FIELD_EXPR_MAC; memcpy(field_expr.val.mac, $1, sizeof(field_expr.val.mac)); } + | string { field_expr.type |= FIELD_EXPR_STRING; + field_expr.val.str = xstrdup($1 + 1); + field_expr.val.str[strlen($1 + 1) - 1] = '\0'; } | ip4_addr { field_expr.type |= FIELD_EXPR_IP4_ADDR; field_expr.val.ip4_addr = $1; } | ip6_addr { field_expr.type |= FIELD_EXPR_IP6_ADDR; @@ -1229,6 +1263,157 @@ tcp : K_TCP { proto_add(PROTO_TCP); } ; +dns_proto + : dns '(' dns_param_list ')' { } + ; + +dns_param_list + : { } + | dns_expr { } + | dns_expr delimiter dns_param_list { } + ; + +dns_field + : K_ID { proto_field_set(DNS_ID); } + | K_QR { proto_field_set(DNS_QR); } + | K_OPER { proto_field_set(DNS_OPCODE); } + | K_AANSWER { proto_field_set(DNS_AA); } + | K_TRUNC { proto_field_set(DNS_TC); } + | K_RDESIRED { proto_field_set(DNS_RD); } + | K_RAVAIL { proto_field_set(DNS_RA); } + | K_ZERO { proto_field_set(DNS_ZERO); } + | K_RCODE { proto_field_set(DNS_RCODE); } + | K_QDCOUNT { proto_field_set(DNS_QD_COUNT); } + | K_ANCOUNT { proto_field_set(DNS_AN_COUNT); } + | K_NSCOUNT { proto_field_set(DNS_NS_COUNT); } + | K_ARCOUNT { proto_field_set(DNS_AR_COUNT); } + ; + +dns_query + : K_QUERY { proto_push_sub_hdr(DNS_QUERY_HDR); } + ; + +dns_query_name + : K_NAME { proto_field_set(DNS_QUERY_NAME); } + ; + +dns_query_field + : K_TYPE { proto_field_set(DNS_QUERY_TYPE); } + | K_CLASS { proto_field_set(DNS_QUERY_CLASS); } + ; + +dns_query_expr + : dns_query_field field_expr skip_white '=' skip_white field_value_expr + { proto_field_expr_eval(); } + | dns_query_field skip_white '=' skip_white field_value_expr + { proto_field_expr_eval(); } + | dns_query_name field_expr skip_white '=' skip_white field_value_expr + { if (field_expr.type & FIELD_EXPR_STRING) + field_expr.type = FIELD_EXPR_FQDN; + proto_field_expr_eval(); } + | dns_query_name skip_white '=' skip_white field_value_expr + { if (field_expr.type & FIELD_EXPR_STRING) + field_expr.type = FIELD_EXPR_FQDN; + proto_field_expr_eval(); } + ; + +dns_query_param_list + : { } + | dns_query_expr { } + | dns_query_expr delimiter dns_query_param_list { } + ; + +dns_query_hdr + : dns_query '(' dns_query_param_list ')' { } + ; + +dns_rrecord + : K_ANSWER { proto_push_sub_hdr(DNS_ANSWER_HDR); } + | K_AUTH { proto_push_sub_hdr(DNS_AUTH_HDR); } + | K_ADD { proto_push_sub_hdr(DNS_ADD_HDR); } + ; + +dns_rrecord_name + : K_NAME { proto_field_set(DNS_RRECORD_NAME); } + ; + +dns_rrecord_data_addr + : ip4_addr + { proto_hdr_field_set_u32(hdr, DNS_RRECORD_DATA, $1.s_addr); + proto_hdr_field_set_be16(hdr, DNS_RRECORD_TYPE, 1); } + | ip6_addr + { proto_hdr_field_set_bytes(hdr, DNS_RRECORD_DATA, (uint8_t *)&$1.s6_addr, 16); + proto_hdr_field_set_be16(hdr, DNS_RRECORD_TYPE, 28); } + ; + +dns_rrecord_data_fqdn + : string + { char *str = xstrdup($1 + 1); + char *fqdn; + str[strlen($1 + 1) - 1] = '\0'; + fqdn = str2fqdn(str); + proto_hdr_field_set_bytes(hdr, DNS_RRECORD_DATA, (uint8_t *) fqdn, strlen(fqdn) + 1); + xfree(fqdn); } + ; + +dns_rrecord_data_expr + : K_ADDR '(' skip_white dns_rrecord_data_addr skip_white ')' + { } + | K_NS '(' skip_white dns_rrecord_data_fqdn skip_white ')' + { proto_hdr_field_set_be16(hdr, DNS_RRECORD_TYPE, 2); } + | K_CNAME '(' skip_white dns_rrecord_data_fqdn skip_white ')' + { proto_hdr_field_set_be16(hdr, DNS_RRECORD_TYPE, 5); } + | K_PTR '(' skip_white dns_rrecord_data_fqdn skip_white ')' + { proto_hdr_field_set_be16(hdr, DNS_RRECORD_TYPE, 12); } + ; + +dns_rrecord_field + : K_TYPE { proto_field_set(DNS_RRECORD_TYPE); } + | K_CLASS { proto_field_set(DNS_RRECORD_CLASS); } + | K_TTL { proto_field_set(DNS_RRECORD_TTL); } + | K_LEN { proto_field_set(DNS_RRECORD_LEN); } + | K_DATA { proto_field_set(DNS_RRECORD_DATA); } + ; + +dns_rrecord_expr + : dns_rrecord_field field_expr skip_white '=' skip_white field_value_expr + { proto_field_expr_eval(); } + | dns_rrecord_field skip_white '=' skip_white field_value_expr + { proto_field_expr_eval(); } + | dns_rrecord_name field_expr skip_white '=' skip_white field_value_expr + { if (field_expr.type & FIELD_EXPR_STRING) + field_expr.type = FIELD_EXPR_FQDN; + proto_field_expr_eval(); } + | dns_rrecord_name skip_white '=' skip_white field_value_expr + { if (field_expr.type & FIELD_EXPR_STRING) + field_expr.type = FIELD_EXPR_FQDN; + proto_field_expr_eval(); } + | dns_rrecord_data_expr + { } + ; + +dns_rrecord_param_list + : { } + | dns_rrecord_expr { } + | dns_rrecord_expr delimiter dns_rrecord_param_list { } + ; + +dns_rrecord_hdr + : dns_rrecord '(' dns_rrecord_param_list ')' { } + ; + +dns_expr + : dns_field field_expr skip_white '=' skip_white field_value_expr + { proto_field_expr_eval(); } + | dns_field skip_white '=' skip_white field_value_expr + { proto_field_expr_eval(); } + | dns_query_hdr { proto_pop_sub_hdr(); } + | dns_rrecord_hdr { proto_pop_sub_hdr(); } + ; + +dns + : K_DNS { proto_add(PROTO_DNS); } + ; %% static void finalize_packet(void) @@ -1281,9 +1466,17 @@ void cleanup_packets(void) for (j = 0; j < pkt->headers_count; j++) { struct proto_hdr *hdr = pkt->headers[j]; + int k; + + for (k = 0; k < hdr->sub_headers_count; k++) + xfree(hdr->sub_headers[k]); + + if (hdr->sub_headers) + xfree(hdr->sub_headers); if (hdr->fields) xfree(hdr->fields); + xfree(hdr); } } |