trafgen: parser: Add support of 'dinc' function for proto fields
[netsniff-ng.git] / trafgen_parser.y
blob9b313d14bfd19bcbff84fc6d7316a01f240a8c9f
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 <stdint.h>
16 #include <stdbool.h>
17 #include <errno.h>
18 #include <libgen.h>
19 #include <signal.h>
20 #include <unistd.h>
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>
27 #include "xmalloc.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 "built_in.h"
35 #include "die.h"
36 #include "str.h"
37 #include "csum.h"
38 #include "cpp.h"
40 #define YYERROR_VERBOSE 0
41 #define YYDEBUG 0
42 #define YYENABLE_NLS 1
43 #define YYLTYPE_IS_TRIVIAL 1
44 #define ENABLE_NLS 1
46 extern FILE *yyin;
47 extern int yylex(void);
48 extern void yy_scan_string(char *);
49 extern void yylex_destroy();
50 extern void yyerror(const char *);
51 extern int yylineno;
52 extern char *yytext;
54 extern struct packet *packets;
55 extern size_t plen;
57 #define packet_last (plen - 1)
59 #define payload_last (packets[packet_last].len - 1)
61 extern struct packet_dyn *packet_dyn;
62 extern size_t dlen;
64 #define packetd_last (dlen - 1)
66 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
67 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
68 #define packetds_last (packet_dyn[packetd_last].slen - 1)
70 static int our_cpu, min_cpu = -1, max_cpu = -1;
72 enum field_expr_type_t {
73 FIELD_EXPR_UNKNOWN,
74 FIELD_EXPR_NUMB,
75 FIELD_EXPR_MAC,
76 FIELD_EXPR_IP4_ADDR,
77 FIELD_EXPR_IP6_ADDR,
78 FIELD_EXPR_INC,
81 struct proto_field_expr {
82 enum field_expr_type_t type;
83 struct proto_field *field;
85 union {
86 struct in_addr ip4_addr;
87 struct in6_addr ip6_addr;
88 long long int number;
89 uint8_t bytes[256];
90 struct proto_field_func func;
91 } val;
94 static struct proto_field_expr field_expr;
95 static struct proto_hdr *hdr;
97 static inline int test_ignore(void)
99 if (min_cpu < 0 && max_cpu < 0)
100 return 0;
101 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
102 return 0;
103 else
104 return 1;
107 static inline void __init_new_packet_slot(struct packet *slot)
109 slot->payload = NULL;
110 slot->len = 0;
113 static inline void __init_new_counter_slot(struct packet_dyn *slot)
115 slot->cnt = NULL;
116 slot->clen = 0;
119 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
121 slot->rnd = NULL;
122 slot->rlen = 0;
125 static inline void __init_new_csum_slot(struct packet_dyn *slot)
127 slot->csum = NULL;
128 slot->slen = 0;
131 static inline void __init_new_fields_slot(struct packet_dyn *slot)
133 slot->fields = NULL;
134 slot->flen = 0;
137 static inline void __setup_new_counter(struct counter *c, uint8_t start,
138 uint8_t stop, uint8_t stepping,
139 int type)
141 c->min = start;
142 c->max = stop;
143 c->inc = stepping;
144 c->val = (type == TYPE_INC) ? start : stop;
145 c->off = payload_last;
146 c->type = type;
149 static inline void __setup_new_randomizer(struct randomizer *r)
151 r->off = payload_last;
154 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
155 enum csum which)
157 s->off = payload_last - 1;
158 s->from = from;
159 s->to = to;
160 s->which = which;
163 static void realloc_packet(void)
165 if (test_ignore())
166 return;
168 plen++;
169 packets = xrealloc(packets, plen * sizeof(*packets));
171 __init_new_packet_slot(&packets[packet_last]);
173 dlen++;
174 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
176 __init_new_counter_slot(&packet_dyn[packetd_last]);
177 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
178 __init_new_csum_slot(&packet_dyn[packetd_last]);
179 __init_new_fields_slot(&packet_dyn[packetd_last]);
182 struct packet *current_packet(void)
184 return &packets[packet_last];
187 uint32_t current_packet_id(void)
189 return packet_last;
192 struct packet *packet_get(uint32_t id)
194 return &packets[id];
197 static void set_byte(uint8_t val)
199 struct packet *pkt = &packets[packet_last];
201 if (test_ignore())
202 return;
204 pkt->len++;
205 pkt->payload = xrealloc(pkt->payload, pkt->len);
206 pkt->payload[payload_last] = val;
209 static void set_multi_byte(uint8_t *s, size_t len)
211 size_t i;
213 for (i = 0; i < len; ++i)
214 set_byte(s[i]);
217 void set_fill(uint8_t val, size_t len)
219 size_t i;
220 struct packet *pkt = &packets[packet_last];
222 if (test_ignore())
223 return;
225 pkt->len += len;
226 pkt->payload = xrealloc(pkt->payload, pkt->len);
227 for (i = 0; i < len; ++i)
228 pkt->payload[payload_last - i] = val;
231 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
233 struct packet *pkt = &packets[packet_last];
234 struct packet_dyn *pktd = &packet_dyn[packetd_last];
236 pkt->len += 2;
237 pkt->payload = xrealloc(pkt->payload, pkt->len);
239 pktd->slen++;
240 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
242 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
245 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
247 struct packet *pkt = &packets[packet_last];
248 uint16_t sum;
249 uint8_t *psum;
251 sum = htons(calc_csum(pkt->payload + from, to - from));
252 psum = (uint8_t *) &sum;
254 set_byte(psum[0]);
255 set_byte(psum[1]);
258 static inline bool is_dynamic_csum(enum csum which)
260 switch (which) {
261 case CSUM_UDP:
262 case CSUM_TCP:
263 case CSUM_UDP6:
264 case CSUM_TCP6:
265 return true;
266 default:
267 return false;
271 static void set_csum16(size_t from, size_t to, enum csum which)
273 struct packet *pkt = &packets[packet_last];
274 struct packet_dyn *pktd = &packet_dyn[packetd_last];
276 if (test_ignore())
277 return;
279 if (to < from) {
280 size_t tmp = to;
282 to = from;
283 from = tmp;
286 bug_on(!(from < to));
288 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
289 __set_csum16_dynamic(from, to, which);
290 else
291 __set_csum16_static(from, to, which);
294 static void set_rnd(size_t len)
296 size_t i;
297 struct packet *pkt = &packets[packet_last];
299 if (test_ignore())
300 return;
302 pkt->len += len;
303 pkt->payload = xrealloc(pkt->payload, pkt->len);
304 for (i = 0; i < len; ++i)
305 pkt->payload[payload_last - i] = (uint8_t) rand();
308 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
310 size_t i;
311 struct packet *pkt = &packets[packet_last];
313 if (test_ignore())
314 return;
316 pkt->len += len;
317 pkt->payload = xrealloc(pkt->payload, pkt->len);
318 for (i = 0; i < len; ++i) {
319 off_t off = len - 1 - i;
321 pkt->payload[payload_last - off] = start;
322 start += stepping;
326 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
328 size_t i;
329 struct packet *pkt = &packets[packet_last];
331 if (test_ignore())
332 return;
334 pkt->len += len;
335 pkt->payload = xrealloc(pkt->payload, pkt->len);
336 for (i = 0; i < len; ++i) {
337 int off = len - 1 - i;
339 pkt->payload[payload_last - off] = start;
340 start -= stepping;
344 static void set_dynamic_rnd(void)
346 struct packet *pkt = &packets[packet_last];
347 struct packet_dyn *pktd = &packet_dyn[packetd_last];
349 if (test_ignore())
350 return;
352 pkt->len++;
353 pkt->payload = xrealloc(pkt->payload, pkt->len);
355 pktd->rlen++;
356 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
358 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
361 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
362 int type)
364 struct packet *pkt = &packets[packet_last];
365 struct packet_dyn *pktd = &packet_dyn[packetd_last];
367 if (test_ignore())
368 return;
370 pkt->len++;
371 pkt->payload = xrealloc(pkt->payload, pkt->len);
373 pktd->clen++;
374 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
376 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
379 static void proto_add(enum proto_id pid)
381 hdr = proto_header_push(pid);
384 static void proto_field_set(uint32_t fid)
386 field_expr.field = proto_field_by_id(hdr, fid);
389 static void proto_field_func_setup(struct proto_field *field, struct proto_field_func *func)
391 struct packet_dyn *pkt_dyn;
393 proto_field_func_add(field->hdr, field->id, func);
395 pkt_dyn = &packet_dyn[packetd_last];
396 pkt_dyn->flen++;
397 pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
398 sizeof(struct proto_field *));
399 pkt_dyn->fields[pkt_dyn->flen - 1] = field;
402 static void proto_field_expr_eval(void)
404 struct proto_field *field = field_expr.field;
406 switch (field_expr.type) {
407 case FIELD_EXPR_NUMB:
408 if (field->len == 1)
409 proto_field_set_u8(hdr, field->id, field_expr.val.number);
410 else if (field->len == 2)
411 proto_field_set_be16(hdr, field->id, field_expr.val.number);
412 else if (field->len == 4)
413 proto_field_set_be32(hdr, field->id, field_expr.val.number);
414 else
415 bug();
416 break;
418 case FIELD_EXPR_MAC:
419 proto_field_set_bytes(hdr, field->id, field_expr.val.bytes);
420 break;
422 case FIELD_EXPR_IP4_ADDR:
423 proto_field_set_u32(hdr, field->id, field_expr.val.ip4_addr.s_addr);
424 break;
426 case FIELD_EXPR_IP6_ADDR:
427 proto_field_set_bytes(hdr, field->id,
428 (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
429 break;
431 case FIELD_EXPR_INC:
432 if (field_expr.val.func.min
433 && field_expr.val.func.min >= field_expr.val.func.max)
434 panic("dinc(): min(%u) can't be >= max(%u)\n",
435 field_expr.val.func.min, field_expr.val.func.max);
437 proto_field_func_setup(field, &field_expr.val.func);
438 break;
440 case FIELD_EXPR_UNKNOWN:
441 default:
442 bug();
445 memset(&field_expr, 0, sizeof(field_expr));
450 %union {
451 struct in_addr ip4_addr;
452 struct in6_addr ip6_addr;
453 long long int number;
454 uint8_t bytes[256];
455 char *str;
458 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
459 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
461 %token K_DADDR K_SADDR K_ETYPE K_TYPE
462 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
463 %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
464 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
465 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
466 %token K_SPORT K_DPORT
467 %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
468 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
469 %token K_LABEL K_TC K_LAST K_EXP
471 %token K_ADDR K_MTU
473 %token K_ETH
474 %token K_VLAN K_MPLS
475 %token K_ARP
476 %token K_IP4 K_IP6
477 %token K_ICMP4 K_ICMP6
478 %token K_UDP K_TCP
480 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
482 %token number string mac ip4_addr ip6_addr
484 %type <number> number expression
485 %type <str> string
486 %type <bytes> mac
487 %type <ip4_addr> ip4_addr
488 %type <ip6_addr> ip6_addr
490 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
494 packets
495 : { }
496 | packets packet { }
497 | packets inline_comment { }
498 | packets K_WHITE { }
501 inline_comment
502 : K_COMMENT { }
505 cpu_delim
506 : ':' { }
507 | '-' { }
510 delimiter_nowhite
511 : ',' { }
512 | ',' K_WHITE { }
515 noenforce_white
516 : { }
517 | K_WHITE { }
518 | delimiter_nowhite { }
521 skip_white
522 : { }
523 | K_WHITE { }
525 packet
526 : '{' noenforce_white payload noenforce_white '}' {
527 min_cpu = max_cpu = -1;
529 proto_packet_finish();
531 realloc_packet();
533 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
534 min_cpu = $3;
535 max_cpu = $5;
537 if (min_cpu > max_cpu) {
538 int tmp = min_cpu;
540 min_cpu = max_cpu;
541 max_cpu = tmp;
544 proto_packet_finish();
546 realloc_packet();
548 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
549 min_cpu = max_cpu = $3;
551 proto_packet_finish();
553 realloc_packet();
557 payload
558 : elem { }
559 | payload elem_delimiter { }
562 delimiter
563 : delimiter_nowhite { }
564 | K_WHITE { }
567 elem_delimiter
568 : delimiter elem { }
571 elem
572 : number { set_byte((uint8_t) $1); }
573 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
574 | fill { }
575 | rnd { }
576 | drnd { }
577 | seqinc { }
578 | seqdec { }
579 | dinc { }
580 | ddec { }
581 | csum { }
582 | const { }
583 | proto { proto_header_finish(hdr); }
584 | inline_comment { }
587 expression
588 : number
589 { $$ = $1; }
590 | expression '+' expression
591 { $$ = $1 + $3; }
592 | expression '-' expression
593 { $$ = $1 - $3; }
594 | expression '*' expression
595 { $$ = $1 * $3; }
596 | expression '/' expression
597 { $$ = $1 / $3; }
598 | expression '%' expression
599 { $$ = $1 % $3; }
600 | expression '&' expression
601 { $$ = $1 & $3; }
602 | expression '|' expression
603 { $$ = $1 | $3; }
604 | expression '^' expression
605 { $$ = $1 ^ $3; }
606 | expression '<' '<' expression
607 { $$ = $1 << $4; }
608 | expression '>' '>' expression
609 { $$ = $1 >> $4; }
610 | '-' expression
611 { $$ = -1 * $2; }
612 | '(' expression ')'
613 { $$ = $2;}
616 fill
617 : K_FILL '(' number delimiter number ')'
618 { set_fill($3, $5); }
621 const
622 : K_CONST8 '(' expression ')'
623 { set_byte((uint8_t) $3); }
624 | K_CONST16 '(' expression ')' {
625 uint16_t __c = cpu_to_be16((uint16_t) $3);
627 set_multi_byte((uint8_t *) &__c, sizeof(__c));
629 | K_CONST32 '(' expression ')' {
630 uint32_t __c = cpu_to_be32((uint32_t) $3);
632 set_multi_byte((uint8_t *) &__c, sizeof(__c));
634 | K_CONST64 '(' expression ')' {
635 uint64_t __c = cpu_to_be64((uint64_t) $3);
637 set_multi_byte((uint8_t *) &__c, sizeof(__c));
642 : K_RND '(' number ')'
643 { set_rnd($3); }
646 csum
647 : K_CSUMIP '(' number delimiter number ')'
648 { set_csum16($3, $5, CSUM_IP); }
649 | K_CSUMTCP '(' number delimiter number ')'
650 { set_csum16($3, $5, CSUM_TCP); }
651 | K_CSUMUDP '(' number delimiter number ')'
652 { set_csum16($3, $5, CSUM_UDP); }
653 | K_CSUMTCP6 '(' number delimiter number ')'
654 { set_csum16($3, $5, CSUM_TCP6); }
655 | K_CSUMUDP6 '(' number delimiter number ')'
656 { set_csum16($3, $5, CSUM_UDP6); }
659 seqinc
660 : K_SEQINC '(' number delimiter number ')'
661 { set_sequential_inc($3, $5, 1); }
662 | K_SEQINC '(' number delimiter number delimiter number ')'
663 { set_sequential_inc($3, $5, $7); }
666 seqdec
667 : K_SEQDEC '(' number delimiter number ')'
668 { set_sequential_dec($3, $5, 1); }
669 | K_SEQDEC '(' number delimiter number delimiter number ')'
670 { set_sequential_dec($3, $5, $7); }
673 drnd
674 : K_DRND '(' ')'
675 { set_dynamic_rnd(); }
676 | K_DRND '(' number ')'
678 int i, max = $3;
679 for (i = 0; i < max; ++i)
680 set_dynamic_rnd();
684 dinc
685 : K_DINC '(' number delimiter number ')'
686 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
687 | K_DINC '(' number delimiter number delimiter number ')'
688 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
691 ddec
692 : K_DDEC '(' number delimiter number ')'
693 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
694 | K_DDEC '(' number delimiter number delimiter number ')'
695 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
698 proto
699 : eth_proto { }
700 | vlan_proto { }
701 | mpls_proto { }
702 | arp_proto { }
703 | ip4_proto { }
704 | ip6_proto { }
705 | icmp4_proto { }
706 | icmpv6_proto { }
707 | udp_proto { }
708 | tcp_proto { }
711 field_expr
712 : number { field_expr.type = FIELD_EXPR_NUMB;
713 field_expr.val.number = $1; }
714 | mac { field_expr.type = FIELD_EXPR_MAC;
715 memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); }
716 | ip4_addr { field_expr.type = FIELD_EXPR_IP4_ADDR;
717 field_expr.val.ip4_addr = $1; }
718 | ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
719 field_expr.val.ip6_addr = $1; }
720 | K_DINC '(' ')' { field_expr.type = FIELD_EXPR_INC;
721 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
722 field_expr.val.func.inc = 1; }
723 | K_DINC '(' number ')'
724 { field_expr.type = FIELD_EXPR_INC;
725 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
726 field_expr.val.func.inc = $3; }
727 | K_DINC '(' number delimiter number ')'
728 { field_expr.type = FIELD_EXPR_INC;
729 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
730 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
731 field_expr.val.func.min = $3;
732 field_expr.val.func.max = $5;
733 field_expr.val.func.inc = 1; }
734 | K_DINC '(' number delimiter number delimiter number ')'
735 { field_expr.type = FIELD_EXPR_INC;
736 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
737 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
738 field_expr.val.func.min = $3;
739 field_expr.val.func.max = $5;
740 field_expr.val.func.inc = $7; }
743 eth_proto
744 : eth '(' eth_param_list ')' { }
748 : K_ETH { proto_add(PROTO_ETH); }
751 eth_param_list
752 : { }
753 | eth_expr { }
754 | eth_expr delimiter eth_param_list { }
757 eth_type
758 : K_ETYPE { }
759 | K_TYPE { }
760 | K_PROT { }
763 eth_field
764 : K_DADDR { proto_field_set(ETH_DST_ADDR); }
765 | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
766 | eth_type { proto_field_set(ETH_TYPE); }
768 eth_expr
769 : eth_field skip_white '=' skip_white field_expr
770 { proto_field_expr_eval(); }
773 vlan_proto
774 : vlan '(' vlan_param_list ')' { }
777 vlan
778 : K_VLAN { proto_add(PROTO_VLAN); }
781 vlan_param_list
782 : { }
783 | vlan_expr { }
784 | vlan_expr delimiter vlan_param_list { }
787 vlan_type
788 : K_TPID { }
789 | K_PROT
792 vlan_field
793 : vlan_type { proto_field_set(VLAN_TPID); }
794 | K_TCI { proto_field_set(VLAN_TCI); }
795 | K_PCP { proto_field_set(VLAN_PCP); }
796 | K_DEI { proto_field_set(VLAN_DEI); }
797 | K_ID { proto_field_set(VLAN_VID); }
800 vlan_expr
801 : vlan_field skip_white '=' skip_white field_expr
802 { proto_field_expr_eval(); }
803 | K_1Q
804 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
805 | K_1AD
806 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
809 mpls_proto
810 : mpls '(' mpls_param_list ')' { }
813 mpls
814 : K_MPLS { proto_add(PROTO_MPLS); }
817 mpls_param_list
818 : { }
819 | mpls_expr { }
820 | mpls_expr delimiter mpls_param_list { }
823 mpls_tc
824 : K_TC { }
825 | K_EXP { }
828 mpls_field
829 : K_LABEL { proto_field_set(MPLS_LABEL); }
830 | mpls_tc { proto_field_set(MPLS_TC); }
831 | K_LAST { proto_field_set(MPLS_LAST); }
832 | K_TTL { proto_field_set(MPLS_TTL); }
835 mpls_expr
836 : mpls_field skip_white '=' skip_white field_expr
837 { proto_field_expr_eval(); }
839 arp_proto
840 : arp '(' arp_param_list ')' { }
843 arp_param_list
844 : { }
845 | arp_expr { }
846 | arp_expr delimiter arp_param_list { }
849 arp_field
850 : K_HTYPE
851 { proto_field_set(ARP_HTYPE); }
852 | K_PTYPE
853 { proto_field_set(ARP_PTYPE); }
854 | K_SHA
855 { proto_field_set(ARP_SHA); }
856 | K_THA
857 { proto_field_set(ARP_THA); }
858 | K_SPA
859 { proto_field_set(ARP_SPA); }
860 | K_TPA
861 { proto_field_set(ARP_TPA); }
864 arp_expr
865 : arp_field skip_white '=' skip_white field_expr
866 { proto_field_expr_eval(); }
867 | K_OPER skip_white '=' skip_white field_expr
868 { proto_field_set(ARP_OPER);
869 proto_field_expr_eval(); }
870 | K_OPER skip_white '=' skip_white K_REQUEST
871 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
872 | K_OPER skip_white '=' skip_white K_REPLY
873 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
874 | K_REQUEST
875 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
876 | K_REPLY
877 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
880 : K_ARP { proto_add(PROTO_ARP); }
883 ip4_proto
884 : ip4 '(' ip4_param_list ')' { }
887 ip4_param_list
888 : { }
889 | ip4_expr { }
890 | ip4_expr delimiter ip4_param_list { }
893 ip4_field
894 : K_VER { proto_field_set(IP4_VER); }
895 | K_IHL { proto_field_set(IP4_IHL); }
896 | K_DADDR { proto_field_set(IP4_DADDR); }
897 | K_SADDR { proto_field_set(IP4_SADDR); }
898 | K_PROT { proto_field_set(IP4_PROTO); }
899 | K_TTL { proto_field_set(IP4_TTL); }
900 | K_DSCP { proto_field_set(IP4_DSCP); }
901 | K_ECN { proto_field_set(IP4_ECN); }
902 | K_TOS { proto_field_set(IP4_TOS); }
903 | K_LEN { proto_field_set(IP4_LEN); }
904 | K_ID { proto_field_set(IP4_ID); }
905 | K_FLAGS { proto_field_set(IP4_FLAGS); }
906 | K_FRAG { proto_field_set(IP4_FRAG_OFFS); }
907 | K_CSUM { proto_field_set(IP4_CSUM); }
910 ip4_expr
911 : ip4_field skip_white '=' skip_white field_expr
912 { proto_field_expr_eval(); }
913 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
914 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
918 : K_IP4 { proto_add(PROTO_IP4); }
921 ip6_proto
922 : ip6 '(' ip6_param_list ')' { }
925 ip6_param_list
926 : { }
927 | ip6_expr { }
928 | ip6_expr delimiter ip6_param_list { }
931 ip6_hop_limit
932 : K_HOP_LIMIT { }
933 | K_TTL { }
936 ip6_field
937 : K_VER { proto_field_set(IP6_VER); }
938 | K_TC { proto_field_set(IP6_CLASS); }
939 | K_FLOW { proto_field_set(IP6_FLOW_LBL); }
940 | K_LEN { proto_field_set(IP6_LEN); }
941 | K_NEXT_HDR { proto_field_set(IP6_NEXT_HDR); }
942 | ip6_hop_limit { proto_field_set(IP6_HOP_LIMIT); }
943 | K_SADDR { proto_field_set(IP6_SADDR); }
944 | K_DADDR { proto_field_set(IP6_DADDR) ; }
947 ip6_expr
948 : ip6_field skip_white '=' skip_white field_expr
949 { proto_field_expr_eval(); }
953 : K_IP6 { proto_add(PROTO_IP6); }
956 icmp4_proto
957 : icmp4 '(' icmp4_param_list ')' { }
960 icmp4_param_list
961 : { }
962 | icmp4_expr { }
963 | icmp4_expr delimiter icmp4_param_list { }
966 icmp4_field
967 : K_TYPE { proto_field_set(ICMPV4_TYPE); }
968 | K_CODE { proto_field_set(ICMPV4_CODE); }
969 | K_ID { proto_field_set(ICMPV4_ID); }
970 | K_SEQ { proto_field_set(ICMPV4_SEQ); }
971 | K_MTU { proto_field_set(ICMPV4_MTU); }
972 | K_ADDR { proto_field_set(ICMPV4_REDIR_ADDR); }
975 icmp4_expr
976 : icmp4_field skip_white '=' skip_white field_expr
977 { proto_field_expr_eval(); }
978 | K_ECHO_REQUEST
979 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
980 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
981 | K_ECHO_REPLY
982 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
983 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
986 icmp4
987 : K_ICMP4 { proto_add(PROTO_ICMP4); }
990 icmpv6_proto
991 : icmp6 '(' icmp6_param_list ')' { }
993 icmp6_param_list
994 : { }
995 | icmp6_expr { }
996 | icmp6_expr delimiter icmp6_param_list { }
999 icmp6_field
1000 : K_CODE { proto_field_set(ICMPV6_CODE); }
1001 | K_CSUM { proto_field_set(ICMPV6_CSUM); }
1004 icmp6_expr
1005 : icmp6_field skip_white '=' skip_white field_expr
1006 { proto_field_expr_eval(); }
1007 | K_TYPE skip_white '=' skip_white field_expr
1008 { proto_field_set(ICMPV6_TYPE);
1009 proto_field_expr_eval(); }
1010 | K_TYPE skip_white '=' K_ECHO_REQUEST
1011 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1012 | K_ECHO_REQUEST
1013 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1014 | K_TYPE skip_white '=' K_ECHO_REPLY
1015 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1016 | K_ECHO_REPLY
1017 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1019 icmp6
1020 : K_ICMP6 { proto_add(PROTO_ICMP6); }
1023 udp_proto
1024 : udp '(' udp_param_list ')' { }
1027 udp_param_list
1028 : { }
1029 | udp_expr { }
1030 | udp_expr delimiter udp_param_list { }
1033 udp_field
1034 : K_SPORT { proto_field_set(UDP_SPORT); }
1035 | K_DPORT { proto_field_set(UDP_DPORT); }
1036 | K_LEN { proto_field_set(UDP_LEN); }
1037 | K_CSUM { proto_field_set(UDP_CSUM); }
1040 udp_expr
1041 : udp_field skip_white '=' skip_white field_expr
1042 { proto_field_expr_eval(); }
1046 : K_UDP { proto_add(PROTO_UDP); }
1049 tcp_proto
1050 : tcp '(' tcp_param_list ')' { }
1053 tcp_param_list
1054 : { }
1055 | tcp_expr { }
1056 | tcp_expr delimiter tcp_param_list { }
1059 tcp_field
1060 : K_SPORT { proto_field_set(TCP_SPORT); }
1061 | K_DPORT { proto_field_set(TCP_DPORT); }
1062 | K_SEQ { proto_field_set(TCP_SEQ); }
1063 | K_ACK_SEQ { proto_field_set(TCP_ACK_SEQ); }
1064 | K_DOFF { proto_field_set(TCP_DOFF); }
1065 | K_WINDOW { proto_field_set(TCP_WINDOW); }
1066 | K_CSUM { proto_field_set(TCP_CSUM); }
1067 | K_URG_PTR { proto_field_set(TCP_URG_PTR); }
1070 tcp_expr
1071 : tcp_field skip_white '=' skip_white field_expr
1072 { proto_field_expr_eval(); }
1073 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
1074 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
1075 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
1076 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
1077 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
1078 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
1079 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
1080 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
1084 : K_TCP { proto_add(PROTO_TCP); }
1089 static void finalize_packet(void)
1091 /* XXX hack ... we allocated one packet pointer too much */
1092 plen--;
1093 dlen--;
1096 static void dump_conf(void)
1098 size_t i, j;
1100 for (i = 0; i < plen; ++i) {
1101 printf("[%zu] pkt\n", i);
1102 printf(" len %zu cnts %zu rnds %zu\n",
1103 packets[i].len,
1104 packet_dyn[i].clen,
1105 packet_dyn[i].rlen);
1107 printf(" payload ");
1108 for (j = 0; j < packets[i].len; ++j)
1109 printf("%02x ", packets[i].payload[j]);
1110 printf("\n");
1112 for (j = 0; j < packet_dyn[i].clen; ++j)
1113 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
1114 packet_dyn[i].cnt[j].min,
1115 packet_dyn[i].cnt[j].max,
1116 packet_dyn[i].cnt[j].inc,
1117 (intmax_t)packet_dyn[i].cnt[j].off,
1118 packet_dyn[i].cnt[j].type == TYPE_INC ?
1119 "inc" : "dec");
1121 for (j = 0; j < packet_dyn[i].rlen; ++j)
1122 printf(" rnd%zu off %jd\n", j,
1123 (intmax_t)packet_dyn[i].rnd[j].off);
1127 void cleanup_packets(void)
1129 size_t i, j;
1131 for (i = 0; i < plen; ++i) {
1132 struct packet *pkt = &packets[i];
1134 if (pkt->len > 0)
1135 xfree(pkt->payload);
1137 for (j = 0; j < pkt->headers_count; j++) {
1138 struct proto_hdr *hdr = pkt->headers[j];
1140 if (hdr->fields)
1141 xfree(hdr->fields);
1142 xfree(hdr);
1146 free(packets);
1148 for (i = 0; i < dlen; ++i) {
1149 free(packet_dyn[i].cnt);
1150 free(packet_dyn[i].rnd);
1151 free(packet_dyn[i].fields);
1154 free(packet_dyn);
1157 void compile_packets(char *file, bool verbose, unsigned int cpu,
1158 bool invoke_cpp, char *const cpp_argv[])
1160 char tmp_file[128];
1161 int ret = -1;
1163 if (access(file, R_OK)) {
1164 fprintf(stderr, "Cannot access %s: %s!\n", file, strerror(errno));
1165 die();
1168 memset(tmp_file, 0, sizeof(tmp_file));
1169 our_cpu = cpu;
1171 if (invoke_cpp) {
1172 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1173 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1174 goto err;
1176 file = tmp_file;
1179 if (!strncmp("-", file, strlen("-")))
1180 yyin = stdin;
1181 else
1182 yyin = fopen(file, "r");
1183 if (!yyin) {
1184 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1185 goto err;
1188 realloc_packet();
1189 if (yyparse() != 0)
1190 goto err;
1191 finalize_packet();
1193 if (our_cpu == 0 && verbose)
1194 dump_conf();
1196 ret = 0;
1197 err:
1198 if (yyin && yyin != stdin)
1199 fclose(yyin);
1201 if (invoke_cpp)
1202 unlink(tmp_file);
1203 if (ret)
1204 die();
1207 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1209 int ret = 1;
1211 our_cpu = cpu;
1212 realloc_packet();
1214 yy_scan_string(str);
1215 if (yyparse() != 0)
1216 goto err;
1218 finalize_packet();
1219 if (our_cpu == 0 && verbose)
1220 dump_conf();
1222 ret = 0;
1223 err:
1224 yylex_destroy();
1226 if (ret)
1227 die();
1230 void yyerror(const char *err)
1232 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);