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 */
20 #include <net/if_arp.h>
21 #include <netinet/in.h>
24 #include "trafgen_parser.tab.h"
25 #include "trafgen_conf.h"
26 #include "trafgen_proto.h"
27 #include "trafgen_l2.h"
28 #include "trafgen_l3.h"
29 #include "trafgen_l4.h"
36 #define YYERROR_VERBOSE 0
38 #define YYENABLE_NLS 1
39 #define YYLTYPE_IS_TRIVIAL 1
43 extern
int yylex(void);
44 extern
void yy_scan_string
(char *);
45 extern
void yylex_destroy
();
46 extern
void yyerror(const char *);
50 extern
struct packet
*packets
;
53 #define packet_last (plen - 1)
55 #define payload_last (packets[packet_last].len - 1)
57 extern
struct packet_dyn
*packet_dyn
;
60 #define packetd_last (dlen - 1)
62 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
63 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
64 #define packetds_last (packet_dyn[packetd_last].slen - 1)
66 static int our_cpu
, min_cpu
= -1, max_cpu
= -1;
68 static struct proto_hdr
*hdr
;
70 static inline
int test_ignore
(void)
72 if
(min_cpu
< 0 && max_cpu
< 0)
74 else if
(max_cpu
>= our_cpu
&& min_cpu
<= our_cpu
)
80 static inline
void __init_new_packet_slot
(struct packet
*slot
)
86 static inline
void __init_new_counter_slot
(struct packet_dyn
*slot
)
92 static inline
void __init_new_randomizer_slot
(struct packet_dyn
*slot
)
98 static inline
void __init_new_csum_slot
(struct packet_dyn
*slot
)
104 static inline
void __setup_new_counter
(struct counter
*c
, uint8_t start
,
105 uint8_t stop
, uint8_t stepping
,
111 c
->val
= (type
== TYPE_INC
) ? start
: stop
;
112 c
->off
= payload_last
;
116 static inline
void __setup_new_randomizer
(struct randomizer
*r
)
118 r
->off
= payload_last
;
121 static inline
void __setup_new_csum16
(struct csum16
*s
, off_t from
, off_t to
,
124 s
->off
= payload_last
- 1;
130 static void realloc_packet
(void)
136 packets
= xrealloc
(packets
, plen
* sizeof
(*packets
));
138 __init_new_packet_slot
(&packets
[packet_last
]);
141 packet_dyn
= xrealloc
(packet_dyn
, dlen
* sizeof
(*packet_dyn
));
143 __init_new_counter_slot
(&packet_dyn
[packetd_last
]);
144 __init_new_randomizer_slot
(&packet_dyn
[packetd_last
]);
145 __init_new_csum_slot
(&packet_dyn
[packetd_last
]);
148 struct packet
*current_packet
(void)
150 return
&packets
[packet_last
];
153 static void set_byte
(uint8_t val
)
155 struct packet
*pkt
= &packets
[packet_last
];
161 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
162 pkt
->payload
[payload_last
] = val
;
165 static void set_multi_byte
(uint8_t *s
, size_t len
)
169 for
(i
= 0; i
< len
; ++i
)
173 void set_fill
(uint8_t val
, size_t len
)
176 struct packet
*pkt
= &packets
[packet_last
];
182 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
183 for
(i
= 0; i
< len
; ++i
)
184 pkt
->payload
[payload_last
- i
] = val
;
187 static void __set_csum16_dynamic
(size_t from
, size_t to
, enum csum which
)
189 struct packet
*pkt
= &packets
[packet_last
];
190 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
193 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
196 pktd
->csum
= xrealloc
(pktd
->csum
, pktd
->slen
* sizeof
(struct csum16
));
198 __setup_new_csum16
(&pktd
->csum
[packetds_last
], from
, to
, which
);
201 static void __set_csum16_static
(size_t from
, size_t to
, enum csum which __maybe_unused
)
203 struct packet
*pkt
= &packets
[packet_last
];
207 sum
= htons
(calc_csum
(pkt
->payload
+ from
, to
- from
));
208 psum
= (uint8_t *) &sum
;
214 static inline
bool is_dynamic_csum
(enum csum which
)
227 static void set_csum16
(size_t from
, size_t to
, enum csum which
)
229 struct packet
*pkt
= &packets
[packet_last
];
230 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
242 bug_on
(!(from
< to
));
244 if
(packet_dyn_has_elems
(pktd
) || to
>= pkt
->len || is_dynamic_csum
(which
))
245 __set_csum16_dynamic
(from
, to
, which
);
247 __set_csum16_static
(from
, to
, which
);
250 static void set_rnd
(size_t len
)
253 struct packet
*pkt
= &packets
[packet_last
];
259 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
260 for
(i
= 0; i
< len
; ++i
)
261 pkt
->payload
[payload_last
- i
] = (uint8_t) rand
();
264 static void set_sequential_inc
(uint8_t start
, size_t len
, uint8_t stepping
)
267 struct packet
*pkt
= &packets
[packet_last
];
273 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
274 for
(i
= 0; i
< len
; ++i
) {
275 off_t off
= len
- 1 - i
;
277 pkt
->payload
[payload_last
- off
] = start
;
282 static void set_sequential_dec
(uint8_t start
, size_t len
, uint8_t stepping
)
285 struct packet
*pkt
= &packets
[packet_last
];
291 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
292 for
(i
= 0; i
< len
; ++i
) {
293 int off
= len
- 1 - i
;
295 pkt
->payload
[payload_last
- off
] = start
;
300 static void set_dynamic_rnd
(void)
302 struct packet
*pkt
= &packets
[packet_last
];
303 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
309 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
312 pktd
->rnd
= xrealloc
(pktd
->rnd
, pktd
->rlen
* sizeof
(struct randomizer
));
314 __setup_new_randomizer
(&pktd
->rnd
[packetdr_last
]);
317 static void set_dynamic_incdec
(uint8_t start
, uint8_t stop
, uint8_t stepping
,
320 struct packet
*pkt
= &packets
[packet_last
];
321 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
327 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
330 pktd
->cnt
= xrealloc
(pktd
->cnt
, pktd
->clen
* sizeof
(struct counter
));
332 __setup_new_counter
(&pktd
->cnt
[packetdc_last
], start
, stop
, stepping
, type
);
335 static void proto_add
(enum proto_id pid
)
337 proto_header_init
(pid
);
338 hdr
= proto_current_header
();
344 struct in_addr ip_addr
;
345 long long int number
;
350 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
351 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
353 %token K_DADDR K_SADDR K_ETYPE
354 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
355 %token K_PROT K_TTL K_DSCP K_ECN K_TOS K_LEN K_ID K_FLAGS K_FRAG K_IHL K_VER K_CSUM K_DF K_MF
356 %token K_SPORT K_DPORT
363 %token
',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
365 %token number
string mac ip_addr
367 %type
<number
> number expression
370 %type
<ip_addr
> ip_addr
372 %left
'-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
379 | packets inline_comment
{ }
380 | packets K_WHITE
{ }
400 | delimiter_nowhite
{ }
408 : '{' noenforce_white payload noenforce_white
'}' {
409 min_cpu
= max_cpu
= -1;
411 proto_packet_finish
();
415 | K_CPU
'(' number cpu_delim number
')' ':' noenforce_white
'{' noenforce_white payload noenforce_white
'}' {
419 if
(min_cpu
> max_cpu
) {
426 proto_packet_finish
();
430 | K_CPU
'(' number
')' ':' noenforce_white
'{' noenforce_white payload noenforce_white
'}' {
431 min_cpu
= max_cpu
= $3;
433 proto_packet_finish
();
441 | payload elem_delimiter
{ }
445 : delimiter_nowhite
{ }
454 : number
{ set_byte
((uint8_t) $1); }
455 |
string { set_multi_byte
((uint8_t *) $1 + 1, strlen
($1) - 2); }
465 | proto
{ proto_header_finish
(hdr
); }
472 | expression
'+' expression
474 | expression
'-' expression
476 | expression
'*' expression
478 | expression
'/' expression
480 | expression
'%' expression
482 | expression
'&' expression
484 | expression
'|' expression
486 | expression
'^' expression
488 | expression
'<' '<' expression
490 | expression
'>' '>' expression
499 : K_FILL
'(' number delimiter number
')'
500 { set_fill
($3, $5); }
504 : K_CONST8
'(' expression
')'
505 { set_byte
((uint8_t) $3); }
506 | K_CONST16
'(' expression
')' {
507 uint16_t __c
= cpu_to_be16
((uint16_t) $3);
509 set_multi_byte
((uint8_t *) &__c
, sizeof
(__c
));
511 | K_CONST32
'(' expression
')' {
512 uint32_t __c
= cpu_to_be32
((uint32_t) $3);
514 set_multi_byte
((uint8_t *) &__c
, sizeof
(__c
));
516 | K_CONST64
'(' expression
')' {
517 uint64_t __c
= cpu_to_be64
((uint64_t) $3);
519 set_multi_byte
((uint8_t *) &__c
, sizeof
(__c
));
524 : K_RND
'(' number
')'
529 : K_CSUMIP
'(' number delimiter number
')'
530 { set_csum16
($3, $5, CSUM_IP
); }
531 | K_CSUMTCP
'(' number delimiter number
')'
532 { set_csum16
($3, $5, CSUM_TCP
); }
533 | K_CSUMUDP
'(' number delimiter number
')'
534 { set_csum16
($3, $5, CSUM_UDP
); }
535 | K_CSUMTCP6
'(' number delimiter number
')'
536 { set_csum16
($3, $5, CSUM_TCP6
); }
537 | K_CSUMUDP6
'(' number delimiter number
')'
538 { set_csum16
($3, $5, CSUM_UDP6
); }
542 : K_SEQINC
'(' number delimiter number
')'
543 { set_sequential_inc
($3, $5, 1); }
544 | K_SEQINC
'(' number delimiter number delimiter number
')'
545 { set_sequential_inc
($3, $5, $7); }
549 : K_SEQDEC
'(' number delimiter number
')'
550 { set_sequential_dec
($3, $5, 1); }
551 | K_SEQDEC
'(' number delimiter number delimiter number
')'
552 { set_sequential_dec
($3, $5, $7); }
557 { set_dynamic_rnd
(); }
558 | K_DRND
'(' number
')'
561 for
(i
= 0; i
< max
; ++i
)
567 : K_DINC
'(' number delimiter number
')'
568 { set_dynamic_incdec
($3, $5, 1, TYPE_INC
); }
569 | K_DINC
'(' number delimiter number delimiter number
')'
570 { set_dynamic_incdec
($3, $5, $7, TYPE_INC
); }
574 : K_DDEC
'(' number delimiter number
')'
575 { set_dynamic_incdec
($3, $5, 1, TYPE_DEC
); }
576 | K_DDEC
'(' number delimiter number delimiter number
')'
577 { set_dynamic_incdec
($3, $5, $7, TYPE_DEC
); }
588 : eth
'(' eth_param_list
')' { }
592 : K_ETH
{ proto_add
(PROTO_ETH
); }
598 | eth_field delimiter eth_param_list
{ }
602 : K_DADDR skip_white
'=' skip_white mac
603 { proto_field_set_bytes
(hdr
, ETH_DST_ADDR
, $5); }
604 | K_SADDR skip_white
'=' skip_white mac
605 { proto_field_set_bytes
(hdr
, ETH_SRC_ADDR
, $5); }
606 | K_ETYPE skip_white
'=' skip_white number
607 { proto_field_set_be16
(hdr
, ETH_TYPE
, $5); }
611 : arp
'(' arp_param_list
')' { }
617 | arp_field delimiter arp_param_list
{ }
621 : K_OPER skip_white
'=' skip_white K_REQUEST
622 { proto_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REQUEST
); }
623 | K_OPER skip_white
'=' skip_white K_REPLY
624 { proto_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REPLY
); }
625 | K_OPER skip_white
'=' skip_white number
626 { proto_field_set_be16
(hdr
, ARP_OPER
, $5); }
628 { proto_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REQUEST
); }
630 { proto_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REPLY
); }
631 | K_HTYPE skip_white
'=' skip_white number
632 { proto_field_set_be16
(hdr
, ARP_HTYPE
, $5); }
633 | K_PTYPE skip_white
'=' skip_white number
634 { proto_field_set_be16
(hdr
, ARP_PTYPE
, $5); }
635 | K_SHA skip_white
'=' skip_white mac
636 { proto_field_set_bytes
(hdr
, ARP_SHA
, $5); }
637 | K_THA skip_white
'=' skip_white mac
638 { proto_field_set_bytes
(hdr
, ARP_THA
, $5); }
639 | K_SPA skip_white
'=' skip_white ip_addr
640 { proto_field_set_u32
(hdr
, ARP_SPA
, $5.s_addr
); }
641 | K_TPA skip_white
'=' skip_white ip_addr
642 { proto_field_set_u32
(hdr
, ARP_TPA
, $5.s_addr
); }
645 : K_ARP
{ proto_add
(PROTO_ARP
); }
649 : ip4
'(' ip4_param_list
')' { }
655 | ip4_field delimiter ip4_param_list
{ }
659 : K_VER skip_white
'=' skip_white number
660 { proto_field_set_u8
(hdr
, IP4_VER
, $5); }
661 | K_IHL skip_white
'=' skip_white number
662 { proto_field_set_u8
(hdr
, IP4_IHL
, $5); }
663 | K_DADDR skip_white
'=' skip_white ip_addr
664 { proto_field_set_u32
(hdr
, IP4_DADDR
, $5.s_addr
); }
665 | K_SADDR skip_white
'=' skip_white ip_addr
666 { proto_field_set_u32
(hdr
, IP4_SADDR
, $5.s_addr
); }
667 | K_PROT skip_white
'=' skip_white number
668 { proto_field_set_u8
(hdr
, IP4_PROTO
, $5); }
669 | K_TTL skip_white
'=' skip_white number
670 { proto_field_set_u8
(hdr
, IP4_TTL
, $5); }
671 | K_DSCP skip_white
'=' skip_white number
672 { proto_field_set_u8
(hdr
, IP4_DSCP
, $5); }
673 | K_ECN skip_white
'=' skip_white number
674 { proto_field_set_u8
(hdr
, IP4_ECN
, $5); }
675 | K_TOS skip_white
'=' skip_white number
676 { proto_field_set_u8
(hdr
, IP4_TOS
, $5); }
677 | K_LEN skip_white
'=' skip_white number
678 { proto_field_set_be16
(hdr
, IP4_LEN
, $5); }
679 | K_ID skip_white
'=' skip_white number
680 { proto_field_set_be16
(hdr
, IP4_ID
, $5); }
681 | K_FLAGS skip_white
'=' skip_white number
682 { proto_field_set_be16
(hdr
, IP4_FLAGS
, $5); }
683 | K_DF
{ proto_field_set_be16
(hdr
, IP4_DF
, 1); }
684 | K_MF
{ proto_field_set_be16
(hdr
, IP4_MF
, 1); }
685 | K_FRAG skip_white
'=' skip_white number
686 { proto_field_set_be16
(hdr
, IP4_FRAG_OFFS
, $5); }
687 | K_CSUM skip_white
'=' skip_white number
688 { proto_field_set_be16
(hdr
, IP4_CSUM
, $5); }
692 : K_IP4
{ proto_add
(PROTO_IP4
); }
696 : udp
'(' udp_param_list
')' { }
702 | udp_field delimiter udp_param_list
{ }
706 : K_SPORT skip_white
'=' skip_white number
707 { proto_field_set_be16
(hdr
, UDP_SPORT
, $5); }
708 | K_DPORT skip_white
'=' skip_white number
709 { proto_field_set_be16
(hdr
, UDP_DPORT
, $5); }
710 | K_LEN skip_white
'=' skip_white number
711 { proto_field_set_be16
(hdr
, UDP_LEN
, $5); }
712 | K_CSUM skip_white
'=' skip_white number
713 { proto_field_set_be16
(hdr
, UDP_CSUM
, $5); }
717 : K_UDP
{ proto_add
(PROTO_UDP
); }
722 static void finalize_packet
(void)
724 /* XXX hack ... we allocated one packet pointer too much */
729 static void dump_conf
(void)
733 for
(i
= 0; i
< plen
; ++i
) {
734 printf
("[%zu] pkt\n", i
);
735 printf
(" len %zu cnts %zu rnds %zu\n",
741 for
(j
= 0; j
< packets
[i
].len
; ++j
)
742 printf
("%02x ", packets
[i
].payload
[j
]);
745 for
(j
= 0; j
< packet_dyn
[i
].clen
; ++j
)
746 printf
(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j
,
747 packet_dyn
[i
].cnt
[j
].min
,
748 packet_dyn
[i
].cnt
[j
].max
,
749 packet_dyn
[i
].cnt
[j
].inc
,
750 (intmax_t)packet_dyn
[i
].cnt
[j
].off
,
751 packet_dyn
[i
].cnt
[j
].type
== TYPE_INC ?
754 for
(j
= 0; j
< packet_dyn
[i
].rlen
; ++j
)
755 printf
(" rnd%zu off %jd\n", j
,
756 (intmax_t)packet_dyn
[i
].rnd
[j
].off
);
760 void cleanup_packets
(void)
764 for
(i
= 0; i
< plen
; ++i
) {
765 if
(packets
[i
].len
> 0)
766 xfree
(packets
[i
].payload
);
771 for
(i
= 0; i
< dlen
; ++i
) {
772 free
(packet_dyn
[i
].cnt
);
773 free
(packet_dyn
[i
].rnd
);
779 void compile_packets
(char *file
, bool verbose
, unsigned int cpu
,
780 bool invoke_cpp
, char *const cpp_argv
[])
785 memset
(tmp_file
, 0, sizeof
(tmp_file
));
789 if
(cpp_exec
(file
, tmp_file
, sizeof
(tmp_file
), cpp_argv
)) {
790 fprintf
(stderr
, "Failed to invoke C preprocessor!\n");
796 if
(!strncmp
("-", file
, strlen
("-")))
799 yyin
= fopen
(file
, "r");
801 fprintf
(stderr
, "Cannot open %s: %s!\n", file
, strerror
(errno
));
810 if
(our_cpu
== 0 && verbose
)
815 if
(yyin
&& yyin
!= stdin
)
824 void compile_packets_str
(char *str
, bool verbose
, unsigned int cpu
)
836 if
(our_cpu
== 0 && verbose
)
847 void yyerror(const char *err
)
849 fprintf
(stderr
, "Syntax error at line %d, char '%s': %s\n", yylineno
, yytext
, err
);