bpf: Fix confusing panic() message
[netsniff-ng.git] / trafgen_parser.y
blobadd8698fcfd5e148f8691aff6b6b6b5c4e219386
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 #ifndef ETH_P_8021AD
41 #define ETH_P_8021AD 0x88A8
42 #endif
44 #define YYERROR_VERBOSE 0
45 #define YYDEBUG 0
46 #define YYENABLE_NLS 1
47 #define YYLTYPE_IS_TRIVIAL 1
48 #define ENABLE_NLS 1
50 extern FILE *yyin;
51 extern int yylex(void);
52 extern void yy_scan_string(char *);
53 extern void yylex_destroy();
54 extern void yyerror(const char *);
55 extern int yylineno;
56 extern char *yytext;
58 extern struct packet *packets;
59 extern size_t plen;
61 #define packet_last (plen - 1)
63 #define payload_last (packets[packet_last].len - 1)
65 extern struct packet_dyn *packet_dyn;
66 extern size_t dlen;
68 #define packetd_last (dlen - 1)
70 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
71 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
72 #define packetds_last (packet_dyn[packetd_last].slen - 1)
74 static int our_cpu, min_cpu = -1, max_cpu = -1;
76 enum field_expr_type_t {
77 FIELD_EXPR_UNKNOWN,
78 FIELD_EXPR_NUMB,
79 FIELD_EXPR_MAC,
80 FIELD_EXPR_IP4_ADDR,
81 FIELD_EXPR_IP6_ADDR,
82 FIELD_EXPR_INC,
83 FIELD_EXPR_RND,
86 struct proto_field_expr {
87 enum field_expr_type_t type;
88 struct proto_field *field;
90 union {
91 struct in_addr ip4_addr;
92 struct in6_addr ip6_addr;
93 long long int number;
94 uint8_t bytes[256];
95 struct proto_field_func func;
96 } val;
99 static struct proto_field_expr field_expr;
100 static struct proto_hdr *hdr;
102 static inline int test_ignore(void)
104 if (min_cpu < 0 && max_cpu < 0)
105 return 0;
106 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
107 return 0;
108 else
109 return 1;
112 static inline void __init_new_packet_slot(struct packet *slot)
114 slot->payload = NULL;
115 slot->len = 0;
118 static inline void __init_new_counter_slot(struct packet_dyn *slot)
120 memset(slot, 0, sizeof(*slot));
123 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
125 slot->rnd = NULL;
126 slot->rlen = 0;
129 static inline void __init_new_csum_slot(struct packet_dyn *slot)
131 slot->csum = NULL;
132 slot->slen = 0;
135 static inline void __init_new_fields_slot(struct packet_dyn *slot)
137 slot->fields = NULL;
138 slot->flen = 0;
141 static inline void __setup_new_counter(struct counter *c, uint8_t start,
142 uint8_t stop, uint8_t stepping,
143 int type)
145 c->min = start;
146 c->max = stop;
147 c->inc = stepping;
148 c->val = (type == TYPE_INC) ? start : stop;
149 c->off = payload_last;
150 c->type = type;
153 static inline void __setup_new_randomizer(struct randomizer *r)
155 r->off = payload_last;
158 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
159 enum csum which)
161 s->off = payload_last - 1;
162 s->from = from;
163 s->to = to;
164 s->which = which;
167 static void realloc_packet(void)
169 if (test_ignore())
170 return;
172 plen++;
173 packets = xrealloc(packets, plen * sizeof(*packets));
175 __init_new_packet_slot(&packets[packet_last]);
177 dlen++;
178 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
180 __init_new_counter_slot(&packet_dyn[packetd_last]);
181 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
182 __init_new_csum_slot(&packet_dyn[packetd_last]);
183 __init_new_fields_slot(&packet_dyn[packetd_last]);
186 struct packet *current_packet(void)
188 return &packets[packet_last];
191 uint32_t current_packet_id(void)
193 return packet_last;
196 struct packet *packet_get(uint32_t id)
198 return &packets[id];
201 static void set_byte(uint8_t val)
203 struct packet *pkt = &packets[packet_last];
205 if (test_ignore())
206 return;
208 pkt->len++;
209 pkt->payload = xrealloc(pkt->payload, pkt->len);
210 pkt->payload[payload_last] = val;
213 static void set_multi_byte(uint8_t *s, size_t len)
215 size_t i;
217 for (i = 0; i < len; ++i)
218 set_byte(s[i]);
221 void set_fill(uint8_t val, size_t len)
223 size_t i;
224 struct packet *pkt = &packets[packet_last];
226 if (test_ignore())
227 return;
229 pkt->len += len;
230 pkt->payload = xrealloc(pkt->payload, pkt->len);
231 for (i = 0; i < len; ++i)
232 pkt->payload[payload_last - i] = val;
235 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
237 struct packet *pkt = &packets[packet_last];
238 struct packet_dyn *pktd = &packet_dyn[packetd_last];
240 pkt->len += 2;
241 pkt->payload = xrealloc(pkt->payload, pkt->len);
243 pktd->slen++;
244 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
246 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
249 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
251 struct packet *pkt = &packets[packet_last];
252 uint16_t sum;
253 uint8_t *psum;
255 sum = htons(calc_csum(pkt->payload + from, to - from));
256 psum = (uint8_t *) &sum;
258 set_byte(psum[0]);
259 set_byte(psum[1]);
262 static inline bool is_dynamic_csum(enum csum which)
264 switch (which) {
265 case CSUM_UDP:
266 case CSUM_TCP:
267 case CSUM_UDP6:
268 case CSUM_TCP6:
269 return true;
270 default:
271 return false;
275 static void set_csum16(size_t from, size_t to, enum csum which)
277 struct packet *pkt = &packets[packet_last];
278 struct packet_dyn *pktd = &packet_dyn[packetd_last];
280 if (test_ignore())
281 return;
283 if (to < from) {
284 size_t tmp = to;
286 to = from;
287 from = tmp;
290 bug_on(!(from < to));
292 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
293 __set_csum16_dynamic(from, to, which);
294 else
295 __set_csum16_static(from, to, which);
298 static void set_rnd(size_t len)
300 size_t i;
301 struct packet *pkt = &packets[packet_last];
303 if (test_ignore())
304 return;
306 pkt->len += len;
307 pkt->payload = xrealloc(pkt->payload, pkt->len);
308 for (i = 0; i < len; ++i)
309 pkt->payload[payload_last - i] = (uint8_t) rand();
312 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
314 size_t i;
315 struct packet *pkt = &packets[packet_last];
317 if (test_ignore())
318 return;
320 pkt->len += len;
321 pkt->payload = xrealloc(pkt->payload, pkt->len);
322 for (i = 0; i < len; ++i) {
323 off_t off = len - 1 - i;
325 pkt->payload[payload_last - off] = start;
326 start += stepping;
330 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
332 size_t i;
333 struct packet *pkt = &packets[packet_last];
335 if (test_ignore())
336 return;
338 pkt->len += len;
339 pkt->payload = xrealloc(pkt->payload, pkt->len);
340 for (i = 0; i < len; ++i) {
341 int off = len - 1 - i;
343 pkt->payload[payload_last - off] = start;
344 start -= stepping;
348 static void set_dynamic_rnd(void)
350 struct packet *pkt = &packets[packet_last];
351 struct packet_dyn *pktd = &packet_dyn[packetd_last];
353 if (test_ignore())
354 return;
356 pkt->len++;
357 pkt->payload = xrealloc(pkt->payload, pkt->len);
359 pktd->rlen++;
360 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
362 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
365 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
366 int type)
368 struct packet *pkt = &packets[packet_last];
369 struct packet_dyn *pktd = &packet_dyn[packetd_last];
371 if (test_ignore())
372 return;
374 pkt->len++;
375 pkt->payload = xrealloc(pkt->payload, pkt->len);
377 pktd->clen++;
378 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
380 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
383 static void proto_add(enum proto_id pid)
385 hdr = proto_header_push(pid);
388 static void proto_field_set(uint32_t fid)
390 field_expr.field = proto_field_by_id(hdr, fid);
393 static void proto_field_func_setup(struct proto_field *field, struct proto_field_func *func)
395 struct packet_dyn *pkt_dyn;
397 proto_field_func_add(field->hdr, field->id, func);
399 pkt_dyn = &packet_dyn[packetd_last];
400 pkt_dyn->flen++;
401 pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
402 sizeof(struct proto_field *));
403 pkt_dyn->fields[pkt_dyn->flen - 1] = field;
406 static void proto_field_expr_eval(void)
408 struct proto_field *field = field_expr.field;
410 switch (field_expr.type) {
411 case FIELD_EXPR_NUMB:
412 if (field->len == 1)
413 proto_field_set_u8(hdr, field->id, field_expr.val.number);
414 else if (field->len == 2)
415 proto_field_set_be16(hdr, field->id, field_expr.val.number);
416 else if (field->len == 4)
417 proto_field_set_be32(hdr, field->id, field_expr.val.number);
418 else
419 bug();
420 break;
422 case FIELD_EXPR_MAC:
423 proto_field_set_bytes(hdr, field->id, field_expr.val.bytes);
424 break;
426 case FIELD_EXPR_IP4_ADDR:
427 proto_field_set_u32(hdr, field->id, field_expr.val.ip4_addr.s_addr);
428 break;
430 case FIELD_EXPR_IP6_ADDR:
431 proto_field_set_bytes(hdr, field->id,
432 (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
433 break;
435 case FIELD_EXPR_INC:
436 case FIELD_EXPR_RND:
437 if (field_expr.val.func.min
438 && field_expr.val.func.min >= field_expr.val.func.max)
439 panic("dinc(): min(%u) can't be >= max(%u)\n",
440 field_expr.val.func.min, field_expr.val.func.max);
442 proto_field_func_setup(field, &field_expr.val.func);
443 break;
445 case FIELD_EXPR_UNKNOWN:
446 default:
447 bug();
450 memset(&field_expr, 0, sizeof(field_expr));
455 %union {
456 struct in_addr ip4_addr;
457 struct in6_addr ip6_addr;
458 long long int number;
459 uint8_t bytes[256];
460 char *str;
463 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
464 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
466 %token K_DADDR K_SADDR K_ETYPE K_TYPE
467 %token K_TIME K_PRIO
468 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
469 %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
470 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
471 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
472 %token K_SPORT K_DPORT
473 %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
474 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
475 %token K_LABEL K_TC K_LAST K_EXP
477 %token K_ADDR K_MTU
479 %token K_ETH
480 %token K_PAUSE
481 %token K_PFC
482 %token K_VLAN K_MPLS
483 %token K_ARP
484 %token K_IP4 K_IP6
485 %token K_ICMP4 K_ICMP6
486 %token K_UDP K_TCP
488 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
490 %token number string mac ip4_addr ip6_addr
492 %type <number> number expression
493 %type <str> string
494 %type <bytes> mac
495 %type <ip4_addr> ip4_addr
496 %type <ip6_addr> ip6_addr
498 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
502 packets
503 : { }
504 | packets packet { }
505 | packets inline_comment { }
506 | packets K_WHITE { }
509 inline_comment
510 : K_COMMENT { }
513 cpu_delim
514 : ':' { }
515 | '-' { }
518 delimiter_nowhite
519 : ',' { }
520 | ',' K_WHITE { }
523 noenforce_white
524 : { }
525 | K_WHITE { }
526 | delimiter_nowhite { }
529 skip_white
530 : { }
531 | K_WHITE { }
533 packet
534 : '{' noenforce_white payload noenforce_white '}' {
535 min_cpu = max_cpu = -1;
537 proto_packet_finish();
539 realloc_packet();
541 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
542 min_cpu = $3;
543 max_cpu = $5;
545 if (min_cpu > max_cpu) {
546 int tmp = min_cpu;
548 min_cpu = max_cpu;
549 max_cpu = tmp;
552 proto_packet_finish();
554 realloc_packet();
556 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
557 min_cpu = max_cpu = $3;
559 proto_packet_finish();
561 realloc_packet();
565 payload
566 : elem { }
567 | payload elem_delimiter { }
570 delimiter
571 : delimiter_nowhite { }
572 | K_WHITE { }
575 elem_delimiter
576 : delimiter elem { }
579 elem
580 : number { set_byte((uint8_t) $1); }
581 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
582 | fill { }
583 | rnd { }
584 | drnd { }
585 | seqinc { }
586 | seqdec { }
587 | dinc { }
588 | ddec { }
589 | csum { }
590 | const { }
591 | proto { proto_header_finish(hdr); }
592 | inline_comment { }
595 expression
596 : number
597 { $$ = $1; }
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 % $3; }
608 | expression '&' expression
609 { $$ = $1 & $3; }
610 | expression '|' expression
611 { $$ = $1 | $3; }
612 | expression '^' expression
613 { $$ = $1 ^ $3; }
614 | expression '<' '<' expression
615 { $$ = $1 << $4; }
616 | expression '>' '>' expression
617 { $$ = $1 >> $4; }
618 | '-' expression
619 { $$ = -1 * $2; }
620 | '(' expression ')'
621 { $$ = $2;}
624 fill
625 : K_FILL '(' number delimiter number ')'
626 { set_fill($3, $5); }
629 const
630 : K_CONST8 '(' expression ')'
631 { set_byte((uint8_t) $3); }
632 | K_CONST16 '(' expression ')' {
633 uint16_t __c = cpu_to_be16((uint16_t) $3);
635 set_multi_byte((uint8_t *) &__c, sizeof(__c));
637 | K_CONST32 '(' expression ')' {
638 uint32_t __c = cpu_to_be32((uint32_t) $3);
640 set_multi_byte((uint8_t *) &__c, sizeof(__c));
642 | K_CONST64 '(' expression ')' {
643 uint64_t __c = cpu_to_be64((uint64_t) $3);
645 set_multi_byte((uint8_t *) &__c, sizeof(__c));
650 : K_RND '(' number ')'
651 { set_rnd($3); }
654 csum
655 : K_CSUMIP '(' number delimiter number ')'
656 { set_csum16($3, $5, CSUM_IP); }
657 | K_CSUMTCP '(' number delimiter number ')'
658 { set_csum16($3, $5, CSUM_TCP); }
659 | K_CSUMUDP '(' number delimiter number ')'
660 { set_csum16($3, $5, CSUM_UDP); }
661 | K_CSUMTCP6 '(' number delimiter number ')'
662 { set_csum16($3, $5, CSUM_TCP6); }
663 | K_CSUMUDP6 '(' number delimiter number ')'
664 { set_csum16($3, $5, CSUM_UDP6); }
667 seqinc
668 : K_SEQINC '(' number delimiter number ')'
669 { set_sequential_inc($3, $5, 1); }
670 | K_SEQINC '(' number delimiter number delimiter number ')'
671 { set_sequential_inc($3, $5, $7); }
674 seqdec
675 : K_SEQDEC '(' number delimiter number ')'
676 { set_sequential_dec($3, $5, 1); }
677 | K_SEQDEC '(' number delimiter number delimiter number ')'
678 { set_sequential_dec($3, $5, $7); }
681 drnd
682 : K_DRND '(' ')'
683 { set_dynamic_rnd(); }
684 | K_DRND '(' number ')'
686 int i, max = $3;
687 for (i = 0; i < max; ++i)
688 set_dynamic_rnd();
692 dinc
693 : K_DINC '(' number delimiter number ')'
694 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
695 | K_DINC '(' number delimiter number delimiter number ')'
696 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
699 ddec
700 : K_DDEC '(' number delimiter number ')'
701 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
702 | K_DDEC '(' number delimiter number delimiter number ')'
703 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
706 proto
707 : eth_proto { }
708 | pause_proto { }
709 | pfc_proto { }
710 | vlan_proto { }
711 | mpls_proto { }
712 | arp_proto { }
713 | ip4_proto { }
714 | ip6_proto { }
715 | icmp4_proto { }
716 | icmpv6_proto { }
717 | udp_proto { }
718 | tcp_proto { }
721 field_expr
722 : number { field_expr.type = FIELD_EXPR_NUMB;
723 field_expr.val.number = $1; }
724 | mac { field_expr.type = FIELD_EXPR_MAC;
725 memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); }
726 | ip4_addr { field_expr.type = FIELD_EXPR_IP4_ADDR;
727 field_expr.val.ip4_addr = $1; }
728 | ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
729 field_expr.val.ip6_addr = $1; }
730 | K_DINC '(' ')' { field_expr.type = FIELD_EXPR_INC;
731 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
732 field_expr.val.func.inc = 1; }
733 | K_DINC '(' number ')'
734 { field_expr.type = FIELD_EXPR_INC;
735 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
736 field_expr.val.func.inc = $3; }
737 | K_DINC '(' number delimiter number ')'
738 { field_expr.type = FIELD_EXPR_INC;
739 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
740 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
741 field_expr.val.func.min = $3;
742 field_expr.val.func.max = $5;
743 field_expr.val.func.inc = 1; }
744 | K_DINC '(' number delimiter number delimiter number ')'
745 { field_expr.type = FIELD_EXPR_INC;
746 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
747 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
748 field_expr.val.func.min = $3;
749 field_expr.val.func.max = $5;
750 field_expr.val.func.inc = $7; }
751 | K_DRND '(' ')' { field_expr.type = FIELD_EXPR_RND;
752 field_expr.val.func.type = PROTO_FIELD_FUNC_RND; }
753 | K_DRND '(' number delimiter number ')'
754 { field_expr.type = FIELD_EXPR_RND;
755 field_expr.val.func.type = PROTO_FIELD_FUNC_RND;
756 field_expr.val.func.min = $3;
757 field_expr.val.func.max = $5; }
760 eth_proto
761 : eth '(' eth_param_list ')' { }
765 : K_ETH { proto_add(PROTO_ETH); }
768 eth_param_list
769 : { }
770 | eth_expr { }
771 | eth_expr delimiter eth_param_list { }
774 eth_type
775 : K_ETYPE { }
776 | K_TYPE { }
777 | K_PROT { }
780 eth_field
781 : K_DADDR { proto_field_set(ETH_DST_ADDR); }
782 | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
783 | eth_type { proto_field_set(ETH_TYPE); }
785 eth_expr
786 : eth_field skip_white '=' skip_white field_expr
787 { proto_field_expr_eval(); }
790 pause_proto
791 : pause '(' pause_param_list ')' { }
794 pause
795 : K_PAUSE { proto_add(PROTO_PAUSE); }
798 pause_param_list
799 : { }
800 | pause_expr { }
801 | pause_expr delimiter pause_param_list { }
804 pause_field
805 : K_CODE { proto_field_set(PAUSE_OPCODE); }
806 | K_TIME { proto_field_set(PAUSE_TIME); }
809 pause_expr
810 : pause_field skip_white '=' skip_white field_expr
811 { proto_field_expr_eval(); }
814 pfc_proto
815 : pfc '(' pfc_param_list ')' { }
819 : K_PFC { proto_add(PROTO_PFC); }
822 pfc_param_list
823 : { }
824 | pfc_expr { }
825 | pfc_expr delimiter pfc_param_list { }
828 pfc_field
829 : K_CODE { proto_field_set(PFC_OPCODE); }
830 | K_PRIO { proto_field_set(PFC_PRIO); }
831 | K_PRIO '(' number ')'
832 { if ($3 > 7) {
833 yyerror("pfc: Invalid prio(index) parameter");
834 panic("pfc: prio(0)..prio(7) is allowed only\n");
836 proto_field_set(PFC_PRIO_0 + $3); }
837 | K_TIME '(' number ')'
838 { if ($3 > 7) {
839 yyerror("pfc: Invalid time(index) parameter");
840 panic("pfc: time(0)..time(7) is allowed only\n");
842 proto_field_set(PFC_TIME_0 + $3); }
845 pfc_expr
846 : pfc_field skip_white '=' skip_white field_expr
847 { proto_field_expr_eval(); }
850 vlan_proto
851 : vlan '(' vlan_param_list ')' { }
854 vlan
855 : K_VLAN { proto_add(PROTO_VLAN); }
858 vlan_param_list
859 : { }
860 | vlan_expr { }
861 | vlan_expr delimiter vlan_param_list { }
864 vlan_type
865 : K_TPID { }
866 | K_PROT
869 vlan_field
870 : vlan_type { proto_field_set(VLAN_TPID); }
871 | K_TCI { proto_field_set(VLAN_TCI); }
872 | K_PCP { proto_field_set(VLAN_PCP); }
873 | K_DEI { proto_field_set(VLAN_DEI); }
874 | K_ID { proto_field_set(VLAN_VID); }
877 vlan_expr
878 : vlan_field skip_white '=' skip_white field_expr
879 { proto_field_expr_eval(); }
880 | K_1Q
881 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
882 | K_1AD
883 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
886 mpls_proto
887 : mpls '(' mpls_param_list ')' { }
890 mpls
891 : K_MPLS { proto_add(PROTO_MPLS); }
894 mpls_param_list
895 : { }
896 | mpls_expr { }
897 | mpls_expr delimiter mpls_param_list { }
900 mpls_tc
901 : K_TC { }
902 | K_EXP { }
905 mpls_field
906 : K_LABEL { proto_field_set(MPLS_LABEL); }
907 | mpls_tc { proto_field_set(MPLS_TC); }
908 | K_LAST { proto_field_set(MPLS_LAST); }
909 | K_TTL { proto_field_set(MPLS_TTL); }
912 mpls_expr
913 : mpls_field skip_white '=' skip_white field_expr
914 { proto_field_expr_eval(); }
916 arp_proto
917 : arp '(' arp_param_list ')' { }
920 arp_param_list
921 : { }
922 | arp_expr { }
923 | arp_expr delimiter arp_param_list { }
926 arp_field
927 : K_HTYPE
928 { proto_field_set(ARP_HTYPE); }
929 | K_PTYPE
930 { proto_field_set(ARP_PTYPE); }
931 | K_SHA
932 { proto_field_set(ARP_SHA); }
933 | K_THA
934 { proto_field_set(ARP_THA); }
935 | K_SPA
936 { proto_field_set(ARP_SPA); }
937 | K_TPA
938 { proto_field_set(ARP_TPA); }
941 arp_expr
942 : arp_field skip_white '=' skip_white field_expr
943 { proto_field_expr_eval(); }
944 | K_OPER skip_white '=' skip_white field_expr
945 { proto_field_set(ARP_OPER);
946 proto_field_expr_eval(); }
947 | K_OPER skip_white '=' skip_white K_REQUEST
948 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
949 | K_OPER skip_white '=' skip_white K_REPLY
950 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
951 | K_REQUEST
952 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
953 | K_REPLY
954 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
957 : K_ARP { proto_add(PROTO_ARP); }
960 ip4_proto
961 : ip4 '(' ip4_param_list ')' { }
964 ip4_param_list
965 : { }
966 | ip4_expr { }
967 | ip4_expr delimiter ip4_param_list { }
970 ip4_field
971 : K_VER { proto_field_set(IP4_VER); }
972 | K_IHL { proto_field_set(IP4_IHL); }
973 | K_DADDR { proto_field_set(IP4_DADDR); }
974 | K_SADDR { proto_field_set(IP4_SADDR); }
975 | K_PROT { proto_field_set(IP4_PROTO); }
976 | K_TTL { proto_field_set(IP4_TTL); }
977 | K_DSCP { proto_field_set(IP4_DSCP); }
978 | K_ECN { proto_field_set(IP4_ECN); }
979 | K_TOS { proto_field_set(IP4_TOS); }
980 | K_LEN { proto_field_set(IP4_LEN); }
981 | K_ID { proto_field_set(IP4_ID); }
982 | K_FLAGS { proto_field_set(IP4_FLAGS); }
983 | K_FRAG { proto_field_set(IP4_FRAG_OFFS); }
984 | K_CSUM { proto_field_set(IP4_CSUM); }
987 ip4_expr
988 : ip4_field skip_white '=' skip_white field_expr
989 { proto_field_expr_eval(); }
990 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
991 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
995 : K_IP4 { proto_add(PROTO_IP4); }
998 ip6_proto
999 : ip6 '(' ip6_param_list ')' { }
1002 ip6_param_list
1003 : { }
1004 | ip6_expr { }
1005 | ip6_expr delimiter ip6_param_list { }
1008 ip6_hop_limit
1009 : K_HOP_LIMIT { }
1010 | K_TTL { }
1013 ip6_field
1014 : K_VER { proto_field_set(IP6_VER); }
1015 | K_TC { proto_field_set(IP6_CLASS); }
1016 | K_FLOW { proto_field_set(IP6_FLOW_LBL); }
1017 | K_LEN { proto_field_set(IP6_LEN); }
1018 | K_NEXT_HDR { proto_field_set(IP6_NEXT_HDR); }
1019 | ip6_hop_limit { proto_field_set(IP6_HOP_LIMIT); }
1020 | K_SADDR { proto_field_set(IP6_SADDR); }
1021 | K_DADDR { proto_field_set(IP6_DADDR) ; }
1024 ip6_expr
1025 : ip6_field skip_white '=' skip_white field_expr
1026 { proto_field_expr_eval(); }
1030 : K_IP6 { proto_add(PROTO_IP6); }
1033 icmp4_proto
1034 : icmp4 '(' icmp4_param_list ')' { }
1037 icmp4_param_list
1038 : { }
1039 | icmp4_expr { }
1040 | icmp4_expr delimiter icmp4_param_list { }
1043 icmp4_field
1044 : K_TYPE { proto_field_set(ICMPV4_TYPE); }
1045 | K_CODE { proto_field_set(ICMPV4_CODE); }
1046 | K_ID { proto_field_set(ICMPV4_ID); }
1047 | K_SEQ { proto_field_set(ICMPV4_SEQ); }
1048 | K_MTU { proto_field_set(ICMPV4_MTU); }
1049 | K_ADDR { proto_field_set(ICMPV4_REDIR_ADDR); }
1052 icmp4_expr
1053 : icmp4_field skip_white '=' skip_white field_expr
1054 { proto_field_expr_eval(); }
1055 | K_ECHO_REQUEST
1056 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
1057 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
1058 | K_ECHO_REPLY
1059 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
1060 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
1063 icmp4
1064 : K_ICMP4 { proto_add(PROTO_ICMP4); }
1067 icmpv6_proto
1068 : icmp6 '(' icmp6_param_list ')' { }
1070 icmp6_param_list
1071 : { }
1072 | icmp6_expr { }
1073 | icmp6_expr delimiter icmp6_param_list { }
1076 icmp6_field
1077 : K_CODE { proto_field_set(ICMPV6_CODE); }
1078 | K_CSUM { proto_field_set(ICMPV6_CSUM); }
1081 icmp6_expr
1082 : icmp6_field skip_white '=' skip_white field_expr
1083 { proto_field_expr_eval(); }
1084 | K_TYPE skip_white '=' skip_white field_expr
1085 { proto_field_set(ICMPV6_TYPE);
1086 proto_field_expr_eval(); }
1087 | K_TYPE skip_white '=' K_ECHO_REQUEST
1088 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1089 | K_ECHO_REQUEST
1090 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1091 | K_TYPE skip_white '=' K_ECHO_REPLY
1092 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1093 | K_ECHO_REPLY
1094 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1096 icmp6
1097 : K_ICMP6 { proto_add(PROTO_ICMP6); }
1100 udp_proto
1101 : udp '(' udp_param_list ')' { }
1104 udp_param_list
1105 : { }
1106 | udp_expr { }
1107 | udp_expr delimiter udp_param_list { }
1110 udp_field
1111 : K_SPORT { proto_field_set(UDP_SPORT); }
1112 | K_DPORT { proto_field_set(UDP_DPORT); }
1113 | K_LEN { proto_field_set(UDP_LEN); }
1114 | K_CSUM { proto_field_set(UDP_CSUM); }
1117 udp_expr
1118 : udp_field skip_white '=' skip_white field_expr
1119 { proto_field_expr_eval(); }
1123 : K_UDP { proto_add(PROTO_UDP); }
1126 tcp_proto
1127 : tcp '(' tcp_param_list ')' { }
1130 tcp_param_list
1131 : { }
1132 | tcp_expr { }
1133 | tcp_expr delimiter tcp_param_list { }
1136 tcp_field
1137 : K_SPORT { proto_field_set(TCP_SPORT); }
1138 | K_DPORT { proto_field_set(TCP_DPORT); }
1139 | K_SEQ { proto_field_set(TCP_SEQ); }
1140 | K_ACK_SEQ { proto_field_set(TCP_ACK_SEQ); }
1141 | K_DOFF { proto_field_set(TCP_DOFF); }
1142 | K_WINDOW { proto_field_set(TCP_WINDOW); }
1143 | K_CSUM { proto_field_set(TCP_CSUM); }
1144 | K_URG_PTR { proto_field_set(TCP_URG_PTR); }
1147 tcp_expr
1148 : tcp_field skip_white '=' skip_white field_expr
1149 { proto_field_expr_eval(); }
1150 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
1151 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
1152 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
1153 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
1154 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
1155 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
1156 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
1157 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
1161 : K_TCP { proto_add(PROTO_TCP); }
1166 static void finalize_packet(void)
1168 /* XXX hack ... we allocated one packet pointer too much */
1169 plen--;
1170 dlen--;
1173 static void dump_conf(void)
1175 size_t i, j;
1177 for (i = 0; i < plen; ++i) {
1178 printf("[%zu] pkt\n", i);
1179 printf(" len %zu cnts %zu rnds %zu\n",
1180 packets[i].len,
1181 packet_dyn[i].clen,
1182 packet_dyn[i].rlen);
1184 printf(" payload ");
1185 for (j = 0; j < packets[i].len; ++j)
1186 printf("%02x ", packets[i].payload[j]);
1187 printf("\n");
1189 for (j = 0; j < packet_dyn[i].clen; ++j)
1190 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
1191 packet_dyn[i].cnt[j].min,
1192 packet_dyn[i].cnt[j].max,
1193 packet_dyn[i].cnt[j].inc,
1194 (intmax_t)packet_dyn[i].cnt[j].off,
1195 packet_dyn[i].cnt[j].type == TYPE_INC ?
1196 "inc" : "dec");
1198 for (j = 0; j < packet_dyn[i].rlen; ++j)
1199 printf(" rnd%zu off %jd\n", j,
1200 (intmax_t)packet_dyn[i].rnd[j].off);
1204 void cleanup_packets(void)
1206 size_t i, j;
1208 for (i = 0; i < plen; ++i) {
1209 struct packet *pkt = &packets[i];
1211 if (pkt->len > 0)
1212 xfree(pkt->payload);
1214 for (j = 0; j < pkt->headers_count; j++) {
1215 struct proto_hdr *hdr = pkt->headers[j];
1217 if (hdr->fields)
1218 xfree(hdr->fields);
1219 xfree(hdr);
1223 free(packets);
1225 for (i = 0; i < dlen; ++i) {
1226 free(packet_dyn[i].cnt);
1227 free(packet_dyn[i].rnd);
1228 free(packet_dyn[i].fields);
1231 free(packet_dyn);
1234 void compile_packets(char *file, bool verbose, unsigned int cpu,
1235 bool invoke_cpp, char *const cpp_argv[])
1237 char tmp_file[128];
1238 int ret = -1;
1240 if (access(file, R_OK)) {
1241 fprintf(stderr, "Cannot access %s: %s!\n", file, strerror(errno));
1242 die();
1245 memset(tmp_file, 0, sizeof(tmp_file));
1246 our_cpu = cpu;
1248 if (invoke_cpp) {
1249 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1250 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1251 goto err;
1253 file = tmp_file;
1256 if (!strncmp("-", file, strlen("-")))
1257 yyin = stdin;
1258 else
1259 yyin = fopen(file, "r");
1260 if (!yyin) {
1261 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1262 goto err;
1265 realloc_packet();
1266 if (yyparse() != 0)
1267 goto err;
1268 finalize_packet();
1270 if (our_cpu == 0 && verbose)
1271 dump_conf();
1273 ret = 0;
1274 err:
1275 if (yyin && yyin != stdin)
1276 fclose(yyin);
1278 if (invoke_cpp)
1279 unlink(tmp_file);
1280 if (ret)
1281 die();
1284 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1286 int ret = 1;
1288 our_cpu = cpu;
1289 realloc_packet();
1291 yy_scan_string(str);
1292 if (yyparse() != 0)
1293 goto err;
1295 finalize_packet();
1296 if (our_cpu == 0 && verbose)
1297 dump_conf();
1299 ret = 0;
1300 err:
1301 yylex_destroy();
1303 if (ret)
1304 die();
1307 void yyerror(const char *err)
1309 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);