summaryrefslogtreecommitdiff
path: root/trafgen_parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'trafgen_parser.y')
-rw-r--r--trafgen_parser.y611
1 files changed, 611 insertions, 0 deletions
diff --git a/trafgen_parser.y b/trafgen_parser.y
new file mode 100644
index 0000000..ece3b25
--- /dev/null
+++ b/trafgen_parser.y
@@ -0,0 +1,611 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * By Daniel Borkmann <daniel@netsniff-ng.org>
+ * Copyright 2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
+ * Swiss federal institute of technology (ETH Zurich)
+ * Subject to the GPL, version 2.
+ */
+
+/* yaac-func-prefix: yy */
+
+%{
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <libgen.h>
+
+#include "xmalloc.h"
+#include "trafgen_parser.tab.h"
+#include "trafgen_conf.h"
+#include "built_in.h"
+#include "die.h"
+#include "csum.h"
+#include "xutils.h"
+
+#define YYERROR_VERBOSE 0
+#define YYDEBUG 0
+#define YYENABLE_NLS 1
+#define YYLTYPE_IS_TRIVIAL 1
+#define ENABLE_NLS 1
+
+extern FILE *yyin;
+extern int yylex(void);
+extern void yyerror(const char *);
+extern int yylineno;
+extern char *yytext;
+
+extern struct packet *packets;
+extern size_t plen;
+
+#define packet_last (plen - 1)
+
+#define payload_last (packets[packet_last].len - 1)
+
+extern struct packet_dyn *packet_dyn;
+extern size_t dlen;
+
+#define packetd_last (dlen - 1)
+
+#define packetdc_last (packet_dyn[packetd_last].clen - 1)
+#define packetdr_last (packet_dyn[packetd_last].rlen - 1)
+#define packetds_last (packet_dyn[packetd_last].slen - 1)
+
+static int our_cpu, min_cpu = -1, max_cpu = -1;
+
+static inline int test_ignore(void)
+{
+ if (min_cpu < 0 && max_cpu < 0)
+ return 0;
+ else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
+ return 0;
+ else
+ return 1;
+}
+
+static inline int has_dynamic_elems(struct packet_dyn *p)
+{
+ return (p->rlen + p->slen + p->clen);
+}
+
+static inline void __init_new_packet_slot(struct packet *slot)
+{
+ slot->payload = NULL;
+ slot->len = 0;
+}
+
+static inline void __init_new_counter_slot(struct packet_dyn *slot)
+{
+ slot->cnt = NULL;
+ slot->clen = 0;
+}
+
+static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
+{
+ slot->rnd = NULL;
+ slot->rlen = 0;
+}
+
+static inline void __init_new_csum_slot(struct packet_dyn *slot)
+{
+ slot->csum = NULL;
+ slot->slen = 0;
+}
+
+static inline void __setup_new_counter(struct counter *c, uint8_t start,
+ uint8_t stop, uint8_t stepping,
+ int type)
+{
+ c->min = start;
+ c->max = stop;
+ c->inc = stepping;
+ c->val = (type == TYPE_INC) ? start : stop;
+ c->off = payload_last;
+ c->type = type;
+}
+
+static inline void __setup_new_randomizer(struct randomizer *r)
+{
+ r->off = payload_last;
+}
+
+static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
+ enum csum which)
+{
+ s->off = payload_last - 1;
+ s->from = from;
+ s->to = to;
+ s->which = which;
+}
+
+static void realloc_packet(void)
+{
+ if (test_ignore())
+ return;
+
+ plen++;
+ packets = xrealloc(packets, 1, plen * sizeof(*packets));
+
+ __init_new_packet_slot(&packets[packet_last]);
+
+ dlen++;
+ packet_dyn = xrealloc(packet_dyn, 1, dlen * sizeof(*packet_dyn));
+
+ __init_new_counter_slot(&packet_dyn[packetd_last]);
+ __init_new_randomizer_slot(&packet_dyn[packetd_last]);
+ __init_new_csum_slot(&packet_dyn[packetd_last]);
+}
+
+static void set_byte(uint8_t val)
+{
+ struct packet *pkt = &packets[packet_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len++;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+ pkt->payload[payload_last] = val;
+}
+
+static void set_multi_byte(uint8_t *s, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; ++i)
+ set_byte(s[i]);
+}
+
+static void set_fill(uint8_t val, size_t len)
+{
+ size_t i;
+ struct packet *pkt = &packets[packet_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len += len;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+ for (i = 0; i < len; ++i)
+ pkt->payload[payload_last - i] = val;
+}
+
+static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
+{
+ struct packet *pkt = &packets[packet_last];
+ struct packet_dyn *pktd = &packet_dyn[packetd_last];
+
+ pkt->len += 2;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+
+ pktd->slen++;
+ pktd->csum = xrealloc(pktd->csum, 1, pktd->slen * sizeof(struct csum16));
+
+ __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
+}
+
+static void __set_csum16_static(size_t from, size_t to, enum csum which)
+{
+ struct packet *pkt = &packets[packet_last];
+ uint16_t sum;
+ uint8_t *psum;
+
+ sum = htons(calc_csum(pkt->payload + from, to - from, 0));
+ psum = (uint8_t *) &sum;
+
+ set_byte(psum[0]);
+ set_byte(psum[1]);
+}
+
+static void set_csum16(size_t from, size_t to, enum csum which)
+{
+ int make_it_dynamic = 0;
+ struct packet *pkt = &packets[packet_last];
+ struct packet_dyn *pktd = &packet_dyn[packetd_last];
+
+ if (test_ignore())
+ return;
+
+ if (to < from) {
+ size_t tmp = to;
+
+ to = from;
+ from = tmp;
+ }
+
+ bug_on(!(from < to));
+
+ if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
+ make_it_dynamic = 1;
+
+ if (has_dynamic_elems(pktd) || make_it_dynamic)
+ __set_csum16_dynamic(from, to, which);
+ else
+ __set_csum16_static(from, to, which);
+}
+
+static void set_rnd(size_t len)
+{
+ size_t i;
+ struct packet *pkt = &packets[packet_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len += len;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+ for (i = 0; i < len; ++i)
+ pkt->payload[payload_last - i] = (uint8_t) rand();
+}
+
+static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
+{
+ size_t i;
+ struct packet *pkt = &packets[packet_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len += len;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+ for (i = 0; i < len; ++i) {
+ off_t off = len - 1 - i;
+
+ pkt->payload[payload_last - off] = start;
+ start += stepping;
+ }
+}
+
+static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
+{
+ size_t i;
+ struct packet *pkt = &packets[packet_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len += len;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+ for (i = 0; i < len; ++i) {
+ int off = len - 1 - i;
+
+ pkt->payload[payload_last - off] = start;
+ start -= stepping;
+ }
+}
+
+static void set_dynamic_rnd(void)
+{
+ struct packet *pkt = &packets[packet_last];
+ struct packet_dyn *pktd = &packet_dyn[packetd_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len++;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+
+ pktd->rlen++;
+ pktd->rnd = xrealloc(pktd->rnd, 1, pktd->rlen * sizeof(struct randomizer));
+
+ __setup_new_randomizer(&pktd->rnd[packetdr_last]);
+}
+
+static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
+ int type)
+{
+ struct packet *pkt = &packets[packet_last];
+ struct packet_dyn *pktd = &packet_dyn[packetd_last];
+
+ if (test_ignore())
+ return;
+
+ pkt->len++;
+ pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
+
+ pktd->clen++;
+ pktd->cnt =xrealloc(pktd->cnt, 1, pktd->clen * sizeof(struct counter));
+
+ __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
+}
+
+%}
+
+%union {
+ long long int number;
+ char *str;
+}
+
+%token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
+%token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
+
+%token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
+
+%token number string
+
+%type <number> number expression
+%type <str> string
+
+%left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
+
+%%
+
+packets
+ : { }
+ | packets packet { }
+ | packets inline_comment { }
+ | packets K_WHITE { }
+ ;
+
+inline_comment
+ : K_COMMENT { }
+ ;
+
+packet
+ : '{' delimiter payload delimiter '}' {
+ min_cpu = max_cpu = -1;
+ realloc_packet();
+ }
+ | K_CPU '(' number ':' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
+ min_cpu = $3;
+ max_cpu = $5;
+
+ if (min_cpu > max_cpu) {
+ int tmp = min_cpu;
+
+ min_cpu = max_cpu;
+ max_cpu = tmp;
+ }
+
+ realloc_packet();
+ }
+ | K_CPU '(' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
+ min_cpu = max_cpu = $3;
+ realloc_packet();
+ }
+ ;
+
+payload
+ : elem { }
+ | payload elem_delimiter { }
+ ;
+
+delimiter
+ : ',' { }
+ | K_WHITE { }
+ | ',' K_WHITE { }
+ ;
+
+elem_delimiter
+ : delimiter elem { }
+ ;
+
+elem
+ : number { set_byte((uint8_t) $1); }
+ | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
+ | fill { }
+ | rnd { }
+ | drnd { }
+ | seqinc { }
+ | seqdec { }
+ | dinc { }
+ | ddec { }
+ | csum { }
+ | const { }
+ | inline_comment { }
+ ;
+
+expression
+ : number
+ { $$ = $1; }
+ | expression '+' expression
+ { $$ = $1 + $3; }
+ | expression '-' expression
+ { $$ = $1 - $3; }
+ | expression '*' expression
+ { $$ = $1 * $3; }
+ | expression '/' expression
+ { $$ = $1 / $3; }
+ | expression '%' expression
+ { $$ = $1 % $3; }
+ | expression '&' expression
+ { $$ = $1 & $3; }
+ | expression '|' expression
+ { $$ = $1 | $3; }
+ | expression '^' expression
+ { $$ = $1 ^ $3; }
+ | expression '<' '<' expression
+ { $$ = $1 << $4; }
+ | expression '>' '>' expression
+ { $$ = $1 >> $4; }
+ | '(' expression ')'
+ { $$ = $2;}
+ ;
+
+fill
+ : K_FILL '(' number delimiter number ')'
+ { set_fill($3, $5); }
+ ;
+
+const
+ : K_CONST8 '(' expression ')'
+ { set_byte((uint8_t) $3); }
+ | K_CONST16 '(' expression ')' {
+ uint16_t __c = cpu_to_be16((uint16_t) $3);
+
+ set_multi_byte((uint8_t *) &__c, sizeof(__c));
+ }
+ | K_CONST32 '(' expression ')' {
+ uint32_t __c = cpu_to_be32((uint32_t) $3);
+
+ set_multi_byte((uint8_t *) &__c, sizeof(__c));
+ }
+ | K_CONST64 '(' expression ')' {
+ uint64_t __c = cpu_to_be64((uint64_t) $3);
+
+ set_multi_byte((uint8_t *) &__c, sizeof(__c));
+ }
+ ;
+
+rnd
+ : K_RND '(' number ')'
+ { set_rnd($3); }
+ ;
+
+csum
+ : K_CSUMIP '(' number delimiter number ')'
+ { set_csum16($3, $5, CSUM_IP); }
+ | K_CSUMTCP '(' number delimiter number ')'
+ { set_csum16($3, $5, CSUM_TCP); }
+ | K_CSUMUDP '(' number delimiter number ')'
+ { set_csum16($3, $5, CSUM_UDP); }
+ ;
+
+seqinc
+ : K_SEQINC '(' number delimiter number ')'
+ { set_sequential_inc($3, $5, 1); }
+ | K_SEQINC '(' number delimiter number delimiter number ')'
+ { set_sequential_inc($3, $5, $7); }
+ ;
+
+seqdec
+ : K_SEQDEC '(' number delimiter number ')'
+ { set_sequential_dec($3, $5, 1); }
+ | K_SEQDEC '(' number delimiter number delimiter number ')'
+ { set_sequential_dec($3, $5, $7); }
+ ;
+
+drnd
+ : K_DRND '(' ')'
+ { set_dynamic_rnd(); }
+ | K_DRND '(' number ')'
+ {
+ int i, max = $3;
+ for (i = 0; i < max; ++i)
+ set_dynamic_rnd();
+ }
+ ;
+
+dinc
+ : K_DINC '(' number delimiter number ')'
+ { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
+ | K_DINC '(' number delimiter number delimiter number ')'
+ { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
+ ;
+
+ddec
+ : K_DDEC '(' number delimiter number ')'
+ { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
+ | K_DDEC '(' number delimiter number delimiter number ')'
+ { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
+ ;
+
+%%
+
+static void finalize_packet(void)
+{
+ /* XXX hack ... we allocated one packet pointer too much */
+ plen--;
+ dlen--;
+}
+
+static void dump_conf(void)
+{
+ size_t i, j;
+
+ for (i = 0; i < plen; ++i) {
+ printf("[%zu] pkt\n", i);
+ printf(" len %zu cnts %zu rnds %zu\n",
+ packets[i].len,
+ packet_dyn[i].clen,
+ packet_dyn[i].rlen);
+
+ printf(" payload ");
+ for (j = 0; j < packets[i].len; ++j)
+ printf("%02x ", packets[i].payload[j]);
+ printf("\n");
+
+ for (j = 0; j < packet_dyn[i].clen; ++j)
+ printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j,
+ packet_dyn[i].cnt[j].min,
+ packet_dyn[i].cnt[j].max,
+ packet_dyn[i].cnt[j].inc,
+ packet_dyn[i].cnt[j].off,
+ packet_dyn[i].cnt[j].type == TYPE_INC ?
+ "inc" : "dec");
+
+ for (j = 0; j < packet_dyn[i].rlen; ++j)
+ printf(" rnd%zu off %ld\n", j,
+ packet_dyn[i].rnd[j].off);
+ }
+}
+
+void cleanup_packets(void)
+{
+ size_t i;
+
+ for (i = 0; i < plen; ++i) {
+ if (packets[i].len > 0)
+ xfree(packets[i].payload);
+ }
+
+ free(packets);
+
+ for (i = 0; i < dlen; ++i) {
+ free(packet_dyn[i].cnt);
+ free(packet_dyn[i].rnd);
+ }
+
+ free(packet_dyn);
+}
+
+int compile_packets(char *file, int verbose, int cpu, bool invoke_cpp)
+{
+ char tmp_file[128];
+
+ memset(tmp_file, 0, sizeof(tmp_file));
+ our_cpu = cpu;
+
+ if (invoke_cpp) {
+ char cmd[256], *dir, *base, *a, *b;
+
+ dir = dirname((a = xstrdup(file)));
+ base = basename((b = xstrdup(file)));
+
+ slprintf(tmp_file, sizeof(tmp_file), "%s/.tmp-%u-%s", dir, rand(), base);
+ slprintf(cmd, sizeof(cmd), "cpp -I/etc/netsniff-ng/ %s > %s", file, tmp_file);
+ system(cmd);
+
+ file = tmp_file;
+ xfree(a);
+ xfree(b);
+ }
+
+ if (!strncmp("-", file, strlen("-")))
+ yyin = stdin;
+ else
+ yyin = fopen(file, "r");
+ if (!yyin)
+ panic("Cannot open %s: %s!\n", file, strerror(errno));
+
+ realloc_packet();
+ yyparse();
+ finalize_packet();
+
+ if (our_cpu == 0 && verbose)
+ dump_conf();
+
+ fclose(yyin);
+ if (invoke_cpp)
+ unlink(tmp_file);
+
+ return 0;
+}
+
+void yyerror(const char *err)
+{
+ panic("Syntax error at line%d, at char '%s'! %s!\n", yylineno, yytext, err);
+}