str: Add converting cmdline args vector to str module
[netsniff-ng.git] / trafgen_parser.y
blob88daf7a8812521f8691850ed7ef9fdffc3b9e2a4
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"
29 #define YYERROR_VERBOSE 0
30 #define YYDEBUG 0
31 #define YYENABLE_NLS 1
32 #define YYLTYPE_IS_TRIVIAL 1
33 #define ENABLE_NLS 1
35 extern FILE *yyin;
36 extern int yylex(void);
37 extern void yyerror(const char *);
38 extern int yylineno;
39 extern char *yytext;
41 extern struct packet *packets;
42 extern size_t plen;
44 #define packet_last (plen - 1)
46 #define payload_last (packets[packet_last].len - 1)
48 extern struct packet_dyn *packet_dyn;
49 extern size_t dlen;
51 #define packetd_last (dlen - 1)
53 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
54 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
55 #define packetds_last (packet_dyn[packetd_last].slen - 1)
57 static int our_cpu, min_cpu = -1, max_cpu = -1;
59 static inline int test_ignore(void)
61 if (min_cpu < 0 && max_cpu < 0)
62 return 0;
63 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
64 return 0;
65 else
66 return 1;
69 static inline void __init_new_packet_slot(struct packet *slot)
71 slot->payload = NULL;
72 slot->len = 0;
75 static inline void __init_new_counter_slot(struct packet_dyn *slot)
77 slot->cnt = NULL;
78 slot->clen = 0;
81 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
83 slot->rnd = NULL;
84 slot->rlen = 0;
87 static inline void __init_new_csum_slot(struct packet_dyn *slot)
89 slot->csum = NULL;
90 slot->slen = 0;
93 static inline void __setup_new_counter(struct counter *c, uint8_t start,
94 uint8_t stop, uint8_t stepping,
95 int type)
97 c->min = start;
98 c->max = stop;
99 c->inc = stepping;
100 c->val = (type == TYPE_INC) ? start : stop;
101 c->off = payload_last;
102 c->type = type;
105 static inline void __setup_new_randomizer(struct randomizer *r)
107 r->off = payload_last;
110 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
111 enum csum which)
113 s->off = payload_last - 1;
114 s->from = from;
115 s->to = to;
116 s->which = which;
119 static void realloc_packet(void)
121 if (test_ignore())
122 return;
124 plen++;
125 packets = xrealloc(packets, plen * sizeof(*packets));
127 __init_new_packet_slot(&packets[packet_last]);
129 dlen++;
130 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
132 __init_new_counter_slot(&packet_dyn[packetd_last]);
133 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
134 __init_new_csum_slot(&packet_dyn[packetd_last]);
137 static void set_byte(uint8_t val)
139 struct packet *pkt = &packets[packet_last];
141 if (test_ignore())
142 return;
144 pkt->len++;
145 pkt->payload = xrealloc(pkt->payload, pkt->len);
146 pkt->payload[payload_last] = val;
149 static void set_multi_byte(uint8_t *s, size_t len)
151 size_t i;
153 for (i = 0; i < len; ++i)
154 set_byte(s[i]);
157 static void set_fill(uint8_t val, size_t len)
159 size_t i;
160 struct packet *pkt = &packets[packet_last];
162 if (test_ignore())
163 return;
165 pkt->len += len;
166 pkt->payload = xrealloc(pkt->payload, pkt->len);
167 for (i = 0; i < len; ++i)
168 pkt->payload[payload_last - i] = val;
171 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
173 struct packet *pkt = &packets[packet_last];
174 struct packet_dyn *pktd = &packet_dyn[packetd_last];
176 pkt->len += 2;
177 pkt->payload = xrealloc(pkt->payload, pkt->len);
179 pktd->slen++;
180 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
182 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
185 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
187 struct packet *pkt = &packets[packet_last];
188 uint16_t sum;
189 uint8_t *psum;
191 sum = htons(calc_csum(pkt->payload + from, to - from, 0));
192 psum = (uint8_t *) &sum;
194 set_byte(psum[0]);
195 set_byte(psum[1]);
198 static inline bool is_dynamic_csum(enum csum which)
200 switch (which) {
201 case CSUM_UDP:
202 case CSUM_TCP:
203 case CSUM_UDP6:
204 case CSUM_TCP6:
205 return true;
206 default:
207 return false;
211 static void set_csum16(size_t from, size_t to, enum csum which)
213 struct packet *pkt = &packets[packet_last];
214 struct packet_dyn *pktd = &packet_dyn[packetd_last];
216 if (test_ignore())
217 return;
219 if (to < from) {
220 size_t tmp = to;
222 to = from;
223 from = tmp;
226 bug_on(!(from < to));
228 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
229 __set_csum16_dynamic(from, to, which);
230 else
231 __set_csum16_static(from, to, which);
234 static void set_rnd(size_t len)
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, pkt->len);
244 for (i = 0; i < len; ++i)
245 pkt->payload[payload_last - i] = (uint8_t) rand();
248 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
250 size_t i;
251 struct packet *pkt = &packets[packet_last];
253 if (test_ignore())
254 return;
256 pkt->len += len;
257 pkt->payload = xrealloc(pkt->payload, pkt->len);
258 for (i = 0; i < len; ++i) {
259 off_t off = len - 1 - i;
261 pkt->payload[payload_last - off] = start;
262 start += stepping;
266 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
268 size_t i;
269 struct packet *pkt = &packets[packet_last];
271 if (test_ignore())
272 return;
274 pkt->len += len;
275 pkt->payload = xrealloc(pkt->payload, pkt->len);
276 for (i = 0; i < len; ++i) {
277 int off = len - 1 - i;
279 pkt->payload[payload_last - off] = start;
280 start -= stepping;
284 static void set_dynamic_rnd(void)
286 struct packet *pkt = &packets[packet_last];
287 struct packet_dyn *pktd = &packet_dyn[packetd_last];
289 if (test_ignore())
290 return;
292 pkt->len++;
293 pkt->payload = xrealloc(pkt->payload, pkt->len);
295 pktd->rlen++;
296 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
298 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
301 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
302 int type)
304 struct packet *pkt = &packets[packet_last];
305 struct packet_dyn *pktd = &packet_dyn[packetd_last];
307 if (test_ignore())
308 return;
310 pkt->len++;
311 pkt->payload = xrealloc(pkt->payload, pkt->len);
313 pktd->clen++;
314 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
316 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
321 %union {
322 long long int number;
323 char *str;
326 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
327 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
329 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
331 %token number string
333 %type <number> number expression
334 %type <str> string
336 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
340 packets
341 : { }
342 | packets packet { }
343 | packets inline_comment { }
344 | packets K_WHITE { }
347 inline_comment
348 : K_COMMENT { }
351 cpu_delim
352 : ':' { }
353 | '-' { }
356 delimiter_nowhite
357 : ',' { }
358 | ',' K_WHITE { }
361 noenforce_white
362 : { }
363 | K_WHITE { }
364 | delimiter_nowhite { }
367 packet
368 : '{' noenforce_white payload noenforce_white '}' {
369 min_cpu = max_cpu = -1;
370 realloc_packet();
372 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
373 min_cpu = $3;
374 max_cpu = $5;
376 if (min_cpu > max_cpu) {
377 int tmp = min_cpu;
379 min_cpu = max_cpu;
380 max_cpu = tmp;
383 realloc_packet();
385 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
386 min_cpu = max_cpu = $3;
387 realloc_packet();
391 payload
392 : elem { }
393 | payload elem_delimiter { }
396 delimiter
397 : delimiter_nowhite { }
398 | K_WHITE { }
401 elem_delimiter
402 : delimiter elem { }
405 elem
406 : number { set_byte((uint8_t) $1); }
407 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
408 | fill { }
409 | rnd { }
410 | drnd { }
411 | seqinc { }
412 | seqdec { }
413 | dinc { }
414 | ddec { }
415 | csum { }
416 | const { }
417 | inline_comment { }
420 expression
421 : number
422 { $$ = $1; }
423 | expression '+' expression
424 { $$ = $1 + $3; }
425 | expression '-' expression
426 { $$ = $1 - $3; }
427 | expression '*' expression
428 { $$ = $1 * $3; }
429 | expression '/' expression
430 { $$ = $1 / $3; }
431 | expression '%' expression
432 { $$ = $1 % $3; }
433 | expression '&' expression
434 { $$ = $1 & $3; }
435 | expression '|' expression
436 { $$ = $1 | $3; }
437 | expression '^' expression
438 { $$ = $1 ^ $3; }
439 | expression '<' '<' expression
440 { $$ = $1 << $4; }
441 | expression '>' '>' expression
442 { $$ = $1 >> $4; }
443 | '-' expression
444 { $$ = -1 * $2; }
445 | '(' expression ')'
446 { $$ = $2;}
449 fill
450 : K_FILL '(' number delimiter number ')'
451 { set_fill($3, $5); }
454 const
455 : K_CONST8 '(' expression ')'
456 { set_byte((uint8_t) $3); }
457 | K_CONST16 '(' expression ')' {
458 uint16_t __c = cpu_to_be16((uint16_t) $3);
460 set_multi_byte((uint8_t *) &__c, sizeof(__c));
462 | K_CONST32 '(' expression ')' {
463 uint32_t __c = cpu_to_be32((uint32_t) $3);
465 set_multi_byte((uint8_t *) &__c, sizeof(__c));
467 | K_CONST64 '(' expression ')' {
468 uint64_t __c = cpu_to_be64((uint64_t) $3);
470 set_multi_byte((uint8_t *) &__c, sizeof(__c));
475 : K_RND '(' number ')'
476 { set_rnd($3); }
479 csum
480 : K_CSUMIP '(' number delimiter number ')'
481 { set_csum16($3, $5, CSUM_IP); }
482 | K_CSUMTCP '(' number delimiter number ')'
483 { set_csum16($3, $5, CSUM_TCP); }
484 | K_CSUMUDP '(' number delimiter number ')'
485 { set_csum16($3, $5, CSUM_UDP); }
486 | K_CSUMTCP6 '(' number delimiter number ')'
487 { set_csum16($3, $5, CSUM_TCP6); }
488 | K_CSUMUDP6 '(' number delimiter number ')'
489 { set_csum16($3, $5, CSUM_UDP6); }
492 seqinc
493 : K_SEQINC '(' number delimiter number ')'
494 { set_sequential_inc($3, $5, 1); }
495 | K_SEQINC '(' number delimiter number delimiter number ')'
496 { set_sequential_inc($3, $5, $7); }
499 seqdec
500 : K_SEQDEC '(' number delimiter number ')'
501 { set_sequential_dec($3, $5, 1); }
502 | K_SEQDEC '(' number delimiter number delimiter number ')'
503 { set_sequential_dec($3, $5, $7); }
506 drnd
507 : K_DRND '(' ')'
508 { set_dynamic_rnd(); }
509 | K_DRND '(' number ')'
511 int i, max = $3;
512 for (i = 0; i < max; ++i)
513 set_dynamic_rnd();
517 dinc
518 : K_DINC '(' number delimiter number ')'
519 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
520 | K_DINC '(' number delimiter number delimiter number ')'
521 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
524 ddec
525 : K_DDEC '(' number delimiter number ')'
526 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
527 | K_DDEC '(' number delimiter number delimiter number ')'
528 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
533 static void finalize_packet(void)
535 /* XXX hack ... we allocated one packet pointer too much */
536 plen--;
537 dlen--;
540 static void dump_conf(void)
542 size_t i, j;
544 for (i = 0; i < plen; ++i) {
545 printf("[%zu] pkt\n", i);
546 printf(" len %zu cnts %zu rnds %zu\n",
547 packets[i].len,
548 packet_dyn[i].clen,
549 packet_dyn[i].rlen);
551 printf(" payload ");
552 for (j = 0; j < packets[i].len; ++j)
553 printf("%02x ", packets[i].payload[j]);
554 printf("\n");
556 for (j = 0; j < packet_dyn[i].clen; ++j)
557 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
558 packet_dyn[i].cnt[j].min,
559 packet_dyn[i].cnt[j].max,
560 packet_dyn[i].cnt[j].inc,
561 (intmax_t)packet_dyn[i].cnt[j].off,
562 packet_dyn[i].cnt[j].type == TYPE_INC ?
563 "inc" : "dec");
565 for (j = 0; j < packet_dyn[i].rlen; ++j)
566 printf(" rnd%zu off %jd\n", j,
567 (intmax_t)packet_dyn[i].rnd[j].off);
571 void cleanup_packets(void)
573 size_t i;
575 for (i = 0; i < plen; ++i) {
576 if (packets[i].len > 0)
577 xfree(packets[i].payload);
580 free(packets);
582 for (i = 0; i < dlen; ++i) {
583 free(packet_dyn[i].cnt);
584 free(packet_dyn[i].rnd);
587 free(packet_dyn);
590 void compile_packets(char *file, bool verbose, unsigned int cpu, bool invoke_cpp)
592 char tmp_file[128];
593 int ret = -1;
595 memset(tmp_file, 0, sizeof(tmp_file));
596 our_cpu = cpu;
598 if (invoke_cpp) {
599 char cmd[256], *dir, *base, *a, *b;
601 dir = dirname((a = xstrdup(file)));
602 base = basename((b = xstrdup(file)));
604 slprintf(tmp_file, sizeof(tmp_file), "%s/.tmp-%u-%s", dir, rand(), base);
605 slprintf(cmd, sizeof(cmd), "cpp -I" ETCDIRE_STRING " %s > %s",
606 file, tmp_file);
607 if (system(cmd) != 0) {
608 fprintf(stderr, "Failed to invoke C preprocessor!\n");
609 goto err;
612 file = tmp_file;
613 xfree(a);
614 xfree(b);
617 if (!strncmp("-", file, strlen("-")))
618 yyin = stdin;
619 else
620 yyin = fopen(file, "r");
621 if (!yyin) {
622 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
623 goto err;
626 realloc_packet();
627 if (yyparse() != 0)
628 goto err;
629 finalize_packet();
631 if (our_cpu == 0 && verbose)
632 dump_conf();
634 ret = 0;
635 err:
636 fclose(yyin);
638 if (invoke_cpp)
639 unlink(tmp_file);
640 if (ret)
641 die();
644 void yyerror(const char *err)
646 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);