summaryrefslogtreecommitdiff
path: root/trafgen_parser.y
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
committerDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
commit1a9fbac03c684f29cff9ac44875bd9504a89f54e (patch)
tree1b2e40dbe5dc1899ef5b62c4325c9b94c9c450fc /trafgen_parser.y
all: import netsniff-ng 0.5.8-rc0 source
We decided to get rid of the old Git history and start a new one for several reasons: *) Allow / enforce only high-quality commits (which was not the case for many commits in the history), have a policy that is more close to the one from the Linux kernel. With high quality commits, we mean code that is logically split into commits and commit messages that are signed-off and have a proper subject and message body. We do not allow automatic Github merges anymore, since they are total bullshit. However, we will either cherry-pick your patches or pull them manually. *) The old archive was about ~27MB for no particular good reason. This basically derived from the bad decision that also some PDF files where stored there. From this moment onwards, no binary objects are allowed to be stored in this repository anymore. The old archive is not wiped away from the Internet. You will still be able to find it, e.g. on git.cryptoism.org etc. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
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);
+}