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.
9 /* yaac-func-prefix: yy */
22 #include "trafgen_parser.tab.h"
23 #include "trafgen_conf.h"
29 #define YYERROR_VERBOSE 0
31 #define YYENABLE_NLS 1
32 #define YYLTYPE_IS_TRIVIAL 1
36 extern
int yylex(void);
37 extern
void yyerror(const char *);
41 extern
struct packet
*packets
;
44 #define packet_last (plen - 1)
46 #define payload_last (packets[packet_last].len - 1)
48 extern
struct packet_dyn
*packet_dyn
;
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)
63 else if
(max_cpu
>= our_cpu
&& min_cpu
<= our_cpu
)
69 static inline
void __init_new_packet_slot
(struct packet
*slot
)
75 static inline
void __init_new_counter_slot
(struct packet_dyn
*slot
)
81 static inline
void __init_new_randomizer_slot
(struct packet_dyn
*slot
)
87 static inline
void __init_new_csum_slot
(struct packet_dyn
*slot
)
93 static inline
void __setup_new_counter
(struct counter
*c
, uint8_t start
,
94 uint8_t stop
, uint8_t stepping
,
100 c
->val
= (type
== TYPE_INC
) ? start
: stop
;
101 c
->off
= payload_last
;
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
,
113 s
->off
= payload_last
- 1;
119 static void realloc_packet
(void)
125 packets
= xrealloc
(packets
, plen
* sizeof
(*packets
));
127 __init_new_packet_slot
(&packets
[packet_last
]);
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
];
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
)
153 for
(i
= 0; i
< len
; ++i
)
157 static void set_fill
(uint8_t val
, size_t len
)
160 struct packet
*pkt
= &packets
[packet_last
];
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
];
177 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
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
];
191 sum
= htons
(calc_csum
(pkt
->payload
+ from
, to
- from
, 0));
192 psum
= (uint8_t *) &sum
;
198 static inline
bool is_dynamic_csum
(enum csum which
)
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
];
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
);
231 __set_csum16_static
(from
, to
, which
);
234 static void set_rnd
(size_t len
)
237 struct packet
*pkt
= &packets
[packet_last
];
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
)
251 struct packet
*pkt
= &packets
[packet_last
];
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
;
266 static void set_sequential_dec
(uint8_t start
, size_t len
, uint8_t stepping
)
269 struct packet
*pkt
= &packets
[packet_last
];
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
;
284 static void set_dynamic_rnd
(void)
286 struct packet
*pkt
= &packets
[packet_last
];
287 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
293 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
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
,
304 struct packet
*pkt
= &packets
[packet_last
];
305 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
311 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
314 pktd
->cnt
= xrealloc
(pktd
->cnt
, pktd
->clen
* sizeof
(struct counter
));
316 __setup_new_counter
(&pktd
->cnt
[packetdc_last
], start
, stop
, stepping
, type
);
322 long long int number
;
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
',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
333 %type
<number
> number expression
336 %left
'-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
343 | packets inline_comment
{ }
344 | packets K_WHITE
{ }
364 | delimiter_nowhite
{ }
368 : '{' noenforce_white payload noenforce_white
'}' {
369 min_cpu
= max_cpu
= -1;
372 | K_CPU
'(' number cpu_delim number
')' ':' noenforce_white
'{' noenforce_white payload noenforce_white
'}' {
376 if
(min_cpu
> max_cpu
) {
385 | K_CPU
'(' number
')' ':' noenforce_white
'{' noenforce_white payload noenforce_white
'}' {
386 min_cpu
= max_cpu
= $3;
393 | payload elem_delimiter
{ }
397 : delimiter_nowhite
{ }
406 : number
{ set_byte
((uint8_t) $1); }
407 |
string { set_multi_byte
((uint8_t *) $1 + 1, strlen
($1) - 2); }
423 | expression
'+' expression
425 | expression
'-' expression
427 | expression
'*' expression
429 | expression
'/' expression
431 | expression
'%' expression
433 | expression
'&' expression
435 | expression
'|' expression
437 | expression
'^' expression
439 | expression
'<' '<' expression
441 | expression
'>' '>' expression
450 : K_FILL
'(' number delimiter number
')'
451 { set_fill
($3, $5); }
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
')'
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
); }
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); }
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); }
508 { set_dynamic_rnd
(); }
509 | K_DRND
'(' number
')'
512 for
(i
= 0; i
< max
; ++i
)
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
); }
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 */
540 static void dump_conf
(void)
544 for
(i
= 0; i
< plen
; ++i
) {
545 printf
("[%zu] pkt\n", i
);
546 printf
(" len %zu cnts %zu rnds %zu\n",
552 for
(j
= 0; j
< packets
[i
].len
; ++j
)
553 printf
("%02x ", packets
[i
].payload
[j
]);
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 ?
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)
575 for
(i
= 0; i
< plen
; ++i
) {
576 if
(packets
[i
].len
> 0)
577 xfree
(packets
[i
].payload
);
582 for
(i
= 0; i
< dlen
; ++i
) {
583 free
(packet_dyn
[i
].cnt
);
584 free
(packet_dyn
[i
].rnd
);
590 void compile_packets
(char *file
, bool verbose
, unsigned int cpu
, bool invoke_cpp
)
595 memset
(tmp_file
, 0, sizeof
(tmp_file
));
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",
607 if
(system
(cmd
) != 0) {
608 fprintf
(stderr
, "Failed to invoke C preprocessor!\n");
617 if
(!strncmp
("-", file
, strlen
("-")))
620 yyin
= fopen
(file
, "r");
622 fprintf
(stderr
, "Cannot open %s: %s!\n", file
, strerror
(errno
));
631 if
(our_cpu
== 0 && verbose
)
644 void yyerror(const char *err
)
646 fprintf
(stderr
, "Syntax error at line %d, char '%s': %s\n", yylineno
, yytext
, err
);