xutils: remove unused declaration
[netsniff-ng.git] / trafgen_parser.y
blob85d7b01d24acf2cb7aa855b0f1f0e3efdf872e8f
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 "xutils.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 yyerror(const char *);
39 extern int yylineno;
40 extern char *yytext;
42 extern struct packet *packets;
43 extern size_t plen;
45 #define packet_last (plen - 1)
47 #define payload_last (packets[packet_last].len - 1)
49 extern struct packet_dyn *packet_dyn;
50 extern size_t dlen;
52 #define packetd_last (dlen - 1)
54 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
55 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
56 #define packetds_last (packet_dyn[packetd_last].slen - 1)
58 static int our_cpu, min_cpu = -1, max_cpu = -1;
60 static inline int test_ignore(void)
62 if (min_cpu < 0 && max_cpu < 0)
63 return 0;
64 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
65 return 0;
66 else
67 return 1;
70 static inline int has_dynamic_elems(struct packet_dyn *p)
72 return (p->rlen + p->slen + p->clen);
75 static inline void __init_new_packet_slot(struct packet *slot)
77 slot->payload = NULL;
78 slot->len = 0;
81 static inline void __init_new_counter_slot(struct packet_dyn *slot)
83 slot->cnt = NULL;
84 slot->clen = 0;
87 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
89 slot->rnd = NULL;
90 slot->rlen = 0;
93 static inline void __init_new_csum_slot(struct packet_dyn *slot)
95 slot->csum = NULL;
96 slot->slen = 0;
99 static inline void __setup_new_counter(struct counter *c, uint8_t start,
100 uint8_t stop, uint8_t stepping,
101 int type)
103 c->min = start;
104 c->max = stop;
105 c->inc = stepping;
106 c->val = (type == TYPE_INC) ? start : stop;
107 c->off = payload_last;
108 c->type = type;
111 static inline void __setup_new_randomizer(struct randomizer *r)
113 r->off = payload_last;
116 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
117 enum csum which)
119 s->off = payload_last - 1;
120 s->from = from;
121 s->to = to;
122 s->which = which;
125 static void realloc_packet(void)
127 if (test_ignore())
128 return;
130 plen++;
131 packets = xrealloc(packets, 1, plen * sizeof(*packets));
133 __init_new_packet_slot(&packets[packet_last]);
135 dlen++;
136 packet_dyn = xrealloc(packet_dyn, 1, dlen * sizeof(*packet_dyn));
138 __init_new_counter_slot(&packet_dyn[packetd_last]);
139 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
140 __init_new_csum_slot(&packet_dyn[packetd_last]);
143 static void set_byte(uint8_t val)
145 struct packet *pkt = &packets[packet_last];
147 if (test_ignore())
148 return;
150 pkt->len++;
151 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
152 pkt->payload[payload_last] = val;
155 static void set_multi_byte(uint8_t *s, size_t len)
157 size_t i;
159 for (i = 0; i < len; ++i)
160 set_byte(s[i]);
163 static void set_fill(uint8_t val, size_t len)
165 size_t i;
166 struct packet *pkt = &packets[packet_last];
168 if (test_ignore())
169 return;
171 pkt->len += len;
172 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
173 for (i = 0; i < len; ++i)
174 pkt->payload[payload_last - i] = val;
177 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
179 struct packet *pkt = &packets[packet_last];
180 struct packet_dyn *pktd = &packet_dyn[packetd_last];
182 pkt->len += 2;
183 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
185 pktd->slen++;
186 pktd->csum = xrealloc(pktd->csum, 1, pktd->slen * sizeof(struct csum16));
188 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
191 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
193 struct packet *pkt = &packets[packet_last];
194 uint16_t sum;
195 uint8_t *psum;
197 sum = htons(calc_csum(pkt->payload + from, to - from, 0));
198 psum = (uint8_t *) &sum;
200 set_byte(psum[0]);
201 set_byte(psum[1]);
204 static void set_csum16(size_t from, size_t to, enum csum which)
206 int make_it_dynamic = 0;
207 struct packet *pkt = &packets[packet_last];
208 struct packet_dyn *pktd = &packet_dyn[packetd_last];
210 if (test_ignore())
211 return;
213 if (to < from) {
214 size_t tmp = to;
216 to = from;
217 from = tmp;
220 bug_on(!(from < to));
222 if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
223 make_it_dynamic = 1;
225 if (has_dynamic_elems(pktd) || make_it_dynamic)
226 __set_csum16_dynamic(from, to, which);
227 else
228 __set_csum16_static(from, to, which);
231 static void set_rnd(size_t len)
233 size_t i;
234 struct packet *pkt = &packets[packet_last];
236 if (test_ignore())
237 return;
239 pkt->len += len;
240 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
241 for (i = 0; i < len; ++i)
242 pkt->payload[payload_last - i] = (uint8_t) rand();
245 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
247 size_t i;
248 struct packet *pkt = &packets[packet_last];
250 if (test_ignore())
251 return;
253 pkt->len += len;
254 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
255 for (i = 0; i < len; ++i) {
256 off_t off = len - 1 - i;
258 pkt->payload[payload_last - off] = start;
259 start += stepping;
263 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
265 size_t i;
266 struct packet *pkt = &packets[packet_last];
268 if (test_ignore())
269 return;
271 pkt->len += len;
272 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
273 for (i = 0; i < len; ++i) {
274 int off = len - 1 - i;
276 pkt->payload[payload_last - off] = start;
277 start -= stepping;
281 static void set_dynamic_rnd(void)
283 struct packet *pkt = &packets[packet_last];
284 struct packet_dyn *pktd = &packet_dyn[packetd_last];
286 if (test_ignore())
287 return;
289 pkt->len++;
290 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
292 pktd->rlen++;
293 pktd->rnd = xrealloc(pktd->rnd, 1, pktd->rlen * sizeof(struct randomizer));
295 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
298 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
299 int type)
301 struct packet *pkt = &packets[packet_last];
302 struct packet_dyn *pktd = &packet_dyn[packetd_last];
304 if (test_ignore())
305 return;
307 pkt->len++;
308 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
310 pktd->clen++;
311 pktd->cnt =xrealloc(pktd->cnt, 1, pktd->clen * sizeof(struct counter));
313 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
318 %union {
319 long long int number;
320 char *str;
323 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
324 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
326 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
328 %token number string
330 %type <number> number expression
331 %type <str> string
333 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
337 packets
338 : { }
339 | packets packet { }
340 | packets inline_comment { }
341 | packets K_WHITE { }
344 inline_comment
345 : K_COMMENT { }
348 cpu_delim
349 : ':' { }
350 | '-' { }
353 delimiter_nowhite
354 : ',' { }
355 | ',' K_WHITE { }
358 noenforce_white
359 : { }
360 | K_WHITE { }
361 | delimiter_nowhite { }
364 packet
365 : '{' noenforce_white payload noenforce_white '}' {
366 min_cpu = max_cpu = -1;
367 realloc_packet();
369 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
370 min_cpu = $3;
371 max_cpu = $5;
373 if (min_cpu > max_cpu) {
374 int tmp = min_cpu;
376 min_cpu = max_cpu;
377 max_cpu = tmp;
380 realloc_packet();
382 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
383 min_cpu = max_cpu = $3;
384 realloc_packet();
388 payload
389 : elem { }
390 | payload elem_delimiter { }
393 delimiter
394 : delimiter_nowhite { }
395 | K_WHITE { }
398 elem_delimiter
399 : delimiter elem { }
402 elem
403 : number { set_byte((uint8_t) $1); }
404 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
405 | fill { }
406 | rnd { }
407 | drnd { }
408 | seqinc { }
409 | seqdec { }
410 | dinc { }
411 | ddec { }
412 | csum { }
413 | const { }
414 | inline_comment { }
417 expression
418 : number
419 { $$ = $1; }
420 | expression '+' expression
421 { $$ = $1 + $3; }
422 | expression '-' expression
423 { $$ = $1 - $3; }
424 | expression '*' expression
425 { $$ = $1 * $3; }
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 << $4; }
438 | expression '>' '>' expression
439 { $$ = $1 >> $4; }
440 | '-' expression
441 { $$ = -1 * $2; }
442 | '(' expression ')'
443 { $$ = $2;}
446 fill
447 : K_FILL '(' number delimiter number ')'
448 { set_fill($3, $5); }
451 const
452 : K_CONST8 '(' expression ')'
453 { set_byte((uint8_t) $3); }
454 | K_CONST16 '(' expression ')' {
455 uint16_t __c = cpu_to_be16((uint16_t) $3);
457 set_multi_byte((uint8_t *) &__c, sizeof(__c));
459 | K_CONST32 '(' expression ')' {
460 uint32_t __c = cpu_to_be32((uint32_t) $3);
462 set_multi_byte((uint8_t *) &__c, sizeof(__c));
464 | K_CONST64 '(' expression ')' {
465 uint64_t __c = cpu_to_be64((uint64_t) $3);
467 set_multi_byte((uint8_t *) &__c, sizeof(__c));
472 : K_RND '(' number ')'
473 { set_rnd($3); }
476 csum
477 : K_CSUMIP '(' number delimiter number ')'
478 { set_csum16($3, $5, CSUM_IP); }
479 | K_CSUMTCP '(' number delimiter number ')'
480 { set_csum16($3, $5, CSUM_TCP); }
481 | K_CSUMUDP '(' number delimiter number ')'
482 { set_csum16($3, $5, CSUM_UDP); }
485 seqinc
486 : K_SEQINC '(' number delimiter number ')'
487 { set_sequential_inc($3, $5, 1); }
488 | K_SEQINC '(' number delimiter number delimiter number ')'
489 { set_sequential_inc($3, $5, $7); }
492 seqdec
493 : K_SEQDEC '(' number delimiter number ')'
494 { set_sequential_dec($3, $5, 1); }
495 | K_SEQDEC '(' number delimiter number delimiter number ')'
496 { set_sequential_dec($3, $5, $7); }
499 drnd
500 : K_DRND '(' ')'
501 { set_dynamic_rnd(); }
502 | K_DRND '(' number ')'
504 int i, max = $3;
505 for (i = 0; i < max; ++i)
506 set_dynamic_rnd();
510 dinc
511 : K_DINC '(' number delimiter number ')'
512 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
513 | K_DINC '(' number delimiter number delimiter number ')'
514 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
517 ddec
518 : K_DDEC '(' number delimiter number ')'
519 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
520 | K_DDEC '(' number delimiter number delimiter number ')'
521 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
526 static void finalize_packet(void)
528 /* XXX hack ... we allocated one packet pointer too much */
529 plen--;
530 dlen--;
533 static void dump_conf(void)
535 size_t i, j;
537 for (i = 0; i < plen; ++i) {
538 printf("[%zu] pkt\n", i);
539 printf(" len %zu cnts %zu rnds %zu\n",
540 packets[i].len,
541 packet_dyn[i].clen,
542 packet_dyn[i].rlen);
544 printf(" payload ");
545 for (j = 0; j < packets[i].len; ++j)
546 printf("%02x ", packets[i].payload[j]);
547 printf("\n");
549 for (j = 0; j < packet_dyn[i].clen; ++j)
550 printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j,
551 packet_dyn[i].cnt[j].min,
552 packet_dyn[i].cnt[j].max,
553 packet_dyn[i].cnt[j].inc,
554 packet_dyn[i].cnt[j].off,
555 packet_dyn[i].cnt[j].type == TYPE_INC ?
556 "inc" : "dec");
558 for (j = 0; j < packet_dyn[i].rlen; ++j)
559 printf(" rnd%zu off %ld\n", j,
560 packet_dyn[i].rnd[j].off);
564 void cleanup_packets(void)
566 size_t i;
568 for (i = 0; i < plen; ++i) {
569 if (packets[i].len > 0)
570 xfree(packets[i].payload);
573 free(packets);
575 for (i = 0; i < dlen; ++i) {
576 free(packet_dyn[i].cnt);
577 free(packet_dyn[i].rnd);
580 free(packet_dyn);
583 int compile_packets(char *file, int verbose, int cpu, bool invoke_cpp)
585 char tmp_file[128];
587 memset(tmp_file, 0, sizeof(tmp_file));
588 our_cpu = cpu;
590 if (invoke_cpp) {
591 char cmd[256], *dir, *base, *a, *b;
593 dir = dirname((a = xstrdup(file)));
594 base = basename((b = xstrdup(file)));
596 slprintf(tmp_file, sizeof(tmp_file), "%s/.tmp-%u-%s", dir, rand(), base);
597 slprintf(cmd, sizeof(cmd), "cpp -I" PREFIX_STRING
598 "/etc/netsniff-ng/ %s > %s", file, tmp_file);
599 system(cmd);
601 file = tmp_file;
602 xfree(a);
603 xfree(b);
606 if (!strncmp("-", file, strlen("-")))
607 yyin = stdin;
608 else
609 yyin = fopen(file, "r");
610 if (!yyin)
611 panic("Cannot open %s: %s!\n", file, strerror(errno));
613 realloc_packet();
614 yyparse();
615 finalize_packet();
617 if (our_cpu == 0 && verbose)
618 dump_conf();
620 fclose(yyin);
621 if (invoke_cpp)
622 unlink(tmp_file);
624 return 0;
627 void yyerror(const char *err)
629 panic("Syntax error at line%d, at char '%s'! %s!\n", yylineno, yytext, err);