trafgen: Make sure yyin is set before close it
[netsniff-ng.git] / trafgen_parser.y
blob44751ab11a6845184a522ad0e8b8893c41741b22
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 <stdbool.h>
19 #include <libgen.h>
21 #include "xmalloc.h"
22 #include "trafgen_parser.tab.h"
23 #include "trafgen_conf.h"
24 #include "built_in.h"
25 #include "die.h"
26 #include "str.h"
27 #include "csum.h"
28 #include "cpp.h"
30 #define YYERROR_VERBOSE 0
31 #define YYDEBUG 0
32 #define YYENABLE_NLS 1
33 #define YYLTYPE_IS_TRIVIAL 1
34 #define ENABLE_NLS 1
36 extern FILE *yyin;
37 extern int yylex(void);
38 extern void yy_scan_string(char *);
39 extern void yylex_destroy();
40 extern void yyerror(const char *);
41 extern int yylineno;
42 extern char *yytext;
44 extern struct packet *packets;
45 extern size_t plen;
47 #define packet_last (plen - 1)
49 #define payload_last (packets[packet_last].len - 1)
51 extern struct packet_dyn *packet_dyn;
52 extern size_t dlen;
54 #define packetd_last (dlen - 1)
56 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
57 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
58 #define packetds_last (packet_dyn[packetd_last].slen - 1)
60 static int our_cpu, min_cpu = -1, max_cpu = -1;
62 static inline int test_ignore(void)
64 if (min_cpu < 0 && max_cpu < 0)
65 return 0;
66 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
67 return 0;
68 else
69 return 1;
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, plen * sizeof(*packets));
130 __init_new_packet_slot(&packets[packet_last]);
132 dlen++;
133 packet_dyn = xrealloc(packet_dyn, 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, pkt->len);
149 pkt->payload[payload_last] = val;
152 static void set_multi_byte(uint8_t *s, size_t len)
154 size_t i;
156 for (i = 0; i < len; ++i)
157 set_byte(s[i]);
160 static void set_fill(uint8_t val, size_t len)
162 size_t i;
163 struct packet *pkt = &packets[packet_last];
165 if (test_ignore())
166 return;
168 pkt->len += len;
169 pkt->payload = xrealloc(pkt->payload, pkt->len);
170 for (i = 0; i < len; ++i)
171 pkt->payload[payload_last - i] = val;
174 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
176 struct packet *pkt = &packets[packet_last];
177 struct packet_dyn *pktd = &packet_dyn[packetd_last];
179 pkt->len += 2;
180 pkt->payload = xrealloc(pkt->payload, pkt->len);
182 pktd->slen++;
183 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
185 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
188 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
190 struct packet *pkt = &packets[packet_last];
191 uint16_t sum;
192 uint8_t *psum;
194 sum = htons(calc_csum(pkt->payload + from, to - from));
195 psum = (uint8_t *) &sum;
197 set_byte(psum[0]);
198 set_byte(psum[1]);
201 static inline bool is_dynamic_csum(enum csum which)
203 switch (which) {
204 case CSUM_UDP:
205 case CSUM_TCP:
206 case CSUM_UDP6:
207 case CSUM_TCP6:
208 return true;
209 default:
210 return false;
214 static void set_csum16(size_t from, size_t to, enum csum which)
216 struct packet *pkt = &packets[packet_last];
217 struct packet_dyn *pktd = &packet_dyn[packetd_last];
219 if (test_ignore())
220 return;
222 if (to < from) {
223 size_t tmp = to;
225 to = from;
226 from = tmp;
229 bug_on(!(from < to));
231 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
232 __set_csum16_dynamic(from, to, which);
233 else
234 __set_csum16_static(from, to, which);
237 static void set_rnd(size_t len)
239 size_t i;
240 struct packet *pkt = &packets[packet_last];
242 if (test_ignore())
243 return;
245 pkt->len += len;
246 pkt->payload = xrealloc(pkt->payload, pkt->len);
247 for (i = 0; i < len; ++i)
248 pkt->payload[payload_last - i] = (uint8_t) rand();
251 static void set_sequential_inc(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, pkt->len);
261 for (i = 0; i < len; ++i) {
262 off_t off = len - 1 - i;
264 pkt->payload[payload_last - off] = start;
265 start += stepping;
269 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
271 size_t i;
272 struct packet *pkt = &packets[packet_last];
274 if (test_ignore())
275 return;
277 pkt->len += len;
278 pkt->payload = xrealloc(pkt->payload, pkt->len);
279 for (i = 0; i < len; ++i) {
280 int off = len - 1 - i;
282 pkt->payload[payload_last - off] = start;
283 start -= stepping;
287 static void set_dynamic_rnd(void)
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, pkt->len);
298 pktd->rlen++;
299 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
301 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
304 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
305 int type)
307 struct packet *pkt = &packets[packet_last];
308 struct packet_dyn *pktd = &packet_dyn[packetd_last];
310 if (test_ignore())
311 return;
313 pkt->len++;
314 pkt->payload = xrealloc(pkt->payload, pkt->len);
316 pktd->clen++;
317 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
319 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
324 %union {
325 long long int number;
326 char *str;
329 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
330 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
332 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
334 %token number string
336 %type <number> number expression
337 %type <str> string
339 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
343 packets
344 : { }
345 | packets packet { }
346 | packets inline_comment { }
347 | packets K_WHITE { }
350 inline_comment
351 : K_COMMENT { }
354 cpu_delim
355 : ':' { }
356 | '-' { }
359 delimiter_nowhite
360 : ',' { }
361 | ',' K_WHITE { }
364 noenforce_white
365 : { }
366 | K_WHITE { }
367 | delimiter_nowhite { }
370 packet
371 : '{' noenforce_white payload noenforce_white '}' {
372 min_cpu = max_cpu = -1;
373 realloc_packet();
375 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
376 min_cpu = $3;
377 max_cpu = $5;
379 if (min_cpu > max_cpu) {
380 int tmp = min_cpu;
382 min_cpu = max_cpu;
383 max_cpu = tmp;
386 realloc_packet();
388 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
389 min_cpu = max_cpu = $3;
390 realloc_packet();
394 payload
395 : elem { }
396 | payload elem_delimiter { }
399 delimiter
400 : delimiter_nowhite { }
401 | K_WHITE { }
404 elem_delimiter
405 : delimiter elem { }
408 elem
409 : number { set_byte((uint8_t) $1); }
410 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
411 | fill { }
412 | rnd { }
413 | drnd { }
414 | seqinc { }
415 | seqdec { }
416 | dinc { }
417 | ddec { }
418 | csum { }
419 | const { }
420 | inline_comment { }
423 expression
424 : number
425 { $$ = $1; }
426 | expression '+' expression
427 { $$ = $1 + $3; }
428 | expression '-' expression
429 { $$ = $1 - $3; }
430 | expression '*' expression
431 { $$ = $1 * $3; }
432 | expression '/' expression
433 { $$ = $1 / $3; }
434 | expression '%' expression
435 { $$ = $1 % $3; }
436 | expression '&' expression
437 { $$ = $1 & $3; }
438 | expression '|' expression
439 { $$ = $1 | $3; }
440 | expression '^' expression
441 { $$ = $1 ^ $3; }
442 | expression '<' '<' expression
443 { $$ = $1 << $4; }
444 | expression '>' '>' expression
445 { $$ = $1 >> $4; }
446 | '-' expression
447 { $$ = -1 * $2; }
448 | '(' expression ')'
449 { $$ = $2;}
452 fill
453 : K_FILL '(' number delimiter number ')'
454 { set_fill($3, $5); }
457 const
458 : K_CONST8 '(' expression ')'
459 { set_byte((uint8_t) $3); }
460 | K_CONST16 '(' expression ')' {
461 uint16_t __c = cpu_to_be16((uint16_t) $3);
463 set_multi_byte((uint8_t *) &__c, sizeof(__c));
465 | K_CONST32 '(' expression ')' {
466 uint32_t __c = cpu_to_be32((uint32_t) $3);
468 set_multi_byte((uint8_t *) &__c, sizeof(__c));
470 | K_CONST64 '(' expression ')' {
471 uint64_t __c = cpu_to_be64((uint64_t) $3);
473 set_multi_byte((uint8_t *) &__c, sizeof(__c));
478 : K_RND '(' number ')'
479 { set_rnd($3); }
482 csum
483 : K_CSUMIP '(' number delimiter number ')'
484 { set_csum16($3, $5, CSUM_IP); }
485 | K_CSUMTCP '(' number delimiter number ')'
486 { set_csum16($3, $5, CSUM_TCP); }
487 | K_CSUMUDP '(' number delimiter number ')'
488 { set_csum16($3, $5, CSUM_UDP); }
489 | K_CSUMTCP6 '(' number delimiter number ')'
490 { set_csum16($3, $5, CSUM_TCP6); }
491 | K_CSUMUDP6 '(' number delimiter number ')'
492 { set_csum16($3, $5, CSUM_UDP6); }
495 seqinc
496 : K_SEQINC '(' number delimiter number ')'
497 { set_sequential_inc($3, $5, 1); }
498 | K_SEQINC '(' number delimiter number delimiter number ')'
499 { set_sequential_inc($3, $5, $7); }
502 seqdec
503 : K_SEQDEC '(' number delimiter number ')'
504 { set_sequential_dec($3, $5, 1); }
505 | K_SEQDEC '(' number delimiter number delimiter number ')'
506 { set_sequential_dec($3, $5, $7); }
509 drnd
510 : K_DRND '(' ')'
511 { set_dynamic_rnd(); }
512 | K_DRND '(' number ')'
514 int i, max = $3;
515 for (i = 0; i < max; ++i)
516 set_dynamic_rnd();
520 dinc
521 : K_DINC '(' number delimiter number ')'
522 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
523 | K_DINC '(' number delimiter number delimiter number ')'
524 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
527 ddec
528 : K_DDEC '(' number delimiter number ')'
529 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
530 | K_DDEC '(' number delimiter number delimiter number ')'
531 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
536 static void finalize_packet(void)
538 /* XXX hack ... we allocated one packet pointer too much */
539 plen--;
540 dlen--;
543 static void dump_conf(void)
545 size_t i, j;
547 for (i = 0; i < plen; ++i) {
548 printf("[%zu] pkt\n", i);
549 printf(" len %zu cnts %zu rnds %zu\n",
550 packets[i].len,
551 packet_dyn[i].clen,
552 packet_dyn[i].rlen);
554 printf(" payload ");
555 for (j = 0; j < packets[i].len; ++j)
556 printf("%02x ", packets[i].payload[j]);
557 printf("\n");
559 for (j = 0; j < packet_dyn[i].clen; ++j)
560 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
561 packet_dyn[i].cnt[j].min,
562 packet_dyn[i].cnt[j].max,
563 packet_dyn[i].cnt[j].inc,
564 (intmax_t)packet_dyn[i].cnt[j].off,
565 packet_dyn[i].cnt[j].type == TYPE_INC ?
566 "inc" : "dec");
568 for (j = 0; j < packet_dyn[i].rlen; ++j)
569 printf(" rnd%zu off %jd\n", j,
570 (intmax_t)packet_dyn[i].rnd[j].off);
574 void cleanup_packets(void)
576 size_t i;
578 for (i = 0; i < plen; ++i) {
579 if (packets[i].len > 0)
580 xfree(packets[i].payload);
583 free(packets);
585 for (i = 0; i < dlen; ++i) {
586 free(packet_dyn[i].cnt);
587 free(packet_dyn[i].rnd);
590 free(packet_dyn);
593 void compile_packets(char *file, bool verbose, unsigned int cpu, bool invoke_cpp)
595 char tmp_file[128];
596 int ret = -1;
598 memset(tmp_file, 0, sizeof(tmp_file));
599 our_cpu = cpu;
601 if (invoke_cpp) {
602 if (cpp_exec(file, tmp_file, sizeof(tmp_file))) {
603 fprintf(stderr, "Failed to invoke C preprocessor!\n");
604 goto err;
606 file = tmp_file;
609 if (!strncmp("-", file, strlen("-")))
610 yyin = stdin;
611 else
612 yyin = fopen(file, "r");
613 if (!yyin) {
614 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
615 goto err;
618 realloc_packet();
619 if (yyparse() != 0)
620 goto err;
621 finalize_packet();
623 if (our_cpu == 0 && verbose)
624 dump_conf();
626 ret = 0;
627 err:
628 if (yyin && yyin != stdin)
629 fclose(yyin);
631 if (invoke_cpp)
632 unlink(tmp_file);
633 if (ret)
634 die();
637 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
639 int ret = 1;
641 our_cpu = cpu;
642 realloc_packet();
644 yy_scan_string(str);
645 if (yyparse() != 0)
646 goto err;
648 finalize_packet();
649 if (our_cpu == 0 && verbose)
650 dump_conf();
652 ret = 0;
653 err:
654 yylex_destroy();
656 if (ret)
657 die();
660 void yyerror(const char *err)
662 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);