trafgen: allow spaces between operands
[netsniff-ng.git] / src / trafgen_parser.y
blobede081a05f8dbf064274303649d7c9dccef9c533
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>
19 #include "xmalloc.h"
20 #include "trafgen_parser.tab.h"
21 #include "trafgen_conf.h"
22 #include "built_in.h"
23 #include "die.h"
24 #include "csum.h"
26 #define YYERROR_VERBOSE 0
27 #define YYDEBUG 0
28 #define YYENABLE_NLS 1
29 #define YYLTYPE_IS_TRIVIAL 1
30 #define ENABLE_NLS 1
32 extern FILE *yyin;
33 extern int yylex(void);
34 extern void yyerror(const char *);
35 extern int yylineno;
36 extern char *yytext;
38 extern struct packet *packets;
39 extern size_t plen;
41 #define packet_last (plen - 1)
43 #define payload_last (packets[packet_last].len - 1)
45 extern struct packet_dyn *packet_dyn;
46 extern size_t dlen;
48 #define packetd_last (dlen - 1)
50 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
51 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
52 #define packetds_last (packet_dyn[packetd_last].slen - 1)
54 static int our_cpu, min_cpu = -1, max_cpu = -1;
56 static inline int test_ignore(void)
58 if (min_cpu < 0 && max_cpu < 0)
59 return 0;
60 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
61 return 0;
62 else
63 return 1;
66 static inline int has_dynamic_elems(struct packet_dyn *p)
68 return (p->rlen + p->slen + p->clen);
71 static inline void __init_new_packet_slot(struct packet *slot)
73 slot->payload = NULL;
74 slot->len = 0;
77 static inline void __init_new_counter_slot(struct packet_dyn *slot)
79 slot->cnt = NULL;
80 slot->clen = 0;
83 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
85 slot->rnd = NULL;
86 slot->rlen = 0;
89 static inline void __init_new_csum_slot(struct packet_dyn *slot)
91 slot->csum = NULL;
92 slot->slen = 0;
95 static inline void __setup_new_counter(struct counter *c, uint8_t start,
96 uint8_t stop, uint8_t stepping,
97 int type)
99 c->min = start;
100 c->max = stop;
101 c->inc = stepping;
102 c->val = (type == TYPE_INC) ? start : stop;
103 c->off = payload_last;
104 c->type = type;
107 static inline void __setup_new_randomizer(struct randomizer *r)
109 r->off = payload_last;
112 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
113 enum csum which)
115 s->off = payload_last - 1;
116 s->from = from;
117 s->to = to;
118 s->which = which;
121 static void realloc_packet(void)
123 if (test_ignore())
124 return;
126 plen++;
127 packets = xrealloc(packets, 1, plen * sizeof(*packets));
129 __init_new_packet_slot(&packets[packet_last]);
131 dlen++;
132 packet_dyn = xrealloc(packet_dyn, 1, dlen * sizeof(*packet_dyn));
134 __init_new_counter_slot(&packet_dyn[packetd_last]);
135 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
136 __init_new_csum_slot(&packet_dyn[packetd_last]);
139 static void set_byte(uint8_t val)
141 struct packet *pkt = &packets[packet_last];
143 if (test_ignore())
144 return;
146 pkt->len++;
147 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
148 pkt->payload[payload_last] = val;
151 static void set_fill(uint8_t val, size_t len)
153 size_t i;
154 struct packet *pkt = &packets[packet_last];
156 if (test_ignore())
157 return;
159 pkt->len += len;
160 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
161 for (i = 0; i < len; ++i)
162 pkt->payload[payload_last - i] = val;
165 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
167 struct packet *pkt = &packets[packet_last];
168 struct packet_dyn *pktd = &packet_dyn[packetd_last];
170 pkt->len += 2;
171 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
173 pktd->slen++;
174 pktd->csum = xrealloc(pktd->csum, 1, pktd->slen * sizeof(struct csum16));
176 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
179 static void __set_csum16_static(size_t from, size_t to, enum csum which)
181 struct packet *pkt = &packets[packet_last];
182 uint16_t sum;
183 uint8_t *psum;
185 sum = htons(calc_csum(pkt->payload + from, to - from, 0));
186 psum = (uint8_t *) &sum;
188 set_byte(psum[0]);
189 set_byte(psum[1]);
192 static void set_csum16(size_t from, size_t to, enum csum which)
194 int make_it_dynamic = 0;
195 struct packet *pkt = &packets[packet_last];
196 struct packet_dyn *pktd = &packet_dyn[packetd_last];
198 if (test_ignore())
199 return;
201 if (to < from) {
202 size_t tmp = to;
204 to = from;
205 from = tmp;
208 bug_on(!(from < to));
210 if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
211 make_it_dynamic = 1;
213 if (has_dynamic_elems(pktd) || make_it_dynamic)
214 __set_csum16_dynamic(from, to, which);
215 else
216 __set_csum16_static(from, to, which);
219 static void set_rnd(size_t len)
221 size_t i;
222 struct packet *pkt = &packets[packet_last];
224 if (test_ignore())
225 return;
227 pkt->len += len;
228 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
229 for (i = 0; i < len; ++i)
230 pkt->payload[payload_last - i] = (uint8_t) rand();
233 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
235 size_t i;
236 struct packet *pkt = &packets[packet_last];
238 if (test_ignore())
239 return;
241 pkt->len += len;
242 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
243 for (i = 0; i < len; ++i) {
244 off_t off = len - 1 - i;
246 pkt->payload[payload_last - off] = start;
247 start += stepping;
251 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
253 size_t i;
254 struct packet *pkt = &packets[packet_last];
256 if (test_ignore())
257 return;
259 pkt->len += len;
260 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
261 for (i = 0; i < len; ++i) {
262 int off = len - 1 - i;
264 pkt->payload[payload_last - off] = start;
265 start -= stepping;
269 static void set_dynamic_rnd(void)
271 struct packet *pkt = &packets[packet_last];
272 struct packet_dyn *pktd = &packet_dyn[packetd_last];
274 if (test_ignore())
275 return;
277 pkt->len++;
278 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
280 pktd->rlen++;
281 pktd->rnd = xrealloc(pktd->rnd, 1, pktd->rlen * sizeof(struct randomizer));
283 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
286 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
287 int type)
289 struct packet *pkt = &packets[packet_last];
290 struct packet_dyn *pktd = &packet_dyn[packetd_last];
292 if (test_ignore())
293 return;
295 pkt->len++;
296 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
298 pktd->clen++;
299 pktd->cnt =xrealloc(pktd->cnt, 1, pktd->clen * sizeof(struct counter));
301 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
306 %union {
307 long long int number;
310 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
311 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
313 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
315 %token number
317 %type <number> number expression
319 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
323 packets
324 : { }
325 | packets packet { }
326 | packets inline_comment { }
327 | packets K_WHITE { }
330 inline_comment
331 : K_COMMENT { }
334 packet
335 : '{' delimiter payload delimiter '}' {
336 min_cpu = max_cpu = -1;
337 realloc_packet();
339 | K_CPU '(' number ':' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
340 min_cpu = $3;
341 max_cpu = $5;
343 if (min_cpu > max_cpu) {
344 int tmp = min_cpu;
346 min_cpu = max_cpu;
347 max_cpu = tmp;
350 realloc_packet();
352 | K_CPU '(' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
353 min_cpu = max_cpu = $3;
354 realloc_packet();
358 payload
359 : elem { }
360 | payload elem_delimiter { }
363 delimiter
364 : ',' { }
365 | K_WHITE { }
366 | ',' K_WHITE { }
369 elem_delimiter
370 : delimiter elem { }
373 elem
374 : number { set_byte((uint8_t) $1); }
375 | fill { }
376 | rnd { }
377 | drnd { }
378 | seqinc { }
379 | seqdec { }
380 | dinc { }
381 | ddec { }
382 | csum { }
383 | const { }
384 | inline_comment { }
387 expression
388 : number
389 { $$ = $1; }
390 | expression '+' expression
391 { $$ = $1 + $3; }
392 | expression '-' expression
393 { $$ = $1 - $3; }
394 | expression '*' expression
395 { $$ = $1 * $3; }
396 | expression '/' expression
397 { $$ = $1 / $3; }
398 | expression '%' expression
399 { $$ = $1 % $3; }
400 | expression '&' expression
401 { $$ = $1 & $3; }
402 | expression '|' expression
403 { $$ = $1 | $3; }
404 | expression '^' expression
405 { $$ = $1 ^ $3; }
406 | expression '<' '<' expression
407 { $$ = $1 << $4; }
408 | expression '>' '>' expression
409 { $$ = $1 >> $4; }
410 | '(' expression ')'
411 { $$ = $2;}
414 fill
415 : K_FILL '(' number delimiter number ')'
416 { set_fill($3, $5); }
419 const
420 : K_CONST8 '(' expression ')'
421 { set_byte((uint8_t) $3); }
422 | K_CONST16 '(' expression ')' {
423 int i;
424 uint16_t __c = cpu_to_be16((uint16_t) $3);
425 uint8_t *ptr = (uint8_t *) &__c;
427 for (i = 0; i < sizeof(__c); ++i)
428 set_byte(ptr[i]);
430 | K_CONST32 '(' expression ')' {
431 int i;
432 uint32_t __c = cpu_to_be32((uint32_t) $3);
433 uint8_t *ptr = (uint8_t *) &__c;
435 for (i = 0; i < sizeof(__c); ++i)
436 set_byte(ptr[i]);
438 | K_CONST64 '(' expression ')' {
439 int i;
440 uint64_t __c = cpu_to_be64((uint64_t) $3);
441 uint8_t *ptr = (uint8_t *) &__c;
443 for (i = 0; i < sizeof(__c); ++i)
444 set_byte(ptr[i]);
449 : K_RND '(' number ')'
450 { set_rnd($3); }
453 csum
454 : K_CSUMIP '(' number delimiter number ')'
455 { set_csum16($3, $5, CSUM_IP); }
456 | K_CSUMTCP '(' number delimiter number ')'
457 { set_csum16($3, $5, CSUM_TCP); }
458 | K_CSUMUDP '(' number delimiter number ')'
459 { set_csum16($3, $5, CSUM_UDP); }
462 seqinc
463 : K_SEQINC '(' number delimiter number ')'
464 { set_sequential_inc($3, $5, 1); }
465 | K_SEQINC '(' number delimiter number delimiter number ')'
466 { set_sequential_inc($3, $5, $7); }
469 seqdec
470 : K_SEQDEC '(' number delimiter number ')'
471 { set_sequential_dec($3, $5, 1); }
472 | K_SEQDEC '(' number delimiter number delimiter number ')'
473 { set_sequential_dec($3, $5, $7); }
476 drnd
477 : K_DRND '(' ')'
478 { set_dynamic_rnd(); }
479 | K_DRND '(' number ')'
481 int i, max = $3;
482 for (i = 0; i < max; ++i)
483 set_dynamic_rnd();
487 dinc
488 : K_DINC '(' number delimiter number ')'
489 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
490 | K_DINC '(' number delimiter number delimiter number ')'
491 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
494 ddec
495 : K_DDEC '(' number delimiter number ')'
496 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
497 | K_DDEC '(' number delimiter number delimiter number ')'
498 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
503 static void finalize_packet(void)
505 /* XXX hack ... we allocated one packet pointer too much */
506 plen--;
507 dlen--;
510 static void dump_conf(void)
512 size_t i, j;
514 for (i = 0; i < plen; ++i) {
515 printf("[%zu] pkt\n", i);
516 printf(" len %zu cnts %zu rnds %zu\n",
517 packets[i].len,
518 packet_dyn[i].clen,
519 packet_dyn[i].rlen);
521 printf(" payload ");
522 for (j = 0; j < packets[i].len; ++j)
523 printf("%02x ", packets[i].payload[j]);
524 printf("\n");
526 for (j = 0; j < packet_dyn[i].clen; ++j)
527 printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j,
528 packet_dyn[i].cnt[j].min,
529 packet_dyn[i].cnt[j].max,
530 packet_dyn[i].cnt[j].inc,
531 packet_dyn[i].cnt[j].off,
532 packet_dyn[i].cnt[j].type == TYPE_INC ?
533 "inc" : "dec");
535 for (j = 0; j < packet_dyn[i].rlen; ++j)
536 printf(" rnd%zu off %ld\n", j,
537 packet_dyn[i].rnd[j].off);
541 void cleanup_packets(void)
543 size_t i;
545 for (i = 0; i < plen; ++i) {
546 if (packets[i].len > 0)
547 xfree(packets[i].payload);
550 free(packets);
552 for (i = 0; i < dlen; ++i) {
553 free(packet_dyn[i].cnt);
554 free(packet_dyn[i].rnd);
557 free(packet_dyn);
560 int compile_packets(char *file, int verbose, int cpu)
562 our_cpu = cpu;
564 yyin = fopen(file, "r");
565 if (!yyin)
566 panic("Cannot open file!\n");
568 realloc_packet();
569 yyparse();
570 finalize_packet();
572 if (our_cpu == 0 && verbose)
573 dump_conf();
575 fclose(yyin);
576 return 0;
579 void yyerror(const char *err)
581 panic("Syntax error at line%d, at char '%s'! %s!\n", yylineno, yytext, err);