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 /* yacc-func-prefix: yy */
21 #include <net/if_arp.h>
22 #include <netinet/in.h>
23 #include <linux/icmp.h>
24 #include <linux/if_ether.h>
25 #include <linux/icmpv6.h>
28 #include "trafgen_parser.tab.h"
29 #include "trafgen_conf.h"
30 #include "trafgen_proto.h"
31 #include "trafgen_l2.h"
32 #include "trafgen_l3.h"
33 #include "trafgen_l4.h"
34 #include "trafgen_l7.h"
42 #define ETH_P_8021AD 0x88A8
45 #define YYERROR_VERBOSE 0
47 #define YYLTYPE_IS_TRIVIAL 1
50 extern
int yylex(void);
51 extern
void yy_scan_string
(char *);
52 extern
void yylex_destroy
();
53 extern
void yyerror(const char *);
57 extern
struct packet
*packets
;
60 #define packet_last (plen - 1)
62 #define payload_last (packets[packet_last].len - 1)
64 extern
struct packet_dyn
*packet_dyn
;
67 #define packetd_last (dlen - 1)
69 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
70 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
71 #define packetds_last (packet_dyn[packetd_last].slen - 1)
73 static int our_cpu
, min_cpu
= -1, max_cpu
= -1;
75 enum field_expr_type_t
{
76 FIELD_EXPR_UNKNOWN
= 0,
77 FIELD_EXPR_NUMB
= 1 << 0,
78 FIELD_EXPR_MAC
= 1 << 1,
79 FIELD_EXPR_IP4_ADDR
= 1 << 2,
80 FIELD_EXPR_IP6_ADDR
= 1 << 3,
81 FIELD_EXPR_INC
= 1 << 4,
82 FIELD_EXPR_RND
= 1 << 5,
83 FIELD_EXPR_OFFSET
= 1 << 6,
84 FIELD_EXPR_STRING
= 1 << 7,
85 FIELD_EXPR_FQDN
= 1 << 8,
88 struct proto_field_expr
{
89 enum field_expr_type_t type
;
90 struct proto_field
*field
;
93 struct in_addr ip4_addr
;
94 struct in6_addr ip6_addr
;
98 struct proto_field_func func
;
102 static struct proto_field_expr field_expr
;
103 static struct proto_hdr
*hdr
;
105 static inline
int test_ignore
(void)
107 if
(min_cpu
< 0 && max_cpu
< 0)
109 else if
(max_cpu
>= our_cpu
&& min_cpu
<= our_cpu
)
115 static inline
void __init_new_packet_slot
(struct packet
*slot
)
117 memset
(slot
, 0, sizeof
(*slot
));
120 static inline
void __init_new_counter_slot
(struct packet_dyn
*slot
)
126 static inline
void __init_new_randomizer_slot
(struct packet_dyn
*slot
)
132 static inline
void __init_new_csum_slot
(struct packet_dyn
*slot
)
138 static inline
void __init_new_fields_slot
(struct packet_dyn
*slot
)
144 static inline
void __setup_new_counter
(struct counter
*c
, uint8_t start
,
145 uint8_t stop
, uint8_t stepping
,
150 c
->inc
= (type
== TYPE_INC
) ? stepping
: -stepping
;
151 c
->val
= (type
== TYPE_INC
) ? start
: stop
;
152 c
->off
= payload_last
;
156 static inline
void __setup_new_randomizer
(struct randomizer
*r
)
158 r
->off
= payload_last
;
161 static inline
void __setup_new_csum16
(struct csum16
*s
, off_t from
, off_t to
,
164 s
->off
= payload_last
- 1;
170 struct packet
*realloc_packet
(void)
178 packets
= xrealloc
(packets
, plen
* sizeof
(*packets
));
180 __init_new_packet_slot
(&packets
[packet_last
]);
183 packet_dyn
= xrealloc
(packet_dyn
, dlen
* sizeof
(*packet_dyn
));
185 __init_new_counter_slot
(&packet_dyn
[packetd_last
]);
186 __init_new_randomizer_slot
(&packet_dyn
[packetd_last
]);
187 __init_new_csum_slot
(&packet_dyn
[packetd_last
]);
188 __init_new_fields_slot
(&packet_dyn
[packetd_last
]);
190 for
(i
= 0; i
< plen
; i
++)
193 return
&packets
[packet_last
];
196 struct packet
*current_packet
(void)
198 return
&packets
[packet_last
];
201 uint32_t current_packet_id
(void)
206 struct packet
*packet_get
(uint32_t id
)
211 static void set_byte
(uint8_t val
)
213 struct packet
*pkt
= &packets
[packet_last
];
219 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
220 pkt
->payload
[payload_last
] = val
;
223 static void set_multi_byte
(uint8_t *s
, size_t len
)
227 for
(i
= 0; i
< len
; ++i
)
231 void set_fill
(uint8_t val
, size_t len
)
234 struct packet
*pkt
= &packets
[packet_last
];
240 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
241 for
(i
= 0; i
< len
; ++i
)
242 pkt
->payload
[payload_last
- i
] = val
;
245 static void __set_csum16_dynamic
(size_t from
, size_t to
, enum csum which
)
247 struct packet
*pkt
= &packets
[packet_last
];
248 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
251 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
254 pktd
->csum
= xrealloc
(pktd
->csum
, pktd
->slen
* sizeof
(struct csum16
));
256 __setup_new_csum16
(&pktd
->csum
[packetds_last
], from
, to
, which
);
259 static void __set_csum16_static
(size_t from
, size_t to
, enum csum which __maybe_unused
)
261 struct packet
*pkt
= &packets
[packet_last
];
265 sum
= htons
(calc_csum
(pkt
->payload
+ from
, to
- from
));
266 psum
= (uint8_t *) &sum
;
272 static inline
bool is_dynamic_csum
(enum csum which
)
286 static void set_csum16
(size_t from
, size_t to
, enum csum which
)
288 struct packet
*pkt
= &packets
[packet_last
];
289 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
301 bug_on
(!(from
< to
));
303 if
(packet_dyn_has_elems
(pktd
) || to
>= pkt
->len || is_dynamic_csum
(which
))
304 __set_csum16_dynamic
(from
, to
, which
);
306 __set_csum16_static
(from
, to
, which
);
309 static void set_rnd
(size_t len
)
312 struct packet
*pkt
= &packets
[packet_last
];
318 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
319 for
(i
= 0; i
< len
; ++i
)
320 pkt
->payload
[payload_last
- i
] = (uint8_t) rand
();
323 static void set_sequential_inc
(uint8_t start
, size_t len
, uint8_t stepping
)
326 struct packet
*pkt
= &packets
[packet_last
];
332 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
333 for
(i
= 0; i
< len
; ++i
) {
334 off_t off
= len
- 1 - i
;
336 pkt
->payload
[payload_last
- off
] = start
;
341 static void set_sequential_dec
(uint8_t start
, size_t len
, uint8_t stepping
)
344 struct packet
*pkt
= &packets
[packet_last
];
350 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
351 for
(i
= 0; i
< len
; ++i
) {
352 int off
= len
- 1 - i
;
354 pkt
->payload
[payload_last
- off
] = start
;
359 static void set_dynamic_rnd
(void)
361 struct packet
*pkt
= &packets
[packet_last
];
362 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
368 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
371 pktd
->rnd
= xrealloc
(pktd
->rnd
, pktd
->rlen
* sizeof
(struct randomizer
));
373 __setup_new_randomizer
(&pktd
->rnd
[packetdr_last
]);
376 static void set_dynamic_incdec
(uint8_t start
, uint8_t stop
, uint8_t stepping
,
379 struct packet
*pkt
= &packets
[packet_last
];
380 struct packet_dyn
*pktd
= &packet_dyn
[packetd_last
];
386 pkt
->payload
= xrealloc
(pkt
->payload
, pkt
->len
);
389 pktd
->cnt
= xrealloc
(pktd
->cnt
, pktd
->clen
* sizeof
(struct counter
));
391 __setup_new_counter
(&pktd
->cnt
[packetdc_last
], start
, stop
, stepping
, type
);
394 static void proto_add
(enum proto_id pid
)
396 hdr
= proto_header_push
(pid
);
399 static void proto_field_set
(uint32_t fid
)
401 memset
(&field_expr
, 0, sizeof
(field_expr
));
402 field_expr.field
= proto_hdr_field_by_id
(hdr
, fid
);
405 static void proto_field_func_setup
(struct proto_field
*field
, struct proto_field_func
*func
)
407 struct proto_field
*field_copy
;
408 struct packet_dyn
*pkt_dyn
;
410 field_copy
= xmalloc
(sizeof
(*field
));
411 memcpy
(field_copy
, field
, sizeof
(*field
));
413 field_copy
->pkt_offset
+= func
->offset
;
415 field_copy
->len
= func
->len
;
417 proto_field_func_add
(field_copy
, func
);
419 pkt_dyn
= &packet_dyn
[packetd_last
];
421 pkt_dyn
->fields
= xrealloc
(pkt_dyn
->fields
, pkt_dyn
->flen
*
422 sizeof
(struct proto_field
*));
424 pkt_dyn
->fields
[pkt_dyn
->flen
- 1] = field_copy
;
427 static void proto_field_expr_eval
(void)
429 struct proto_field
*field
= field_expr.field
;
431 if
((field_expr.type
& FIELD_EXPR_OFFSET
) &&
432 !((field_expr.type
& FIELD_EXPR_INC
) ||
433 (field_expr.type
& FIELD_EXPR_RND
))) {
435 panic
("Field offset expression is valid only with function expression\n");
438 if
(field_expr.type
& FIELD_EXPR_NUMB
) {
440 proto_field_set_u8
(field
, field_expr.val.number
);
441 else if
(field
->len
== 2)
442 proto_field_set_be16
(field
, field_expr.val.number
);
443 else if
(field
->len
== 4)
444 proto_field_set_be32
(field
, field_expr.val.number
);
446 panic
("Invalid value length %zu, can be 1,2 or 4\n", field
->len
);
447 } else if
(field_expr.type
& FIELD_EXPR_MAC
) {
448 proto_field_set_bytes
(field
, field_expr.val.mac
, 6);
449 } else if
(field_expr.type
& FIELD_EXPR_FQDN
) {
450 char *fqdn
= str2fqdn
(field_expr.val.str
);
451 proto_field_set_bytes
(field
, (uint8_t *) fqdn
, strlen
(fqdn
) + 1);
452 xfree
(field_expr.val.str
);
454 } else if
(field_expr.type
& FIELD_EXPR_STRING
) {
455 proto_field_set_string
(field
, field_expr.val.str
);
456 xfree
(field_expr.val.str
);
457 } else if
(field_expr.type
& FIELD_EXPR_IP4_ADDR
) {
458 proto_field_set_u32
(field
, field_expr.val.ip4_addr.s_addr
);
459 } else if
(field_expr.type
& FIELD_EXPR_IP6_ADDR
) {
460 proto_field_set_bytes
(field
, (uint8_t *)&field_expr.val.ip6_addr.s6_addr
, 16);
461 } else if
((field_expr.type
& FIELD_EXPR_INC
) ||
462 (field_expr.type
& FIELD_EXPR_RND
)) {
464 if
(field_expr.val.func.min
465 && field_expr.val.func.min
>= field_expr.val.func.max
)
466 panic
("dinc(): min(%u) can't be >= max(%u)\n",
467 field_expr.val.func.min
, field_expr.val.func.max
);
469 proto_field_func_setup
(field
, &field_expr.val.func
);
470 } else if
((field_expr.type
& FIELD_EXPR_OFFSET
) &&
471 !((field_expr.type
& FIELD_EXPR_INC
) ||
472 (field_expr.type
& FIELD_EXPR_RND
))) {
474 panic
("Field expression is valid only for function value expression\n");
479 memset
(&field_expr
, 0, sizeof
(field_expr
));
482 static void field_index_validate
(struct proto_field
*field
, uint16_t index
, size_t len
)
484 if
(field_expr.field
->len
<= index
) {
485 yyerror("Invalid [index] parameter");
486 panic
("Index (%u) is bigger than field's length (%zu)\n",
489 if
(len
!= 1 && len
!= 2 && len
!= 4) {
490 yyerror("Invalid [index:len] parameter");
491 panic
("Invalid index length - 1,2 or 4 is only allowed\n");
495 static void proto_push_sub_hdr
(uint32_t id
)
497 hdr
= proto_hdr_push_sub_header
(hdr
, id
);
500 static void proto_pop_sub_hdr
(void)
502 if
(hdr
->ops
->header_finish
)
503 hdr
->ops
->header_finish
(hdr
);
511 struct in_addr ip4_addr
;
512 struct in6_addr ip6_addr
;
513 long long int number
;
518 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
519 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CSUMICMP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
521 %token K_DADDR K_SADDR K_ETYPE K_TYPE
523 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
524 %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
525 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
526 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
527 %token K_SPORT K_DPORT
528 %token K_SEQ K_ACK_SEQ K_DOFF K_CWR K_ECE K_URG K_ACK K_PSH K_RST K_SYN K_FIN K_WINDOW K_URG_PTR
529 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
530 %token K_LABEL K_TC K_LAST K_EXP
534 %token K_QR K_AANSWER K_TRUNC K_RAVAIL K_RDESIRED K_ZERO K_RCODE K_QDCOUNT K_ANCOUNT K_NSCOUNT K_ARCOUNT
535 %token K_QUERY K_ANSWER K_AUTH K_ADD
536 %token K_NAME K_CLASS K_DATA K_NS K_CNAME K_PTR
544 %token K_ICMP4 K_ICMP6
548 %token
',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
550 %token number
string mac ip4_addr ip6_addr
552 %type
<number
> number expression
555 %type
<ip4_addr
> ip4_addr
556 %type
<ip6_addr
> ip6_addr
558 %left
'-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
565 | packets inline_comment
{ }
566 | packets K_WHITE
{ }
586 | delimiter_nowhite
{ }
594 : '{' noenforce_white payload noenforce_white
'}' {
595 min_cpu
= max_cpu
= -1;
597 proto_packet_finish
();
601 | K_CPU
'(' number cpu_delim number
')' ':' noenforce_white
'{' noenforce_white payload noenforce_white
'}' {
605 if
(min_cpu
> max_cpu
) {
612 proto_packet_finish
();
616 | K_CPU
'(' number
')' ':' noenforce_white
'{' noenforce_white payload noenforce_white
'}' {
617 min_cpu
= max_cpu
= $3;
619 proto_packet_finish
();
627 | payload elem_delimiter
{ }
631 : delimiter_nowhite
{ }
640 : number
{ set_byte
((uint8_t) $1); }
641 |
string { set_multi_byte
((uint8_t *) $1 + 1, strlen
($1) - 2); }
651 | proto
{ proto_header_finish
(hdr
); }
658 | expression
'+' expression
660 | expression
'-' expression
662 | expression
'*' expression
664 | expression
'/' expression
666 | expression
'%' expression
668 | expression
'&' expression
670 | expression
'|' expression
672 | expression
'^' expression
674 | expression
'<' '<' expression
676 | expression
'>' '>' expression
685 : K_FILL
'(' number delimiter number
')'
686 { set_fill
($3, $5); }
690 : K_CONST8
'(' expression
')'
691 { set_byte
((uint8_t) $3); }
692 | K_CONST16
'(' expression
')' {
693 uint16_t __c
= cpu_to_be16
((uint16_t) $3);
695 set_multi_byte
((uint8_t *) &__c
, sizeof
(__c
));
697 | K_CONST32
'(' expression
')' {
698 uint32_t __c
= cpu_to_be32
((uint32_t) $3);
700 set_multi_byte
((uint8_t *) &__c
, sizeof
(__c
));
702 | K_CONST64
'(' expression
')' {
703 uint64_t __c
= cpu_to_be64
((uint64_t) $3);
705 set_multi_byte
((uint8_t *) &__c
, sizeof
(__c
));
710 : K_RND
'(' number
')'
715 : K_CSUMIP
'(' number delimiter number
')'
716 { set_csum16
($3, $5, CSUM_IP
); }
717 | K_CSUMTCP
'(' number delimiter number
')'
718 { set_csum16
($3, $5, CSUM_TCP
); }
719 | K_CSUMUDP
'(' number delimiter number
')'
720 { set_csum16
($3, $5, CSUM_UDP
); }
721 | K_CSUMTCP6
'(' number delimiter number
')'
722 { set_csum16
($3, $5, CSUM_TCP6
); }
723 | K_CSUMUDP6
'(' number delimiter number
')'
724 { set_csum16
($3, $5, CSUM_UDP6
); }
725 | K_CSUMICMP6
'(' number delimiter number
')'
726 { set_csum16
($3, $5, CSUM_ICMP6
); }
730 : K_SEQINC
'(' number delimiter number
')'
731 { set_sequential_inc
($3, $5, 1); }
732 | K_SEQINC
'(' number delimiter number delimiter number
')'
733 { set_sequential_inc
($3, $5, $7); }
737 : K_SEQDEC
'(' number delimiter number
')'
738 { set_sequential_dec
($3, $5, 1); }
739 | K_SEQDEC
'(' number delimiter number delimiter number
')'
740 { set_sequential_dec
($3, $5, $7); }
745 { set_dynamic_rnd
(); }
746 | K_DRND
'(' number
')'
749 for
(i
= 0; i
< max
; ++i
)
755 : K_DINC
'(' number delimiter number
')'
756 { set_dynamic_incdec
($3, $5, 1, TYPE_INC
); }
757 | K_DINC
'(' number delimiter number delimiter number
')'
758 { set_dynamic_incdec
($3, $5, $7, TYPE_INC
); }
762 : K_DDEC
'(' number delimiter number
')'
763 { set_dynamic_incdec
($3, $5, 1, TYPE_DEC
); }
764 | K_DDEC
'(' number delimiter number delimiter number
')'
765 { set_dynamic_incdec
($3, $5, $7, TYPE_DEC
); }
785 : '[' skip_white number skip_white
']'
786 { field_index_validate
(field_expr.field
, $3, 1);
787 field_expr.type |
= FIELD_EXPR_OFFSET
;
788 field_expr.val.func.offset
= $3;
789 field_expr.val.func.len
= 1; }
790 |
'[' skip_white number skip_white
':' skip_white number skip_white
']'
791 { field_index_validate
(field_expr.field
, $3, $7);
792 field_expr.type |
= FIELD_EXPR_OFFSET
;
793 field_expr.val.func.offset
= $3;
794 field_expr.val.func.len
= $7; }
798 : number
{ field_expr.type |
= FIELD_EXPR_NUMB
;
799 field_expr.val.number
= $1; }
800 | mac
{ field_expr.type |
= FIELD_EXPR_MAC
;
801 memcpy
(field_expr.val.mac
, $1, sizeof
(field_expr.val.mac
)); }
802 |
string { field_expr.type |
= FIELD_EXPR_STRING
;
803 field_expr.val.str
= xstrdup
($1 + 1);
804 field_expr.val.str
[strlen
($1 + 1) - 1] = '\0'; }
805 | ip4_addr
{ field_expr.type |
= FIELD_EXPR_IP4_ADDR
;
806 field_expr.val.ip4_addr
= $1; }
807 | ip6_addr
{ field_expr.type |
= FIELD_EXPR_IP6_ADDR
;
808 field_expr.val.ip6_addr
= $1; }
809 | K_DINC
'(' ')' { field_expr.type |
= FIELD_EXPR_INC
;
810 field_expr.val.func.type
= PROTO_FIELD_FUNC_INC
;
811 field_expr.val.func.inc
= 1; }
812 | K_DINC
'(' number
')'
813 { field_expr.type |
= FIELD_EXPR_INC
;
814 field_expr.val.func.type
= PROTO_FIELD_FUNC_INC
;
815 field_expr.val.func.inc
= $3; }
816 | K_DINC
'(' number delimiter number
')'
817 { field_expr.type |
= FIELD_EXPR_INC
;
818 field_expr.val.func.type
= PROTO_FIELD_FUNC_INC
;
819 field_expr.val.func.type |
= PROTO_FIELD_FUNC_MIN
;
820 field_expr.val.func.min
= $3;
821 field_expr.val.func.max
= $5;
822 field_expr.val.func.inc
= 1; }
823 | K_DINC
'(' number delimiter number delimiter number
')'
824 { field_expr.type |
= FIELD_EXPR_INC
;
825 field_expr.val.func.type
= PROTO_FIELD_FUNC_INC
;
826 field_expr.val.func.type |
= PROTO_FIELD_FUNC_MIN
;
827 field_expr.val.func.min
= $3;
828 field_expr.val.func.max
= $5;
829 field_expr.val.func.inc
= $7; }
830 | K_DRND
'(' ')' { field_expr.type |
= FIELD_EXPR_RND
;
831 field_expr.val.func.type
= PROTO_FIELD_FUNC_RND
; }
832 | K_DRND
'(' number delimiter number
')'
833 { field_expr.type |
= FIELD_EXPR_RND
;
834 field_expr.val.func.type
= PROTO_FIELD_FUNC_RND
;
835 field_expr.val.func.min
= $3;
836 field_expr.val.func.max
= $5; }
840 : eth
'(' eth_param_list
')' { }
844 : K_ETH
{ proto_add
(PROTO_ETH
); }
850 | eth_expr delimiter eth_param_list
{ }
860 : K_DADDR
{ proto_field_set
(ETH_DST_ADDR
); }
861 | K_SADDR
{ proto_field_set
(ETH_SRC_ADDR
); }
862 | eth_type
{ proto_field_set
(ETH_TYPE
); }
865 : eth_field field_expr skip_white
'=' skip_white field_value_expr
866 { proto_field_expr_eval
(); }
867 | eth_field skip_white
'=' skip_white field_value_expr
868 { proto_field_expr_eval
(); }
872 : pause
'(' pause_param_list
')' { }
876 : K_PAUSE
{ proto_add
(PROTO_PAUSE
); }
882 | pause_expr delimiter pause_param_list
{ }
886 : K_CODE
{ proto_field_set
(PAUSE_OPCODE
); }
887 | K_TIME
{ proto_field_set
(PAUSE_TIME
); }
891 : pause_field field_expr skip_white
'=' skip_white field_value_expr
892 { proto_field_expr_eval
(); }
893 | pause_field skip_white
'=' skip_white field_value_expr
894 { proto_field_expr_eval
(); }
898 : pfc
'(' pfc_param_list
')' { }
902 : K_PFC
{ proto_add
(PROTO_PFC
); }
908 | pfc_expr delimiter pfc_param_list
{ }
912 : K_CODE
{ proto_field_set
(PFC_OPCODE
); }
913 | K_PRIO
{ proto_field_set
(PFC_PRIO
); }
914 | K_PRIO
'(' number
')'
916 yyerror("pfc: Invalid prio(index) parameter");
917 panic
("pfc: prio(0)..prio(7) is allowed only\n");
919 proto_field_set
(PFC_PRIO_0
+ $3); }
920 | K_TIME
'(' number
')'
922 yyerror("pfc: Invalid time(index) parameter");
923 panic
("pfc: time(0)..time(7) is allowed only\n");
925 proto_field_set
(PFC_TIME_0
+ $3); }
929 : pfc_field field_expr skip_white
'=' skip_white field_value_expr
930 { proto_field_expr_eval
(); }
931 | pfc_field skip_white
'=' skip_white field_value_expr
932 { proto_field_expr_eval
(); }
936 : vlan
'(' vlan_param_list
')' { }
940 : K_VLAN
{ proto_add
(PROTO_VLAN
); }
946 | vlan_expr delimiter vlan_param_list
{ }
955 : vlan_type
{ proto_field_set
(VLAN_TPID
); }
956 | K_TCI
{ proto_field_set
(VLAN_TCI
); }
957 | K_PCP
{ proto_field_set
(VLAN_PCP
); }
958 | K_DEI
{ proto_field_set
(VLAN_DEI
); }
959 | K_ID
{ proto_field_set
(VLAN_VID
); }
963 : vlan_field field_expr skip_white
'=' skip_white field_value_expr
964 { proto_field_expr_eval
(); }
965 | vlan_field skip_white
'=' skip_white field_value_expr
966 { proto_field_expr_eval
(); }
968 { proto_hdr_field_set_be16
(hdr
, VLAN_TPID
, ETH_P_8021Q
); }
970 { proto_hdr_field_set_be16
(hdr
, VLAN_TPID
, ETH_P_8021AD
); }
974 : mpls
'(' mpls_param_list
')' { }
978 : K_MPLS
{ proto_add
(PROTO_MPLS
); }
984 | mpls_expr delimiter mpls_param_list
{ }
993 : K_LABEL
{ proto_field_set
(MPLS_LABEL
); }
994 | mpls_tc
{ proto_field_set
(MPLS_TC
); }
995 | K_LAST
{ proto_field_set
(MPLS_LAST
); }
996 | K_TTL
{ proto_field_set
(MPLS_TTL
); }
1000 : mpls_field field_expr skip_white
'=' skip_white field_value_expr
1001 { proto_field_expr_eval
(); }
1002 | mpls_field skip_white
'=' skip_white field_value_expr
1003 { proto_field_expr_eval
(); }
1007 : arp
'(' arp_param_list
')' { }
1013 | arp_expr delimiter arp_param_list
{ }
1018 { proto_field_set
(ARP_HTYPE
); }
1020 { proto_field_set
(ARP_PTYPE
); }
1022 { proto_field_set
(ARP_SHA
); }
1024 { proto_field_set
(ARP_THA
); }
1026 { proto_field_set
(ARP_SPA
); }
1028 { proto_field_set
(ARP_TPA
); }
1032 : arp_field field_expr skip_white
'=' skip_white field_value_expr
1033 { proto_field_expr_eval
(); }
1034 | arp_field skip_white
'=' skip_white field_value_expr
1035 { proto_field_expr_eval
(); }
1036 | K_OPER field_expr skip_white
'=' skip_white field_value_expr
1037 { proto_field_set
(ARP_OPER
);
1038 proto_field_expr_eval
(); }
1039 | K_OPER skip_white
'=' skip_white field_value_expr
1040 { proto_field_set
(ARP_OPER
);
1041 proto_field_expr_eval
(); }
1042 | K_OPER skip_white
'=' skip_white K_REQUEST
1043 { proto_hdr_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REQUEST
); }
1044 | K_OPER skip_white
'=' skip_white K_REPLY
1045 { proto_hdr_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REPLY
); }
1047 { proto_hdr_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REQUEST
); }
1049 { proto_hdr_field_set_be16
(hdr
, ARP_OPER
, ARPOP_REPLY
); }
1053 : K_ARP
{ proto_add
(PROTO_ARP
); }
1057 : ip4
'(' ip4_param_list
')' { }
1063 | ip4_expr delimiter ip4_param_list
{ }
1067 : K_VER
{ proto_field_set
(IP4_VER
); }
1068 | K_IHL
{ proto_field_set
(IP4_IHL
); }
1069 | K_DADDR
{ proto_field_set
(IP4_DADDR
); }
1070 | K_SADDR
{ proto_field_set
(IP4_SADDR
); }
1071 | K_PROT
{ proto_field_set
(IP4_PROTO
); }
1072 | K_TTL
{ proto_field_set
(IP4_TTL
); }
1073 | K_DSCP
{ proto_field_set
(IP4_DSCP
); }
1074 | K_ECN
{ proto_field_set
(IP4_ECN
); }
1075 | K_TOS
{ proto_field_set
(IP4_TOS
); }
1076 | K_LEN
{ proto_field_set
(IP4_LEN
); }
1077 | K_ID
{ proto_field_set
(IP4_ID
); }
1078 | K_FLAGS
{ proto_field_set
(IP4_FLAGS
); }
1079 | K_FRAG
{ proto_field_set
(IP4_FRAG_OFFS
); }
1080 | K_CSUM
{ proto_field_set
(IP4_CSUM
); }
1084 : ip4_field field_expr skip_white
'=' skip_white field_value_expr
1085 { proto_field_expr_eval
(); }
1086 | ip4_field skip_white
'=' skip_white field_value_expr
1087 { proto_field_expr_eval
(); }
1088 | K_DF
{ proto_hdr_field_set_be16
(hdr
, IP4_DF
, 1); }
1089 | K_MF
{ proto_hdr_field_set_be16
(hdr
, IP4_MF
, 1); }
1093 : K_IP4
{ proto_add
(PROTO_IP4
); }
1097 : ip6
'(' ip6_param_list
')' { }
1103 | ip6_expr delimiter ip6_param_list
{ }
1112 : K_VER
{ proto_field_set
(IP6_VER
); }
1113 | K_TC
{ proto_field_set
(IP6_CLASS
); }
1114 | K_FLOW
{ proto_field_set
(IP6_FLOW_LBL
); }
1115 | K_LEN
{ proto_field_set
(IP6_LEN
); }
1116 | K_NEXT_HDR
{ proto_field_set
(IP6_NEXT_HDR
); }
1117 | ip6_hop_limit
{ proto_field_set
(IP6_HOP_LIMIT
); }
1118 | K_SADDR
{ proto_field_set
(IP6_SADDR
); }
1119 | K_DADDR
{ proto_field_set
(IP6_DADDR
) ; }
1123 : ip6_field field_expr skip_white
'=' skip_white field_value_expr
1124 { proto_field_expr_eval
(); }
1125 | ip6_field skip_white
'=' skip_white field_value_expr
1126 { proto_field_expr_eval
(); }
1130 : K_IP6
{ proto_add
(PROTO_IP6
); }
1134 : icmp4
'(' icmp4_param_list
')' { }
1140 | icmp4_expr delimiter icmp4_param_list
{ }
1144 : K_TYPE
{ proto_field_set
(ICMPV4_TYPE
); }
1145 | K_CODE
{ proto_field_set
(ICMPV4_CODE
); }
1146 | K_ID
{ proto_field_set
(ICMPV4_ID
); }
1147 | K_SEQ
{ proto_field_set
(ICMPV4_SEQ
); }
1148 | K_MTU
{ proto_field_set
(ICMPV4_MTU
); }
1149 | K_ADDR
{ proto_field_set
(ICMPV4_REDIR_ADDR
); }
1153 : icmp4_field field_expr skip_white
'=' skip_white field_value_expr
1154 { proto_field_expr_eval
(); }
1155 | icmp4_field skip_white
'=' skip_white field_value_expr
1156 { proto_field_expr_eval
(); }
1158 { proto_hdr_field_set_u8
(hdr
, ICMPV4_TYPE
, ICMP_ECHO
);
1159 proto_hdr_field_set_u8
(hdr
, ICMPV4_CODE
, 0); }
1161 { proto_hdr_field_set_u8
(hdr
, ICMPV4_TYPE
, ICMP_ECHOREPLY
);
1162 proto_hdr_field_set_u8
(hdr
, ICMPV4_CODE
, 0); }
1166 : K_ICMP4
{ proto_add
(PROTO_ICMP4
); }
1170 : icmp6
'(' icmp6_param_list
')' { }
1176 | icmp6_expr delimiter icmp6_param_list
{ }
1180 : K_CODE
{ proto_field_set
(ICMPV6_CODE
); }
1181 | K_CSUM
{ proto_field_set
(ICMPV6_CSUM
); }
1185 : icmp6_field field_expr skip_white
'=' skip_white field_value_expr
1186 { proto_field_expr_eval
(); }
1187 | icmp6_field skip_white
'=' skip_white field_value_expr
1188 { proto_field_expr_eval
(); }
1189 | K_TYPE field_expr skip_white
'=' skip_white field_value_expr
1190 { proto_field_set
(ICMPV6_TYPE
);
1191 proto_field_expr_eval
(); }
1192 | K_TYPE skip_white
'=' skip_white field_value_expr
1193 { proto_field_set
(ICMPV6_TYPE
);
1194 proto_field_expr_eval
(); }
1195 | K_TYPE skip_white
'=' K_ECHO_REQUEST
1196 { proto_hdr_field_set_u8
(hdr
, ICMPV6_TYPE
, ICMPV6_ECHO_REQUEST
); }
1198 { proto_hdr_field_set_u8
(hdr
, ICMPV6_TYPE
, ICMPV6_ECHO_REQUEST
); }
1199 | K_TYPE skip_white
'=' K_ECHO_REPLY
1200 { proto_hdr_field_set_u8
(hdr
, ICMPV6_TYPE
, ICMPV6_ECHO_REPLY
); }
1202 { proto_hdr_field_set_u8
(hdr
, ICMPV6_TYPE
, ICMPV6_ECHO_REPLY
); }
1205 : K_ICMP6
{ proto_add
(PROTO_ICMP6
); }
1209 : udp
'(' udp_param_list
')' { }
1215 | udp_expr delimiter udp_param_list
{ }
1219 : K_SPORT
{ proto_field_set
(UDP_SPORT
); }
1220 | K_DPORT
{ proto_field_set
(UDP_DPORT
); }
1221 | K_LEN
{ proto_field_set
(UDP_LEN
); }
1222 | K_CSUM
{ proto_field_set
(UDP_CSUM
); }
1226 : udp_field field_expr skip_white
'=' skip_white field_value_expr
1227 { proto_field_expr_eval
(); }
1228 | udp_field skip_white
'=' skip_white field_value_expr
1229 { proto_field_expr_eval
(); }
1233 : K_UDP
{ proto_add
(PROTO_UDP
); }
1237 : tcp
'(' tcp_param_list
')' { }
1243 | tcp_expr delimiter tcp_param_list
{ }
1247 : K_SPORT
{ proto_field_set
(TCP_SPORT
); }
1248 | K_DPORT
{ proto_field_set
(TCP_DPORT
); }
1249 | K_SEQ
{ proto_field_set
(TCP_SEQ
); }
1250 | K_ACK_SEQ
{ proto_field_set
(TCP_ACK_SEQ
); }
1251 | K_DOFF
{ proto_field_set
(TCP_DOFF
); }
1252 | K_WINDOW
{ proto_field_set
(TCP_WINDOW
); }
1253 | K_CSUM
{ proto_field_set
(TCP_CSUM
); }
1254 | K_URG_PTR
{ proto_field_set
(TCP_URG_PTR
); }
1258 : tcp_field field_expr skip_white
'=' skip_white field_value_expr
1259 { proto_field_expr_eval
(); }
1260 | tcp_field skip_white
'=' skip_white field_value_expr
1261 { proto_field_expr_eval
(); }
1262 | K_CWR
{ proto_hdr_field_set_be16
(hdr
, TCP_CWR
, 1); }
1263 | K_ECE
{ proto_hdr_field_set_be16
(hdr
, TCP_ECE
, 1); }
1264 | K_URG
{ proto_hdr_field_set_be16
(hdr
, TCP_URG
, 1); }
1265 | K_ACK
{ proto_hdr_field_set_be16
(hdr
, TCP_ACK
, 1); }
1266 | K_PSH
{ proto_hdr_field_set_be16
(hdr
, TCP_PSH
, 1); }
1267 | K_RST
{ proto_hdr_field_set_be16
(hdr
, TCP_RST
, 1); }
1268 | K_SYN
{ proto_hdr_field_set_be16
(hdr
, TCP_SYN
, 1); }
1269 | K_FIN
{ proto_hdr_field_set_be16
(hdr
, TCP_FIN
, 1); }
1273 : K_TCP
{ proto_add
(PROTO_TCP
); }
1277 : dns
'(' dns_param_list
')' { }
1283 | dns_expr delimiter dns_param_list
{ }
1287 : K_ID
{ proto_field_set
(DNS_ID
); }
1288 | K_QR
{ proto_field_set
(DNS_QR
); }
1289 | K_OPER
{ proto_field_set
(DNS_OPCODE
); }
1290 | K_AANSWER
{ proto_field_set
(DNS_AA
); }
1291 | K_TRUNC
{ proto_field_set
(DNS_TC
); }
1292 | K_RDESIRED
{ proto_field_set
(DNS_RD
); }
1293 | K_RAVAIL
{ proto_field_set
(DNS_RA
); }
1294 | K_ZERO
{ proto_field_set
(DNS_ZERO
); }
1295 | K_RCODE
{ proto_field_set
(DNS_RCODE
); }
1296 | K_QDCOUNT
{ proto_field_set
(DNS_QD_COUNT
); }
1297 | K_ANCOUNT
{ proto_field_set
(DNS_AN_COUNT
); }
1298 | K_NSCOUNT
{ proto_field_set
(DNS_NS_COUNT
); }
1299 | K_ARCOUNT
{ proto_field_set
(DNS_AR_COUNT
); }
1303 : K_QUERY
{ proto_push_sub_hdr
(DNS_QUERY_HDR
); }
1307 : K_NAME
{ proto_field_set
(DNS_QUERY_NAME
); }
1311 : K_TYPE
{ proto_field_set
(DNS_QUERY_TYPE
); }
1312 | K_CLASS
{ proto_field_set
(DNS_QUERY_CLASS
); }
1316 : dns_query_field field_expr skip_white
'=' skip_white field_value_expr
1317 { proto_field_expr_eval
(); }
1318 | dns_query_field skip_white
'=' skip_white field_value_expr
1319 { proto_field_expr_eval
(); }
1320 | dns_query_name field_expr skip_white
'=' skip_white field_value_expr
1321 { if
(field_expr.type
& FIELD_EXPR_STRING
)
1322 field_expr.type
= FIELD_EXPR_FQDN
;
1323 proto_field_expr_eval
(); }
1324 | dns_query_name skip_white
'=' skip_white field_value_expr
1325 { if
(field_expr.type
& FIELD_EXPR_STRING
)
1326 field_expr.type
= FIELD_EXPR_FQDN
;
1327 proto_field_expr_eval
(); }
1330 dns_query_param_list
1332 | dns_query_expr
{ }
1333 | dns_query_expr delimiter dns_query_param_list
{ }
1337 : dns_query
'(' dns_query_param_list
')' { }
1341 : K_ANSWER
{ proto_push_sub_hdr
(DNS_ANSWER_HDR
); }
1342 | K_AUTH
{ proto_push_sub_hdr
(DNS_AUTH_HDR
); }
1343 | K_ADD
{ proto_push_sub_hdr
(DNS_ADD_HDR
); }
1347 : K_NAME
{ proto_field_set
(DNS_RRECORD_NAME
); }
1350 dns_rrecord_data_addr
1352 { proto_hdr_field_set_u32
(hdr
, DNS_RRECORD_DATA
, $1.s_addr
);
1353 proto_hdr_field_set_be16
(hdr
, DNS_RRECORD_TYPE
, 1); }
1355 { proto_hdr_field_set_bytes
(hdr
, DNS_RRECORD_DATA
, (uint8_t *)&$1.s6_addr
, 16);
1356 proto_hdr_field_set_be16
(hdr
, DNS_RRECORD_TYPE
, 28); }
1359 dns_rrecord_data_fqdn
1361 { char *str
= xstrdup
($1 + 1);
1363 str
[strlen
($1 + 1) - 1] = '\0';
1364 fqdn
= str2fqdn
(str
);
1365 proto_hdr_field_set_bytes
(hdr
, DNS_RRECORD_DATA
, (uint8_t *) fqdn
, strlen
(fqdn
) + 1);
1370 dns_rrecord_data_expr
1371 : K_ADDR
'(' skip_white dns_rrecord_data_addr skip_white
')'
1373 | K_NS
'(' skip_white dns_rrecord_data_fqdn skip_white
')'
1374 { proto_hdr_field_set_be16
(hdr
, DNS_RRECORD_TYPE
, 2); }
1375 | K_CNAME
'(' skip_white dns_rrecord_data_fqdn skip_white
')'
1376 { proto_hdr_field_set_be16
(hdr
, DNS_RRECORD_TYPE
, 5); }
1377 | K_PTR
'(' skip_white dns_rrecord_data_fqdn skip_white
')'
1378 { proto_hdr_field_set_be16
(hdr
, DNS_RRECORD_TYPE
, 12); }
1382 : K_TYPE
{ proto_field_set
(DNS_RRECORD_TYPE
); }
1383 | K_CLASS
{ proto_field_set
(DNS_RRECORD_CLASS
); }
1384 | K_TTL
{ proto_field_set
(DNS_RRECORD_TTL
); }
1385 | K_LEN
{ proto_field_set
(DNS_RRECORD_LEN
); }
1386 | K_DATA
{ proto_field_set
(DNS_RRECORD_DATA
); }
1390 : dns_rrecord_field field_expr skip_white
'=' skip_white field_value_expr
1391 { proto_field_expr_eval
(); }
1392 | dns_rrecord_field skip_white
'=' skip_white field_value_expr
1393 { proto_field_expr_eval
(); }
1394 | dns_rrecord_name field_expr skip_white
'=' skip_white field_value_expr
1395 { if
(field_expr.type
& FIELD_EXPR_STRING
)
1396 field_expr.type
= FIELD_EXPR_FQDN
;
1397 proto_field_expr_eval
(); }
1398 | dns_rrecord_name skip_white
'=' skip_white field_value_expr
1399 { if
(field_expr.type
& FIELD_EXPR_STRING
)
1400 field_expr.type
= FIELD_EXPR_FQDN
;
1401 proto_field_expr_eval
(); }
1402 | dns_rrecord_data_expr
1406 dns_rrecord_param_list
1408 | dns_rrecord_expr
{ }
1409 | dns_rrecord_expr delimiter dns_rrecord_param_list
{ }
1413 : dns_rrecord
'(' dns_rrecord_param_list
')' { }
1417 : dns_field field_expr skip_white
'=' skip_white field_value_expr
1418 { proto_field_expr_eval
(); }
1419 | dns_field skip_white
'=' skip_white field_value_expr
1420 { proto_field_expr_eval
(); }
1421 | dns_query_hdr
{ proto_pop_sub_hdr
(); }
1422 | dns_rrecord_hdr
{ proto_pop_sub_hdr
(); }
1426 : K_DNS
{ proto_add
(PROTO_DNS
); }
1430 static void finalize_packet
(void)
1432 /* XXX hack ... we allocated one packet pointer too much */
1437 static void dump_conf
(void)
1441 for
(i
= 0; i
< plen
; ++i
) {
1442 printf
("[%zu] pkt\n", i
);
1443 printf
(" len %zu cnts %zu rnds %zu\n",
1446 packet_dyn
[i
].rlen
);
1448 printf
(" payload ");
1449 for
(j
= 0; j
< packets
[i
].len
; ++j
)
1450 printf
("%02x ", packets
[i
].payload
[j
]);
1453 for
(j
= 0; j
< packet_dyn
[i
].clen
; ++j
)
1454 printf
(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j
,
1455 packet_dyn
[i
].cnt
[j
].min
,
1456 packet_dyn
[i
].cnt
[j
].max
,
1457 packet_dyn
[i
].cnt
[j
].inc
,
1458 (intmax_t)packet_dyn
[i
].cnt
[j
].off
,
1459 packet_dyn
[i
].cnt
[j
].type
== TYPE_INC ?
1462 for
(j
= 0; j
< packet_dyn
[i
].rlen
; ++j
)
1463 printf
(" rnd%zu off %jd\n", j
,
1464 (intmax_t)packet_dyn
[i
].rnd
[j
].off
);
1468 void cleanup_packets
(void)
1472 for
(i
= 0; i
< plen
; ++i
) {
1473 struct packet
*pkt
= &packets
[i
];
1476 xfree
(pkt
->payload
);
1478 for
(j
= 0; j
< pkt
->headers_count
; j
++) {
1479 struct proto_hdr
*hdr
= pkt
->headers
[j
];
1482 for
(k
= 0; k
< hdr
->sub_headers_count
; k
++)
1483 xfree
(hdr
->sub_headers
[k
]);
1485 if
(hdr
->sub_headers
)
1486 xfree
(hdr
->sub_headers
);
1497 for
(i
= 0; i
< dlen
; ++i
) {
1498 free
(packet_dyn
[i
].cnt
);
1499 free
(packet_dyn
[i
].rnd
);
1501 for
(j
= 0; j
< packet_dyn
[j
].flen
; j
++)
1502 xfree
(packet_dyn
[i
].fields
[j
]);
1504 free
(packet_dyn
[i
].fields
);
1510 void compile_packets
(char *file
, bool verbose
, unsigned int cpu
,
1511 bool invoke_cpp
, char *const cpp_argv
[])
1516 if
(strncmp
("-", file
, strlen
("-")) && access
(file
, R_OK
)) {
1517 fprintf
(stderr
, "Cannot access %s: %s!\n", file
, strerror
(errno
));
1521 memset
(tmp_file
, 0, sizeof
(tmp_file
));
1525 if
(cpp_exec
(file
, tmp_file
, sizeof
(tmp_file
), cpp_argv
)) {
1526 fprintf
(stderr
, "Failed to invoke C preprocessor!\n");
1532 if
(!strncmp
("-", file
, strlen
("-")))
1535 yyin
= fopen
(file
, "r");
1537 fprintf
(stderr
, "Cannot open %s: %s!\n", file
, strerror
(errno
));
1546 if
(our_cpu
== 0 && verbose
)
1551 if
(yyin
&& yyin
!= stdin
)
1560 void compile_packets_str
(char *str
, bool verbose
, unsigned int cpu
)
1567 yy_scan_string
(str
);
1572 if
(our_cpu
== 0 && verbose
)
1583 void yyerror(const char *err
)
1585 fprintf
(stderr
, "Syntax error at line %d, char '%s': %s\n", yylineno
, yytext
, err
);