man: bpf: also mention that bpfc can be used for seccomp-BPF
[netsniff-ng.git] / trafgen_parser.y
blob71f5ddd4036bf01366a9fe18788cf16a25bb5ab6
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 int has_dynamic_elems(struct packet_dyn *p)
71 return (p->rlen + p->slen + p->clen);
74 static inline void __init_new_packet_slot(struct packet *slot)
76 slot->payload = NULL;
77 slot->len = 0;
80 static inline void __init_new_counter_slot(struct packet_dyn *slot)
82 slot->cnt = NULL;
83 slot->clen = 0;
86 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
88 slot->rnd = NULL;
89 slot->rlen = 0;
92 static inline void __init_new_csum_slot(struct packet_dyn *slot)
94 slot->csum = NULL;
95 slot->slen = 0;
98 static inline void __setup_new_counter(struct counter *c, uint8_t start,
99 uint8_t stop, uint8_t stepping,
100 int type)
102 c->min = start;
103 c->max = stop;
104 c->inc = stepping;
105 c->val = (type == TYPE_INC) ? start : stop;
106 c->off = payload_last;
107 c->type = type;
110 static inline void __setup_new_randomizer(struct randomizer *r)
112 r->off = payload_last;
115 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
116 enum csum which)
118 s->off = payload_last - 1;
119 s->from = from;
120 s->to = to;
121 s->which = which;
124 static void realloc_packet(void)
126 if (test_ignore())
127 return;
129 plen++;
130 packets = xrealloc(packets, 1, plen * sizeof(*packets));
132 __init_new_packet_slot(&packets[packet_last]);
134 dlen++;
135 packet_dyn = xrealloc(packet_dyn, 1, dlen * sizeof(*packet_dyn));
137 __init_new_counter_slot(&packet_dyn[packetd_last]);
138 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
139 __init_new_csum_slot(&packet_dyn[packetd_last]);
142 static void set_byte(uint8_t val)
144 struct packet *pkt = &packets[packet_last];
146 if (test_ignore())
147 return;
149 pkt->len++;
150 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
151 pkt->payload[payload_last] = val;
154 static void set_multi_byte(uint8_t *s, size_t len)
156 size_t i;
158 for (i = 0; i < len; ++i)
159 set_byte(s[i]);
162 static void set_fill(uint8_t val, size_t len)
164 size_t i;
165 struct packet *pkt = &packets[packet_last];
167 if (test_ignore())
168 return;
170 pkt->len += len;
171 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
172 for (i = 0; i < len; ++i)
173 pkt->payload[payload_last - i] = val;
176 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
178 struct packet *pkt = &packets[packet_last];
179 struct packet_dyn *pktd = &packet_dyn[packetd_last];
181 pkt->len += 2;
182 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
184 pktd->slen++;
185 pktd->csum = xrealloc(pktd->csum, 1, pktd->slen * sizeof(struct csum16));
187 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
190 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
192 struct packet *pkt = &packets[packet_last];
193 uint16_t sum;
194 uint8_t *psum;
196 sum = htons(calc_csum(pkt->payload + from, to - from, 0));
197 psum = (uint8_t *) &sum;
199 set_byte(psum[0]);
200 set_byte(psum[1]);
203 static void set_csum16(size_t from, size_t to, enum csum which)
205 int make_it_dynamic = 0;
206 struct packet *pkt = &packets[packet_last];
207 struct packet_dyn *pktd = &packet_dyn[packetd_last];
209 if (test_ignore())
210 return;
212 if (to < from) {
213 size_t tmp = to;
215 to = from;
216 from = tmp;
219 bug_on(!(from < to));
221 if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
222 make_it_dynamic = 1;
224 if (has_dynamic_elems(pktd) || make_it_dynamic)
225 __set_csum16_dynamic(from, to, which);
226 else
227 __set_csum16_static(from, to, which);
230 static void set_rnd(size_t len)
232 size_t i;
233 struct packet *pkt = &packets[packet_last];
235 if (test_ignore())
236 return;
238 pkt->len += len;
239 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
240 for (i = 0; i < len; ++i)
241 pkt->payload[payload_last - i] = (uint8_t) rand();
244 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
246 size_t i;
247 struct packet *pkt = &packets[packet_last];
249 if (test_ignore())
250 return;
252 pkt->len += len;
253 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
254 for (i = 0; i < len; ++i) {
255 off_t off = len - 1 - i;
257 pkt->payload[payload_last - off] = start;
258 start += stepping;
262 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
264 size_t i;
265 struct packet *pkt = &packets[packet_last];
267 if (test_ignore())
268 return;
270 pkt->len += len;
271 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
272 for (i = 0; i < len; ++i) {
273 int off = len - 1 - i;
275 pkt->payload[payload_last - off] = start;
276 start -= stepping;
280 static void set_dynamic_rnd(void)
282 struct packet *pkt = &packets[packet_last];
283 struct packet_dyn *pktd = &packet_dyn[packetd_last];
285 if (test_ignore())
286 return;
288 pkt->len++;
289 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
291 pktd->rlen++;
292 pktd->rnd = xrealloc(pktd->rnd, 1, pktd->rlen * sizeof(struct randomizer));
294 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
297 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
298 int type)
300 struct packet *pkt = &packets[packet_last];
301 struct packet_dyn *pktd = &packet_dyn[packetd_last];
303 if (test_ignore())
304 return;
306 pkt->len++;
307 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
309 pktd->clen++;
310 pktd->cnt =xrealloc(pktd->cnt, 1, pktd->clen * sizeof(struct counter));
312 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
317 %union {
318 long long int number;
319 char *str;
322 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
323 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
325 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
327 %token number string
329 %type <number> number expression
330 %type <str> string
332 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
336 packets
337 : { }
338 | packets packet { }
339 | packets inline_comment { }
340 | packets K_WHITE { }
343 inline_comment
344 : K_COMMENT { }
347 cpu_delim
348 : ':' { }
349 | '-' { }
352 delimiter_nowhite
353 : ',' { }
354 | ',' K_WHITE { }
357 noenforce_white
358 : { }
359 | K_WHITE { }
360 | delimiter_nowhite { }
363 packet
364 : '{' noenforce_white payload noenforce_white '}' {
365 min_cpu = max_cpu = -1;
366 realloc_packet();
368 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
369 min_cpu = $3;
370 max_cpu = $5;
372 if (min_cpu > max_cpu) {
373 int tmp = min_cpu;
375 min_cpu = max_cpu;
376 max_cpu = tmp;
379 realloc_packet();
381 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
382 min_cpu = max_cpu = $3;
383 realloc_packet();
387 payload
388 : elem { }
389 | payload elem_delimiter { }
392 delimiter
393 : delimiter_nowhite { }
394 | K_WHITE { }
397 elem_delimiter
398 : delimiter elem { }
401 elem
402 : number { set_byte((uint8_t) $1); }
403 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
404 | fill { }
405 | rnd { }
406 | drnd { }
407 | seqinc { }
408 | seqdec { }
409 | dinc { }
410 | ddec { }
411 | csum { }
412 | const { }
413 | inline_comment { }
416 expression
417 : number
418 { $$ = $1; }
419 | expression '+' expression
420 { $$ = $1 + $3; }
421 | expression '-' expression
422 { $$ = $1 - $3; }
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 << $4; }
437 | expression '>' '>' expression
438 { $$ = $1 >> $4; }
439 | '-' expression
440 { $$ = -1 * $2; }
441 | '(' expression ')'
442 { $$ = $2;}
445 fill
446 : K_FILL '(' number delimiter number ')'
447 { set_fill($3, $5); }
450 const
451 : K_CONST8 '(' expression ')'
452 { set_byte((uint8_t) $3); }
453 | K_CONST16 '(' expression ')' {
454 uint16_t __c = cpu_to_be16((uint16_t) $3);
456 set_multi_byte((uint8_t *) &__c, sizeof(__c));
458 | K_CONST32 '(' expression ')' {
459 uint32_t __c = cpu_to_be32((uint32_t) $3);
461 set_multi_byte((uint8_t *) &__c, sizeof(__c));
463 | K_CONST64 '(' expression ')' {
464 uint64_t __c = cpu_to_be64((uint64_t) $3);
466 set_multi_byte((uint8_t *) &__c, sizeof(__c));
471 : K_RND '(' number ')'
472 { set_rnd($3); }
475 csum
476 : K_CSUMIP '(' number delimiter number ')'
477 { set_csum16($3, $5, CSUM_IP); }
478 | K_CSUMTCP '(' number delimiter number ')'
479 { set_csum16($3, $5, CSUM_TCP); }
480 | K_CSUMUDP '(' number delimiter number ')'
481 { set_csum16($3, $5, CSUM_UDP); }
484 seqinc
485 : K_SEQINC '(' number delimiter number ')'
486 { set_sequential_inc($3, $5, 1); }
487 | K_SEQINC '(' number delimiter number delimiter number ')'
488 { set_sequential_inc($3, $5, $7); }
491 seqdec
492 : K_SEQDEC '(' number delimiter number ')'
493 { set_sequential_dec($3, $5, 1); }
494 | K_SEQDEC '(' number delimiter number delimiter number ')'
495 { set_sequential_dec($3, $5, $7); }
498 drnd
499 : K_DRND '(' ')'
500 { set_dynamic_rnd(); }
501 | K_DRND '(' number ')'
503 int i, max = $3;
504 for (i = 0; i < max; ++i)
505 set_dynamic_rnd();
509 dinc
510 : K_DINC '(' number delimiter number ')'
511 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
512 | K_DINC '(' number delimiter number delimiter number ')'
513 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
516 ddec
517 : K_DDEC '(' number delimiter number ')'
518 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
519 | K_DDEC '(' number delimiter number delimiter number ')'
520 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
525 static void finalize_packet(void)
527 /* XXX hack ... we allocated one packet pointer too much */
528 plen--;
529 dlen--;
532 static void dump_conf(void)
534 size_t i, j;
536 for (i = 0; i < plen; ++i) {
537 printf("[%zu] pkt\n", i);
538 printf(" len %zu cnts %zu rnds %zu\n",
539 packets[i].len,
540 packet_dyn[i].clen,
541 packet_dyn[i].rlen);
543 printf(" payload ");
544 for (j = 0; j < packets[i].len; ++j)
545 printf("%02x ", packets[i].payload[j]);
546 printf("\n");
548 for (j = 0; j < packet_dyn[i].clen; ++j)
549 printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j,
550 packet_dyn[i].cnt[j].min,
551 packet_dyn[i].cnt[j].max,
552 packet_dyn[i].cnt[j].inc,
553 packet_dyn[i].cnt[j].off,
554 packet_dyn[i].cnt[j].type == TYPE_INC ?
555 "inc" : "dec");
557 for (j = 0; j < packet_dyn[i].rlen; ++j)
558 printf(" rnd%zu off %ld\n", j,
559 packet_dyn[i].rnd[j].off);
563 void cleanup_packets(void)
565 size_t i;
567 for (i = 0; i < plen; ++i) {
568 if (packets[i].len > 0)
569 xfree(packets[i].payload);
572 free(packets);
574 for (i = 0; i < dlen; ++i) {
575 free(packet_dyn[i].cnt);
576 free(packet_dyn[i].rnd);
579 free(packet_dyn);
582 int compile_packets(char *file, int verbose, int cpu, bool invoke_cpp)
584 char tmp_file[128];
586 memset(tmp_file, 0, sizeof(tmp_file));
587 our_cpu = cpu;
589 if (invoke_cpp) {
590 char cmd[256], *dir, *base, *a, *b;
592 dir = dirname((a = xstrdup(file)));
593 base = basename((b = xstrdup(file)));
595 slprintf(tmp_file, sizeof(tmp_file), "%s/.tmp-%u-%s", dir, rand(), base);
596 slprintf(cmd, sizeof(cmd), "cpp -I" PREFIX_STRING
597 "/etc/netsniff-ng/ %s > %s", file, tmp_file);
598 system(cmd);
600 file = tmp_file;
601 xfree(a);
602 xfree(b);
605 if (!strncmp("-", file, strlen("-")))
606 yyin = stdin;
607 else
608 yyin = fopen(file, "r");
609 if (!yyin)
610 panic("Cannot open %s: %s!\n", file, strerror(errno));
612 realloc_packet();
613 yyparse();
614 finalize_packet();
616 if (our_cpu == 0 && verbose)
617 dump_conf();
619 fclose(yyin);
620 if (invoke_cpp)
621 unlink(tmp_file);
623 return 0;
626 void yyerror(const char *err)
628 panic("Syntax error at line%d, at char '%s'! %s!\n", yylineno, yytext, err);