make: minor: update comment
[netsniff-ng.git] / trafgen_parser.y
blobe49cc87ac09aecd9133c6352e8595b33eca9b4e2
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>
20 #include "xmalloc.h"
21 #include "trafgen_parser.tab.h"
22 #include "trafgen_conf.h"
23 #include "built_in.h"
24 #include "die.h"
25 #include "csum.h"
26 #include "xutils.h"
28 #define YYERROR_VERBOSE 0
29 #define YYDEBUG 0
30 #define YYENABLE_NLS 1
31 #define YYLTYPE_IS_TRIVIAL 1
32 #define ENABLE_NLS 1
34 extern FILE *yyin;
35 extern int yylex(void);
36 extern void yyerror(const char *);
37 extern int yylineno;
38 extern char *yytext;
40 extern struct packet *packets;
41 extern size_t plen;
43 #define packet_last (plen - 1)
45 #define payload_last (packets[packet_last].len - 1)
47 extern struct packet_dyn *packet_dyn;
48 extern size_t dlen;
50 #define packetd_last (dlen - 1)
52 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
53 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
54 #define packetds_last (packet_dyn[packetd_last].slen - 1)
56 static int our_cpu, min_cpu = -1, max_cpu = -1;
58 static inline int test_ignore(void)
60 if (min_cpu < 0 && max_cpu < 0)
61 return 0;
62 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
63 return 0;
64 else
65 return 1;
68 static inline int has_dynamic_elems(struct packet_dyn *p)
70 return (p->rlen + p->slen + p->clen);
73 static inline void __init_new_packet_slot(struct packet *slot)
75 slot->payload = NULL;
76 slot->len = 0;
79 static inline void __init_new_counter_slot(struct packet_dyn *slot)
81 slot->cnt = NULL;
82 slot->clen = 0;
85 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
87 slot->rnd = NULL;
88 slot->rlen = 0;
91 static inline void __init_new_csum_slot(struct packet_dyn *slot)
93 slot->csum = NULL;
94 slot->slen = 0;
97 static inline void __setup_new_counter(struct counter *c, uint8_t start,
98 uint8_t stop, uint8_t stepping,
99 int type)
101 c->min = start;
102 c->max = stop;
103 c->inc = stepping;
104 c->val = (type == TYPE_INC) ? start : stop;
105 c->off = payload_last;
106 c->type = type;
109 static inline void __setup_new_randomizer(struct randomizer *r)
111 r->off = payload_last;
114 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
115 enum csum which)
117 s->off = payload_last - 1;
118 s->from = from;
119 s->to = to;
120 s->which = which;
123 static void realloc_packet(void)
125 if (test_ignore())
126 return;
128 plen++;
129 packets = xrealloc(packets, 1, plen * sizeof(*packets));
131 __init_new_packet_slot(&packets[packet_last]);
133 dlen++;
134 packet_dyn = xrealloc(packet_dyn, 1, dlen * sizeof(*packet_dyn));
136 __init_new_counter_slot(&packet_dyn[packetd_last]);
137 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
138 __init_new_csum_slot(&packet_dyn[packetd_last]);
141 static void set_byte(uint8_t val)
143 struct packet *pkt = &packets[packet_last];
145 if (test_ignore())
146 return;
148 pkt->len++;
149 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
150 pkt->payload[payload_last] = val;
153 static void set_multi_byte(uint8_t *s, size_t len)
155 int i;
157 for (i = 0; i < len; ++i)
158 set_byte(s[i]);
161 static void set_fill(uint8_t val, size_t len)
163 size_t i;
164 struct packet *pkt = &packets[packet_last];
166 if (test_ignore())
167 return;
169 pkt->len += len;
170 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
171 for (i = 0; i < len; ++i)
172 pkt->payload[payload_last - i] = val;
175 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
177 struct packet *pkt = &packets[packet_last];
178 struct packet_dyn *pktd = &packet_dyn[packetd_last];
180 pkt->len += 2;
181 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
183 pktd->slen++;
184 pktd->csum = xrealloc(pktd->csum, 1, pktd->slen * sizeof(struct csum16));
186 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
189 static void __set_csum16_static(size_t from, size_t to, enum csum which)
191 struct packet *pkt = &packets[packet_last];
192 uint16_t sum;
193 uint8_t *psum;
195 sum = htons(calc_csum(pkt->payload + from, to - from, 0));
196 psum = (uint8_t *) &sum;
198 set_byte(psum[0]);
199 set_byte(psum[1]);
202 static void set_csum16(size_t from, size_t to, enum csum which)
204 int make_it_dynamic = 0;
205 struct packet *pkt = &packets[packet_last];
206 struct packet_dyn *pktd = &packet_dyn[packetd_last];
208 if (test_ignore())
209 return;
211 if (to < from) {
212 size_t tmp = to;
214 to = from;
215 from = tmp;
218 bug_on(!(from < to));
220 if (to >= pkt->len || which == CSUM_TCP || which == CSUM_UDP)
221 make_it_dynamic = 1;
223 if (has_dynamic_elems(pktd) || make_it_dynamic)
224 __set_csum16_dynamic(from, to, which);
225 else
226 __set_csum16_static(from, to, which);
229 static void set_rnd(size_t len)
231 size_t i;
232 struct packet *pkt = &packets[packet_last];
234 if (test_ignore())
235 return;
237 pkt->len += len;
238 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
239 for (i = 0; i < len; ++i)
240 pkt->payload[payload_last - i] = (uint8_t) rand();
243 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
245 size_t i;
246 struct packet *pkt = &packets[packet_last];
248 if (test_ignore())
249 return;
251 pkt->len += len;
252 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
253 for (i = 0; i < len; ++i) {
254 off_t off = len - 1 - i;
256 pkt->payload[payload_last - off] = start;
257 start += stepping;
261 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
263 size_t i;
264 struct packet *pkt = &packets[packet_last];
266 if (test_ignore())
267 return;
269 pkt->len += len;
270 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
271 for (i = 0; i < len; ++i) {
272 int off = len - 1 - i;
274 pkt->payload[payload_last - off] = start;
275 start -= stepping;
279 static void set_dynamic_rnd(void)
281 struct packet *pkt = &packets[packet_last];
282 struct packet_dyn *pktd = &packet_dyn[packetd_last];
284 if (test_ignore())
285 return;
287 pkt->len++;
288 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
290 pktd->rlen++;
291 pktd->rnd = xrealloc(pktd->rnd, 1, pktd->rlen * sizeof(struct randomizer));
293 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
296 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
297 int type)
299 struct packet *pkt = &packets[packet_last];
300 struct packet_dyn *pktd = &packet_dyn[packetd_last];
302 if (test_ignore())
303 return;
305 pkt->len++;
306 pkt->payload = xrealloc(pkt->payload, 1, pkt->len);
308 pktd->clen++;
309 pktd->cnt =xrealloc(pktd->cnt, 1, pktd->clen * sizeof(struct counter));
311 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
316 %union {
317 long long int number;
318 char *str;
321 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
322 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CONST8 K_CONST16 K_CONST32 K_CONST64
324 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
326 %token number string
328 %type <number> number expression
329 %type <str> string
331 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
335 packets
336 : { }
337 | packets packet { }
338 | packets inline_comment { }
339 | packets K_WHITE { }
342 inline_comment
343 : K_COMMENT { }
346 packet
347 : '{' delimiter payload delimiter '}' {
348 min_cpu = max_cpu = -1;
349 realloc_packet();
351 | K_CPU '(' number ':' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
352 min_cpu = $3;
353 max_cpu = $5;
355 if (min_cpu > max_cpu) {
356 int tmp = min_cpu;
358 min_cpu = max_cpu;
359 max_cpu = tmp;
362 realloc_packet();
364 | K_CPU '(' number ')' ':' K_WHITE '{' delimiter payload delimiter '}' {
365 min_cpu = max_cpu = $3;
366 realloc_packet();
370 payload
371 : elem { }
372 | payload elem_delimiter { }
375 delimiter
376 : ',' { }
377 | K_WHITE { }
378 | ',' K_WHITE { }
381 elem_delimiter
382 : delimiter elem { }
385 elem
386 : number { set_byte((uint8_t) $1); }
387 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
388 | fill { }
389 | rnd { }
390 | drnd { }
391 | seqinc { }
392 | seqdec { }
393 | dinc { }
394 | ddec { }
395 | csum { }
396 | const { }
397 | inline_comment { }
400 expression
401 : number
402 { $$ = $1; }
403 | expression '+' expression
404 { $$ = $1 + $3; }
405 | expression '-' expression
406 { $$ = $1 - $3; }
407 | expression '*' expression
408 { $$ = $1 * $3; }
409 | expression '/' expression
410 { $$ = $1 / $3; }
411 | expression '%' expression
412 { $$ = $1 % $3; }
413 | expression '&' expression
414 { $$ = $1 & $3; }
415 | expression '|' expression
416 { $$ = $1 | $3; }
417 | expression '^' expression
418 { $$ = $1 ^ $3; }
419 | expression '<' '<' expression
420 { $$ = $1 << $4; }
421 | expression '>' '>' expression
422 { $$ = $1 >> $4; }
423 | '(' expression ')'
424 { $$ = $2;}
427 fill
428 : K_FILL '(' number delimiter number ')'
429 { set_fill($3, $5); }
432 const
433 : K_CONST8 '(' expression ')'
434 { set_byte((uint8_t) $3); }
435 | K_CONST16 '(' expression ')' {
436 uint16_t __c = cpu_to_be16((uint16_t) $3);
438 set_multi_byte((uint8_t *) &__c, sizeof(__c));
440 | K_CONST32 '(' expression ')' {
441 uint32_t __c = cpu_to_be32((uint32_t) $3);
443 set_multi_byte((uint8_t *) &__c, sizeof(__c));
445 | K_CONST64 '(' expression ')' {
446 uint64_t __c = cpu_to_be64((uint64_t) $3);
448 set_multi_byte((uint8_t *) &__c, sizeof(__c));
453 : K_RND '(' number ')'
454 { set_rnd($3); }
457 csum
458 : K_CSUMIP '(' number delimiter number ')'
459 { set_csum16($3, $5, CSUM_IP); }
460 | K_CSUMTCP '(' number delimiter number ')'
461 { set_csum16($3, $5, CSUM_TCP); }
462 | K_CSUMUDP '(' number delimiter number ')'
463 { set_csum16($3, $5, CSUM_UDP); }
466 seqinc
467 : K_SEQINC '(' number delimiter number ')'
468 { set_sequential_inc($3, $5, 1); }
469 | K_SEQINC '(' number delimiter number delimiter number ')'
470 { set_sequential_inc($3, $5, $7); }
473 seqdec
474 : K_SEQDEC '(' number delimiter number ')'
475 { set_sequential_dec($3, $5, 1); }
476 | K_SEQDEC '(' number delimiter number delimiter number ')'
477 { set_sequential_dec($3, $5, $7); }
480 drnd
481 : K_DRND '(' ')'
482 { set_dynamic_rnd(); }
483 | K_DRND '(' number ')'
485 int i, max = $3;
486 for (i = 0; i < max; ++i)
487 set_dynamic_rnd();
491 dinc
492 : K_DINC '(' number delimiter number ')'
493 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
494 | K_DINC '(' number delimiter number delimiter number ')'
495 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
498 ddec
499 : K_DDEC '(' number delimiter number ')'
500 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
501 | K_DDEC '(' number delimiter number delimiter number ')'
502 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
507 static void finalize_packet(void)
509 /* XXX hack ... we allocated one packet pointer too much */
510 plen--;
511 dlen--;
514 static void dump_conf(void)
516 size_t i, j;
518 for (i = 0; i < plen; ++i) {
519 printf("[%zu] pkt\n", i);
520 printf(" len %zu cnts %zu rnds %zu\n",
521 packets[i].len,
522 packet_dyn[i].clen,
523 packet_dyn[i].rlen);
525 printf(" payload ");
526 for (j = 0; j < packets[i].len; ++j)
527 printf("%02x ", packets[i].payload[j]);
528 printf("\n");
530 for (j = 0; j < packet_dyn[i].clen; ++j)
531 printf(" cnt%zu [%u,%u], inc %u, off %ld type %s\n", j,
532 packet_dyn[i].cnt[j].min,
533 packet_dyn[i].cnt[j].max,
534 packet_dyn[i].cnt[j].inc,
535 packet_dyn[i].cnt[j].off,
536 packet_dyn[i].cnt[j].type == TYPE_INC ?
537 "inc" : "dec");
539 for (j = 0; j < packet_dyn[i].rlen; ++j)
540 printf(" rnd%zu off %ld\n", j,
541 packet_dyn[i].rnd[j].off);
545 void cleanup_packets(void)
547 size_t i;
549 for (i = 0; i < plen; ++i) {
550 if (packets[i].len > 0)
551 xfree(packets[i].payload);
554 free(packets);
556 for (i = 0; i < dlen; ++i) {
557 free(packet_dyn[i].cnt);
558 free(packet_dyn[i].rnd);
561 free(packet_dyn);
564 int compile_packets(char *file, int verbose, int cpu, bool invoke_cpp)
566 char tmp_file[128];
568 memset(tmp_file, 0, sizeof(tmp_file));
569 our_cpu = cpu;
571 if (invoke_cpp) {
572 char cmd[256];
574 slprintf(tmp_file, sizeof(tmp_file), ".tmp-%u-%s", rand(), file);
575 slprintf(cmd, sizeof(cmd), "cpp %s > %s", file, tmp_file);
576 system(cmd);
578 file = tmp_file;
581 if (!strncmp("-", file, strlen("-")))
582 yyin = stdin;
583 else
584 yyin = fopen(file, "r");
585 if (!yyin)
586 panic("Cannot open %s: %s!\n", file, strerror(errno));
588 realloc_packet();
589 yyparse();
590 finalize_packet();
592 if (our_cpu == 0 && verbose)
593 dump_conf();
595 fclose(yyin);
596 if (invoke_cpp)
597 unlink(tmp_file);
599 return 0;
602 void yyerror(const char *err)
604 panic("Syntax error at line%d, at char '%s'! %s!\n", yylineno, yytext, err);