trafgen: inline constant expression calculator
[netsniff-ng.git] / src / trafgen_parser.y
blobc67b44ba6314d7d880df7eba81caa7371d77a461
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
7 */
9 /* yaac-func-prefix: yy */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <signal.h>
16 #include <stdint.h>
17 #include <errno.h>
18 #include <math.h>
20 #include "xmalloc.h"
21 #include "trafgen_parser.tab.h"
22 #include "trafgen_conf.h"
23 #include "built_in.h"
24 #include "die.h"
25 #include "csum.h"
27 #define YYERROR_VERBOSE 0
28 #define YYDEBUG 0
29 #define YYENABLE_NLS 1
30 #define YYLTYPE_IS_TRIVIAL 1
31 #define ENABLE_NLS 1
33 extern FILE *yyin;
34 extern int yylex(void);
35 extern void yyerror(const char *);
36 extern int yylineno;
37 extern char *yytext;
39 extern struct packet *packets;
40 extern size_t plen;
42 #define packet_last (plen - 1)
44 #define payload_last (packets[packet_last].len - 1)
46 extern struct packet_dyn *packet_dyn;
47 extern size_t dlen;
49 #define packetd_last (dlen - 1)
51 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
52 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
53 #define packetds_last (packet_dyn[packetd_last].slen - 1)
55 static int our_cpu, min_cpu = -1, max_cpu = -1;
57 static inline int test_ignore(void)
59 if (min_cpu < 0 && max_cpu < 0)
60 return 0;
61 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
62 return 0;
63 else
64 return 1;
67 static inline int has_dynamic_elems(struct packet_dyn *p)
69 return (p->rlen + p->slen + p->clen);
72 static inline void __init_new_packet_slot(struct packet *slot)
74 slot->payload = NULL;
75 slot->len = 0;
78 static inline void __init_new_counter_slot(struct packet_dyn *slot)
80 slot->cnt = NULL;
81 slot->clen = 0;
84 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
86 slot->rnd = NULL;
87 slot->rlen = 0;
90 static inline void __init_new_csum_slot(struct packet_dyn *slot)
92 slot->csum = NULL;
93 slot->slen = 0;
96 static inline void __setup_new_counter(struct counter *c, uint8_t start,
97 uint8_t stop, uint8_t stepping,
98 int type)
100 c->min = start;
101 c->max = stop;
102 c->inc = stepping;
103 c->val = (type == TYPE_INC) ? start : stop;
104 c->off = payload_last;
105 c->type = type;
108 static inline void __setup_new_randomizer(struct randomizer *r)
110 r->off = payload_last;
113 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
114 enum csum which)
116 s->off = payload_last - 1;
117 s->from = from;
118 s->to = to;
119 s->which = which;
122 static void realloc_packet(void)
124 if (test_ignore())
125 return;
127 plen++;
128 packets = xrealloc(packets, 1, plen * sizeof(*packets));
130 __init_new_packet_slot(&packets[packet_last]);
132 dlen++;
133 packet_dyn = xrealloc(packet_dyn, 1, dlen * sizeof(*packet_dyn));
135 __init_new_counter_slot(&packet_dyn[packetd_last]);
136 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
137 __init_new_csum_slot(&packet_dyn[packetd_last]);
140 static void set_byte(uint8_t val)
142 struct packet *pkt = &packets[packet_last];
144 if (test_ignore())
145 return;
147 pkt->len++;
148 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
149 pkt->payload[payload_last] = val;
152 static void set_fill(uint8_t val, size_t len)
154 size_t i;
155 struct packet *pkt = &packets[packet_last];
157 if (test_ignore())
158 return;
160 pkt->len += len;
161 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
162 for (i = 0; i < len; ++i)
163 pkt->payload[payload_last - i] = val;
166 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
168 struct packet *pkt = &packets[packet_last];
169 struct packet_dyn *pktd = &packet_dyn[packetd_last];
171 pkt->len += 2;
172 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
174 pktd->slen++;
175 pktd->csum = xrealloc(pktd->csum, 1, pktd->slen * sizeof(struct csum16));
177 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
180 static void __set_csum16_static(size_t from, size_t to, enum csum which)
182 struct packet *pkt = &packets[packet_last];
183 uint16_t sum;
184 uint8_t *psum;
186 sum = htons(calc_csum(pkt->payload + from, to - from, 0));
187 psum = (uint8_t *) &sum;
189 set_byte(psum[0]);
190 set_byte(psum[1]);
193 static void set_csum16(size_t from, size_t to, enum csum which)
195 int make_it_dynamic = 0;
196 struct packet *pkt = &packets[packet_last];
197 struct packet_dyn *pktd = &packet_dyn[packetd_last];
199 if (test_ignore())
200 return;
202 if (to < from) {
203 size_t tmp = to;
205 to = from;
206 from = tmp;
209 bug_on(!(from < to));
211 if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
212 make_it_dynamic = 1;
214 if (has_dynamic_elems(pktd) || make_it_dynamic)
215 __set_csum16_dynamic(from, to, which);
216 else
217 __set_csum16_static(from, to, which);
220 static void set_rnd(size_t len)
222 size_t i;
223 struct packet *pkt = &packets[packet_last];
225 if (test_ignore())
226 return;
228 pkt->len += len;
229 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
230 for (i = 0; i < len; ++i)
231 pkt->payload[payload_last - i] = (uint8_t) rand();
234 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
236 size_t i;
237 struct packet *pkt = &packets[packet_last];
239 if (test_ignore())
240 return;
242 pkt->len += len;
243 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
244 for (i = 0; i < len; ++i) {
245 off_t off = len - 1 - i;
247 pkt->payload[payload_last - off] = start;
248 start += stepping;
252 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
254 size_t i;
255 struct packet *pkt = &packets[packet_last];
257 if (test_ignore())
258 return;
260 pkt->len += len;
261 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
262 for (i = 0; i < len; ++i) {
263 int off = len - 1 - i;
265 pkt->payload[payload_last - off] = start;
266 start -= stepping;
270 static void set_dynamic_rnd(void)
272 struct packet *pkt = &packets[packet_last];
273 struct packet_dyn *pktd = &packet_dyn[packetd_last];
275 if (test_ignore())
276 return;
278 pkt->len++;
279 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
281 pktd->rlen++;
282 pktd->rnd = xrealloc(pktd->rnd, 1, pktd->rlen * sizeof(struct randomizer));
284 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
287 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
288 int type)
290 struct packet *pkt = &packets[packet_last];
291 struct packet_dyn *pktd = &packet_dyn[packetd_last];
293 if (test_ignore())
294 return;
296 pkt->len++;
297 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
299 pktd->clen++;
300 pktd->cnt =xrealloc(pktd->cnt, 1, pktd->clen * sizeof(struct counter));
302 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
307 %union {
308 long long int number;
311 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
312 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
314 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
316 %token number
318 %type <number> number expression
320 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
324 packets
325 : { }
326 | packets packet { }
327 | packets inline_comment { }
328 | packets K_WHITE { }
331 inline_comment
332 : K_COMMENT { }
335 packet
336 : '{' delimiter payload delimiter '}' {
337 min_cpu = max_cpu = -1;
338 realloc_packet();
340 | K_CPU '(' number ':' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
341 min_cpu = $3;
342 max_cpu = $5;
344 if (min_cpu > max_cpu) {
345 int tmp = min_cpu;
347 min_cpu = max_cpu;
348 max_cpu = tmp;
351 realloc_packet();
353 | K_CPU '(' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
354 min_cpu = max_cpu = $3;
355 realloc_packet();
359 payload
360 : elem { }
361 | payload elem_delimiter { }
364 delimiter
365 : ',' { }
366 | K_WHITE { }
367 | ',' K_WHITE { }
370 elem_delimiter
371 : delimiter elem { }
374 elem
375 : number { set_byte((uint8_t) $1); }
376 | fill { }
377 | rnd { }
378 | drnd { }
379 | seqinc { }
380 | seqdec { }
381 | dinc { }
382 | ddec { }
383 | csum { }
384 | const { }
385 | inline_comment { }
388 expression
389 : number
390 { $$ = $1; }
391 | expression '+' expression
392 { $$ = $1 + $3; }
393 | expression '-' expression
394 { $$ = $1 - $3; }
395 | expression '*' expression
396 { $$ = $1 * $3; }
397 | expression '/' expression
398 { $$ = $1 / $3; }
399 | expression '%' expression
400 { $$ = $1 % $3; }
401 | expression '&' expression
402 { $$ = $1 & $3; }
403 | expression '|' expression
404 { $$ = $1 | $3; }
405 | expression '^' expression
406 { $$ = $1 ^ $3; }
407 | expression '<' '<' expression
408 { $$ = $1 << $4; }
409 | expression '>' '>' expression
410 { $$ = $1 >> $4; }
411 | '(' expression ')'
412 { $$ = $2;}
415 fill
416 : K_FILL '(' number delimiter number ')'
417 { set_fill($3, $5); }
420 const
421 : K_CONST8 '(' expression ')'
422 { set_byte((uint8_t) $3); }
423 | K_CONST16 '(' expression ')' {
424 int i;
425 uint16_t __c = cpu_to_be16((uint16_t) $3);
426 uint8_t *ptr = (uint8_t *) &__c;
428 for (i = 0; i < sizeof(__c); ++i)
429 set_byte(ptr[i]);
431 | K_CONST32 '(' expression ')' {
432 int i;
433 uint32_t __c = cpu_to_be32((uint32_t) $3);
434 uint8_t *ptr = (uint8_t *) &__c;
436 for (i = 0; i < sizeof(__c); ++i)
437 set_byte(ptr[i]);
439 | K_CONST64 '(' expression ')' {
440 int i;
441 uint64_t __c = cpu_to_be64((uint64_t) $3);
442 uint8_t *ptr = (uint8_t *) &__c;
444 for (i = 0; i < sizeof(__c); ++i)
445 set_byte(ptr[i]);
450 : K_RND '(' number ')'
451 { set_rnd($3); }
454 csum
455 : K_CSUMIP '(' number delimiter number ')'
456 { set_csum16($3, $5, CSUM_IP); }
457 | K_CSUMTCP '(' number delimiter number ')'
458 { set_csum16($3, $5, CSUM_TCP); }
459 | K_CSUMUDP '(' number delimiter number ')'
460 { set_csum16($3, $5, CSUM_UDP); }
463 seqinc
464 : K_SEQINC '(' number delimiter number ')'
465 { set_sequential_inc($3, $5, 1); }
466 | K_SEQINC '(' number delimiter number delimiter number ')'
467 { set_sequential_inc($3, $5, $7); }
470 seqdec
471 : K_SEQDEC '(' number delimiter number ')'
472 { set_sequential_dec($3, $5, 1); }
473 | K_SEQDEC '(' number delimiter number delimiter number ')'
474 { set_sequential_dec($3, $5, $7); }
477 drnd
478 : K_DRND '(' ')'
479 { set_dynamic_rnd(); }
480 | K_DRND '(' number ')'
482 int i, max = $3;
483 for (i = 0; i < max; ++i)
484 set_dynamic_rnd();
488 dinc
489 : K_DINC '(' number delimiter number ')'
490 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
491 | K_DINC '(' number delimiter number delimiter number ')'
492 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
495 ddec
496 : K_DDEC '(' number delimiter number ')'
497 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
498 | K_DDEC '(' number delimiter number delimiter number ')'
499 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
504 static void finalize_packet(void)
506 /* XXX hack ... we allocated one packet pointer too much */
507 plen--;
508 dlen--;
511 static void dump_conf(void)
513 size_t i, j;
515 for (i = 0; i < plen; ++i) {
516 printf("[%zu] pkt\n", i);
517 printf(" len %zu cnts %zu rnds %zu\n",
518 packets[i].len,
519 packet_dyn[i].clen,
520 packet_dyn[i].rlen);
522 printf(" payload ");
523 for (j = 0; j < packets[i].len; ++j)
524 printf("%02x ", packets[i].payload[j]);
525 printf("\n");
527 for (j = 0; j < packet_dyn[i].clen; ++j)
528 printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j,
529 packet_dyn[i].cnt[j].min,
530 packet_dyn[i].cnt[j].max,
531 packet_dyn[i].cnt[j].inc,
532 packet_dyn[i].cnt[j].off,
533 packet_dyn[i].cnt[j].type == TYPE_INC ?
534 "inc" : "dec");
536 for (j = 0; j < packet_dyn[i].rlen; ++j)
537 printf(" rnd%zu off %ld\n", j,
538 packet_dyn[i].rnd[j].off);
542 void cleanup_packets(void)
544 size_t i;
546 for (i = 0; i < plen; ++i) {
547 if (packets[i].len > 0)
548 xfree(packets[i].payload);
551 free(packets);
553 for (i = 0; i < dlen; ++i) {
554 free(packet_dyn[i].cnt);
555 free(packet_dyn[i].rnd);
558 free(packet_dyn);
561 int compile_packets(char *file, int verbose, int cpu)
563 our_cpu = cpu;
565 yyin = fopen(file, "r");
566 if (!yyin)
567 panic("Cannot open file!\n");
569 realloc_packet();
570 yyparse();
571 finalize_packet();
573 if (our_cpu == 0 && verbose)
574 dump_conf();
576 fclose(yyin);
577 return 0;
580 void yyerror(const char *err)
582 panic("Syntax error at line%d, at char '%s'! %s!\n", yylineno, yytext, err);