netsniff-ng: nlmsg: Print not dissected attribute type number
[netsniff-ng.git] / trafgen_parser.y
bloba05b7e81488969c1c8466f72505103d47d146b69
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 yy_scan_string(char *);
38 extern void yylex_destroy();
39 extern void yyerror(const char *);
40 extern int yylineno;
41 extern char *yytext;
43 extern struct packet *packets;
44 extern size_t plen;
46 #define packet_last (plen - 1)
48 #define payload_last (packets[packet_last].len - 1)
50 extern struct packet_dyn *packet_dyn;
51 extern size_t dlen;
53 #define packetd_last (dlen - 1)
55 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
56 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
57 #define packetds_last (packet_dyn[packetd_last].slen - 1)
59 static int our_cpu, min_cpu = -1, max_cpu = -1;
61 static inline int test_ignore(void)
63 if (min_cpu < 0 && max_cpu < 0)
64 return 0;
65 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
66 return 0;
67 else
68 return 1;
71 static inline void __init_new_packet_slot(struct packet *slot)
73 slot->payload = NULL;
74 slot->len = 0;
77 static inline void __init_new_counter_slot(struct packet_dyn *slot)
79 slot->cnt = NULL;
80 slot->clen = 0;
83 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
85 slot->rnd = NULL;
86 slot->rlen = 0;
89 static inline void __init_new_csum_slot(struct packet_dyn *slot)
91 slot->csum = NULL;
92 slot->slen = 0;
95 static inline void __setup_new_counter(struct counter *c, uint8_t start,
96 uint8_t stop, uint8_t stepping,
97 int type)
99 c->min = start;
100 c->max = stop;
101 c->inc = stepping;
102 c->val = (type == TYPE_INC) ? start : stop;
103 c->off = payload_last;
104 c->type = type;
107 static inline void __setup_new_randomizer(struct randomizer *r)
109 r->off = payload_last;
112 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
113 enum csum which)
115 s->off = payload_last - 1;
116 s->from = from;
117 s->to = to;
118 s->which = which;
121 static void realloc_packet(void)
123 if (test_ignore())
124 return;
126 plen++;
127 packets = xrealloc(packets, plen * sizeof(*packets));
129 __init_new_packet_slot(&packets[packet_last]);
131 dlen++;
132 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
134 __init_new_counter_slot(&packet_dyn[packetd_last]);
135 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
136 __init_new_csum_slot(&packet_dyn[packetd_last]);
139 static void set_byte(uint8_t val)
141 struct packet *pkt = &packets[packet_last];
143 if (test_ignore())
144 return;
146 pkt->len++;
147 pkt->payload = xrealloc(pkt->payload, pkt->len);
148 pkt->payload[payload_last] = val;
151 static void set_multi_byte(uint8_t *s, size_t len)
153 size_t i;
155 for (i = 0; i < len; ++i)
156 set_byte(s[i]);
159 static void set_fill(uint8_t val, size_t len)
161 size_t i;
162 struct packet *pkt = &packets[packet_last];
164 if (test_ignore())
165 return;
167 pkt->len += len;
168 pkt->payload = xrealloc(pkt->payload, pkt->len);
169 for (i = 0; i < len; ++i)
170 pkt->payload[payload_last - i] = val;
173 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
175 struct packet *pkt = &packets[packet_last];
176 struct packet_dyn *pktd = &packet_dyn[packetd_last];
178 pkt->len += 2;
179 pkt->payload = xrealloc(pkt->payload, pkt->len);
181 pktd->slen++;
182 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
184 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
187 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
189 struct packet *pkt = &packets[packet_last];
190 uint16_t sum;
191 uint8_t *psum;
193 sum = htons(calc_csum(pkt->payload + from, to - from));
194 psum = (uint8_t *) &sum;
196 set_byte(psum[0]);
197 set_byte(psum[1]);
200 static inline bool is_dynamic_csum(enum csum which)
202 switch (which) {
203 case CSUM_UDP:
204 case CSUM_TCP:
205 case CSUM_UDP6:
206 case CSUM_TCP6:
207 return true;
208 default:
209 return false;
213 static void set_csum16(size_t from, size_t to, enum csum which)
215 struct packet *pkt = &packets[packet_last];
216 struct packet_dyn *pktd = &packet_dyn[packetd_last];
218 if (test_ignore())
219 return;
221 if (to < from) {
222 size_t tmp = to;
224 to = from;
225 from = tmp;
228 bug_on(!(from < to));
230 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
231 __set_csum16_dynamic(from, to, which);
232 else
233 __set_csum16_static(from, to, which);
236 static void set_rnd(size_t len)
238 size_t i;
239 struct packet *pkt = &packets[packet_last];
241 if (test_ignore())
242 return;
244 pkt->len += len;
245 pkt->payload = xrealloc(pkt->payload, pkt->len);
246 for (i = 0; i < len; ++i)
247 pkt->payload[payload_last - i] = (uint8_t) rand();
250 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
252 size_t i;
253 struct packet *pkt = &packets[packet_last];
255 if (test_ignore())
256 return;
258 pkt->len += len;
259 pkt->payload = xrealloc(pkt->payload, pkt->len);
260 for (i = 0; i < len; ++i) {
261 off_t off = len - 1 - i;
263 pkt->payload[payload_last - off] = start;
264 start += stepping;
268 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
270 size_t i;
271 struct packet *pkt = &packets[packet_last];
273 if (test_ignore())
274 return;
276 pkt->len += len;
277 pkt->payload = xrealloc(pkt->payload, pkt->len);
278 for (i = 0; i < len; ++i) {
279 int off = len - 1 - i;
281 pkt->payload[payload_last - off] = start;
282 start -= stepping;
286 static void set_dynamic_rnd(void)
288 struct packet *pkt = &packets[packet_last];
289 struct packet_dyn *pktd = &packet_dyn[packetd_last];
291 if (test_ignore())
292 return;
294 pkt->len++;
295 pkt->payload = xrealloc(pkt->payload, pkt->len);
297 pktd->rlen++;
298 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
300 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
303 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
304 int type)
306 struct packet *pkt = &packets[packet_last];
307 struct packet_dyn *pktd = &packet_dyn[packetd_last];
309 if (test_ignore())
310 return;
312 pkt->len++;
313 pkt->payload = xrealloc(pkt->payload, pkt->len);
315 pktd->clen++;
316 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
318 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
323 %union {
324 long long int number;
325 char *str;
328 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
329 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
331 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
333 %token number string
335 %type <number> number expression
336 %type <str> string
338 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
342 packets
343 : { }
344 | packets packet { }
345 | packets inline_comment { }
346 | packets K_WHITE { }
349 inline_comment
350 : K_COMMENT { }
353 cpu_delim
354 : ':' { }
355 | '-' { }
358 delimiter_nowhite
359 : ',' { }
360 | ',' K_WHITE { }
363 noenforce_white
364 : { }
365 | K_WHITE { }
366 | delimiter_nowhite { }
369 packet
370 : '{' noenforce_white payload noenforce_white '}' {
371 min_cpu = max_cpu = -1;
372 realloc_packet();
374 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
375 min_cpu = $3;
376 max_cpu = $5;
378 if (min_cpu > max_cpu) {
379 int tmp = min_cpu;
381 min_cpu = max_cpu;
382 max_cpu = tmp;
385 realloc_packet();
387 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
388 min_cpu = max_cpu = $3;
389 realloc_packet();
393 payload
394 : elem { }
395 | payload elem_delimiter { }
398 delimiter
399 : delimiter_nowhite { }
400 | K_WHITE { }
403 elem_delimiter
404 : delimiter elem { }
407 elem
408 : number { set_byte((uint8_t) $1); }
409 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
410 | fill { }
411 | rnd { }
412 | drnd { }
413 | seqinc { }
414 | seqdec { }
415 | dinc { }
416 | ddec { }
417 | csum { }
418 | const { }
419 | inline_comment { }
422 expression
423 : number
424 { $$ = $1; }
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 ^ $3; }
441 | expression '<' '<' expression
442 { $$ = $1 << $4; }
443 | expression '>' '>' expression
444 { $$ = $1 >> $4; }
445 | '-' expression
446 { $$ = -1 * $2; }
447 | '(' expression ')'
448 { $$ = $2;}
451 fill
452 : K_FILL '(' number delimiter number ')'
453 { set_fill($3, $5); }
456 const
457 : K_CONST8 '(' expression ')'
458 { set_byte((uint8_t) $3); }
459 | K_CONST16 '(' expression ')' {
460 uint16_t __c = cpu_to_be16((uint16_t) $3);
462 set_multi_byte((uint8_t *) &__c, sizeof(__c));
464 | K_CONST32 '(' expression ')' {
465 uint32_t __c = cpu_to_be32((uint32_t) $3);
467 set_multi_byte((uint8_t *) &__c, sizeof(__c));
469 | K_CONST64 '(' expression ')' {
470 uint64_t __c = cpu_to_be64((uint64_t) $3);
472 set_multi_byte((uint8_t *) &__c, sizeof(__c));
477 : K_RND '(' number ')'
478 { set_rnd($3); }
481 csum
482 : K_CSUMIP '(' number delimiter number ')'
483 { set_csum16($3, $5, CSUM_IP); }
484 | K_CSUMTCP '(' number delimiter number ')'
485 { set_csum16($3, $5, CSUM_TCP); }
486 | K_CSUMUDP '(' number delimiter number ')'
487 { set_csum16($3, $5, CSUM_UDP); }
488 | K_CSUMTCP6 '(' number delimiter number ')'
489 { set_csum16($3, $5, CSUM_TCP6); }
490 | K_CSUMUDP6 '(' number delimiter number ')'
491 { set_csum16($3, $5, CSUM_UDP6); }
494 seqinc
495 : K_SEQINC '(' number delimiter number ')'
496 { set_sequential_inc($3, $5, 1); }
497 | K_SEQINC '(' number delimiter number delimiter number ')'
498 { set_sequential_inc($3, $5, $7); }
501 seqdec
502 : K_SEQDEC '(' number delimiter number ')'
503 { set_sequential_dec($3, $5, 1); }
504 | K_SEQDEC '(' number delimiter number delimiter number ')'
505 { set_sequential_dec($3, $5, $7); }
508 drnd
509 : K_DRND '(' ')'
510 { set_dynamic_rnd(); }
511 | K_DRND '(' number ')'
513 int i, max = $3;
514 for (i = 0; i < max; ++i)
515 set_dynamic_rnd();
519 dinc
520 : K_DINC '(' number delimiter number ')'
521 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
522 | K_DINC '(' number delimiter number delimiter number ')'
523 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
526 ddec
527 : K_DDEC '(' number delimiter number ')'
528 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
529 | K_DDEC '(' number delimiter number delimiter number ')'
530 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
535 static void finalize_packet(void)
537 /* XXX hack ... we allocated one packet pointer too much */
538 plen--;
539 dlen--;
542 static void dump_conf(void)
544 size_t i, j;
546 for (i = 0; i < plen; ++i) {
547 printf("[%zu] pkt\n", i);
548 printf(" len %zu cnts %zu rnds %zu\n",
549 packets[i].len,
550 packet_dyn[i].clen,
551 packet_dyn[i].rlen);
553 printf(" payload ");
554 for (j = 0; j < packets[i].len; ++j)
555 printf("%02x ", packets[i].payload[j]);
556 printf("\n");
558 for (j = 0; j < packet_dyn[i].clen; ++j)
559 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
560 packet_dyn[i].cnt[j].min,
561 packet_dyn[i].cnt[j].max,
562 packet_dyn[i].cnt[j].inc,
563 (intmax_t)packet_dyn[i].cnt[j].off,
564 packet_dyn[i].cnt[j].type == TYPE_INC ?
565 "inc" : "dec");
567 for (j = 0; j < packet_dyn[i].rlen; ++j)
568 printf(" rnd%zu off %jd\n", j,
569 (intmax_t)packet_dyn[i].rnd[j].off);
573 void cleanup_packets(void)
575 size_t i;
577 for (i = 0; i < plen; ++i) {
578 if (packets[i].len > 0)
579 xfree(packets[i].payload);
582 free(packets);
584 for (i = 0; i < dlen; ++i) {
585 free(packet_dyn[i].cnt);
586 free(packet_dyn[i].rnd);
589 free(packet_dyn);
592 void compile_packets(char *file, bool verbose, unsigned int cpu, bool invoke_cpp)
594 char tmp_file[128];
595 int ret = -1;
597 memset(tmp_file, 0, sizeof(tmp_file));
598 our_cpu = cpu;
600 if (invoke_cpp) {
601 char cmd[256], *dir, *base, *a, *b;
603 dir = dirname((a = xstrdup(file)));
604 base = basename((b = xstrdup(file)));
606 slprintf(tmp_file, sizeof(tmp_file), "%s/.tmp-%u-%s", dir, rand(), base);
607 slprintf(cmd, sizeof(cmd), "cpp -I" ETCDIRE_STRING " %s > %s",
608 file, tmp_file);
609 if (system(cmd) != 0) {
610 fprintf(stderr, "Failed to invoke C preprocessor!\n");
611 goto err;
614 file = tmp_file;
615 xfree(a);
616 xfree(b);
619 if (!strncmp("-", file, strlen("-")))
620 yyin = stdin;
621 else
622 yyin = fopen(file, "r");
623 if (!yyin) {
624 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
625 goto err;
628 realloc_packet();
629 if (yyparse() != 0)
630 goto err;
631 finalize_packet();
633 if (our_cpu == 0 && verbose)
634 dump_conf();
636 ret = 0;
637 err:
638 if (yyin != stdin)
639 fclose(yyin);
641 if (invoke_cpp)
642 unlink(tmp_file);
643 if (ret)
644 die();
647 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
649 int ret = 1;
651 our_cpu = cpu;
652 realloc_packet();
654 yy_scan_string(str);
655 if (yyparse() != 0)
656 goto err;
658 finalize_packet();
659 if (our_cpu == 0 && verbose)
660 dump_conf();
662 ret = 0;
663 err:
664 yylex_destroy();
666 if (ret)
667 die();
670 void yyerror(const char *err)
672 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);