netsniff-ng: remove unnecessary zeroing of packet counters in init_ctx()
[netsniff-ng.git] / trafgen_parser.y
blob5281bf64a4f11cc080274646f7b894418c92541d
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 /* yacc-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 = 0,
78 FIELD_EXPR_NUMB = 1 << 0,
79 FIELD_EXPR_MAC = 1 << 1,
80 FIELD_EXPR_IP4_ADDR = 1 << 2,
81 FIELD_EXPR_IP6_ADDR = 1 << 3,
82 FIELD_EXPR_INC = 1 << 4,
83 FIELD_EXPR_RND = 1 << 5,
84 FIELD_EXPR_OFFSET = 1 << 6,
87 struct proto_field_expr {
88 enum field_expr_type_t type;
89 struct proto_field *field;
91 union {
92 struct in_addr ip4_addr;
93 struct in6_addr ip6_addr;
94 long long int number;
95 uint8_t mac[256];
96 struct proto_field_func func;
97 } val;
100 static struct proto_field_expr field_expr;
101 static struct proto_hdr *hdr;
103 static inline int test_ignore(void)
105 if (min_cpu < 0 && max_cpu < 0)
106 return 0;
107 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
108 return 0;
109 else
110 return 1;
113 static inline void __init_new_packet_slot(struct packet *slot)
115 memset(slot, 0, sizeof(*slot));
118 static inline void __init_new_counter_slot(struct packet_dyn *slot)
120 slot->cnt = NULL;
121 slot->clen = 0;
124 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
126 slot->rnd = NULL;
127 slot->rlen = 0;
130 static inline void __init_new_csum_slot(struct packet_dyn *slot)
132 slot->csum = NULL;
133 slot->slen = 0;
136 static inline void __init_new_fields_slot(struct packet_dyn *slot)
138 slot->fields = NULL;
139 slot->flen = 0;
142 static inline void __setup_new_counter(struct counter *c, uint8_t start,
143 uint8_t stop, uint8_t stepping,
144 int type)
146 c->min = start;
147 c->max = stop;
148 c->inc = stepping;
149 c->val = (type == TYPE_INC) ? start : stop;
150 c->off = payload_last;
151 c->type = type;
154 static inline void __setup_new_randomizer(struct randomizer *r)
156 r->off = payload_last;
159 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
160 enum csum which)
162 s->off = payload_last - 1;
163 s->from = from;
164 s->to = to;
165 s->which = which;
168 void realloc_packet(void)
170 if (test_ignore())
171 return;
173 plen++;
174 packets = xrealloc(packets, plen * sizeof(*packets));
176 __init_new_packet_slot(&packets[packet_last]);
178 dlen++;
179 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
181 __init_new_counter_slot(&packet_dyn[packetd_last]);
182 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
183 __init_new_csum_slot(&packet_dyn[packetd_last]);
184 __init_new_fields_slot(&packet_dyn[packetd_last]);
187 struct packet *current_packet(void)
189 return &packets[packet_last];
192 uint32_t current_packet_id(void)
194 return packet_last;
197 struct packet *packet_get(uint32_t id)
199 return &packets[id];
202 static void set_byte(uint8_t val)
204 struct packet *pkt = &packets[packet_last];
206 if (test_ignore())
207 return;
209 pkt->len++;
210 pkt->payload = xrealloc(pkt->payload, pkt->len);
211 pkt->payload[payload_last] = val;
214 static void set_multi_byte(uint8_t *s, size_t len)
216 size_t i;
218 for (i = 0; i < len; ++i)
219 set_byte(s[i]);
222 void set_fill(uint8_t val, size_t len)
224 size_t i;
225 struct packet *pkt = &packets[packet_last];
227 if (test_ignore())
228 return;
230 pkt->len += len;
231 pkt->payload = xrealloc(pkt->payload, pkt->len);
232 for (i = 0; i < len; ++i)
233 pkt->payload[payload_last - i] = val;
236 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
238 struct packet *pkt = &packets[packet_last];
239 struct packet_dyn *pktd = &packet_dyn[packetd_last];
241 pkt->len += 2;
242 pkt->payload = xrealloc(pkt->payload, pkt->len);
244 pktd->slen++;
245 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
247 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
250 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
252 struct packet *pkt = &packets[packet_last];
253 uint16_t sum;
254 uint8_t *psum;
256 sum = htons(calc_csum(pkt->payload + from, to - from));
257 psum = (uint8_t *) &sum;
259 set_byte(psum[0]);
260 set_byte(psum[1]);
263 static inline bool is_dynamic_csum(enum csum which)
265 switch (which) {
266 case CSUM_UDP:
267 case CSUM_TCP:
268 case CSUM_UDP6:
269 case CSUM_TCP6:
270 return true;
271 default:
272 return false;
276 static void set_csum16(size_t from, size_t to, enum csum which)
278 struct packet *pkt = &packets[packet_last];
279 struct packet_dyn *pktd = &packet_dyn[packetd_last];
281 if (test_ignore())
282 return;
284 if (to < from) {
285 size_t tmp = to;
287 to = from;
288 from = tmp;
291 bug_on(!(from < to));
293 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
294 __set_csum16_dynamic(from, to, which);
295 else
296 __set_csum16_static(from, to, which);
299 static void set_rnd(size_t len)
301 size_t i;
302 struct packet *pkt = &packets[packet_last];
304 if (test_ignore())
305 return;
307 pkt->len += len;
308 pkt->payload = xrealloc(pkt->payload, pkt->len);
309 for (i = 0; i < len; ++i)
310 pkt->payload[payload_last - i] = (uint8_t) rand();
313 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
315 size_t i;
316 struct packet *pkt = &packets[packet_last];
318 if (test_ignore())
319 return;
321 pkt->len += len;
322 pkt->payload = xrealloc(pkt->payload, pkt->len);
323 for (i = 0; i < len; ++i) {
324 off_t off = len - 1 - i;
326 pkt->payload[payload_last - off] = start;
327 start += stepping;
331 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
333 size_t i;
334 struct packet *pkt = &packets[packet_last];
336 if (test_ignore())
337 return;
339 pkt->len += len;
340 pkt->payload = xrealloc(pkt->payload, pkt->len);
341 for (i = 0; i < len; ++i) {
342 int off = len - 1 - i;
344 pkt->payload[payload_last - off] = start;
345 start -= stepping;
349 static void set_dynamic_rnd(void)
351 struct packet *pkt = &packets[packet_last];
352 struct packet_dyn *pktd = &packet_dyn[packetd_last];
354 if (test_ignore())
355 return;
357 pkt->len++;
358 pkt->payload = xrealloc(pkt->payload, pkt->len);
360 pktd->rlen++;
361 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
363 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
366 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
367 int type)
369 struct packet *pkt = &packets[packet_last];
370 struct packet_dyn *pktd = &packet_dyn[packetd_last];
372 if (test_ignore())
373 return;
375 pkt->len++;
376 pkt->payload = xrealloc(pkt->payload, pkt->len);
378 pktd->clen++;
379 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
381 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
384 static void proto_add(enum proto_id pid)
386 hdr = proto_header_push(pid);
389 static void proto_field_set(uint32_t fid)
391 memset(&field_expr, 0, sizeof(field_expr));
392 field_expr.field = proto_hdr_field_by_id(hdr, fid);
395 static void proto_field_func_setup(struct proto_field *field, struct proto_field_func *func)
397 struct proto_field *field_copy;
398 struct packet_dyn *pkt_dyn;
400 field_copy = xmalloc(sizeof(*field));
401 memcpy(field_copy, field, sizeof(*field));
403 field_copy->pkt_offset += func->offset;
404 if (func->len)
405 field_copy->len = func->len;
407 proto_field_func_add(field_copy, func);
409 pkt_dyn = &packet_dyn[packetd_last];
410 pkt_dyn->flen++;
411 pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
412 sizeof(struct proto_field *));
414 pkt_dyn->fields[pkt_dyn->flen - 1] = field_copy;
417 static void proto_field_expr_eval(void)
419 struct proto_field *field = field_expr.field;
421 if ((field_expr.type & FIELD_EXPR_OFFSET) &&
422 !((field_expr.type & FIELD_EXPR_INC) ||
423 (field_expr.type & FIELD_EXPR_RND))) {
425 panic("Field offset expression is valid only with function expression\n");
428 if (field_expr.type & FIELD_EXPR_NUMB) {
429 if (field->len == 1)
430 proto_hdr_field_set_u8(hdr, field->id, field_expr.val.number);
431 else if (field->len == 2)
432 proto_hdr_field_set_be16(hdr, field->id, field_expr.val.number);
433 else if (field->len == 4)
434 proto_hdr_field_set_be32(hdr, field->id, field_expr.val.number);
435 else
436 panic("Invalid value length %zu, can be 1,2 or 4\n", field->len);
437 } else if (field_expr.type & FIELD_EXPR_MAC) {
438 proto_hdr_field_set_bytes(hdr, field->id, field_expr.val.mac);
439 } else if (field_expr.type & FIELD_EXPR_IP4_ADDR) {
440 proto_hdr_field_set_u32(hdr, field->id, field_expr.val.ip4_addr.s_addr);
441 } else if (field_expr.type & FIELD_EXPR_IP6_ADDR) {
442 proto_hdr_field_set_bytes(hdr, field->id,
443 (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
444 } else if ((field_expr.type & FIELD_EXPR_INC) ||
445 (field_expr.type & FIELD_EXPR_RND)) {
447 if (field_expr.val.func.min
448 && field_expr.val.func.min >= field_expr.val.func.max)
449 panic("dinc(): min(%u) can't be >= max(%u)\n",
450 field_expr.val.func.min, field_expr.val.func.max);
452 proto_field_func_setup(field, &field_expr.val.func);
453 } else if ((field_expr.type & FIELD_EXPR_OFFSET) &&
454 !((field_expr.type & FIELD_EXPR_INC) ||
455 (field_expr.type & FIELD_EXPR_RND))) {
457 panic("Field expression is valid only for function value expression\n");
458 } else {
459 bug();
462 memset(&field_expr, 0, sizeof(field_expr));
465 static void field_index_validate(struct proto_field *field, uint16_t index, size_t len)
467 if (field_expr.field->len <= index) {
468 yyerror("Invalid [index] parameter");
469 panic("Index (%u) is bigger than field's length (%zu)\n",
470 index, field->len);
472 if (len != 1 && len != 2 && len != 4) {
473 yyerror("Invalid [index:len] parameter");
474 panic("Invalid index length - 1,2 or 4 is only allowed\n");
480 %union {
481 struct in_addr ip4_addr;
482 struct in6_addr ip6_addr;
483 long long int number;
484 uint8_t mac[6];
485 char *str;
488 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
489 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
491 %token K_DADDR K_SADDR K_ETYPE K_TYPE
492 %token K_TIME K_PRIO
493 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
494 %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
495 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
496 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
497 %token K_SPORT K_DPORT
498 %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
499 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
500 %token K_LABEL K_TC K_LAST K_EXP
502 %token K_ADDR K_MTU
504 %token K_ETH
505 %token K_PAUSE
506 %token K_PFC
507 %token K_VLAN K_MPLS
508 %token K_ARP
509 %token K_IP4 K_IP6
510 %token K_ICMP4 K_ICMP6
511 %token K_UDP K_TCP
513 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
515 %token number string mac ip4_addr ip6_addr
517 %type <number> number expression
518 %type <str> string
519 %type <mac> mac
520 %type <ip4_addr> ip4_addr
521 %type <ip6_addr> ip6_addr
523 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
527 packets
528 : { }
529 | packets packet { }
530 | packets inline_comment { }
531 | packets K_WHITE { }
534 inline_comment
535 : K_COMMENT { }
538 cpu_delim
539 : ':' { }
540 | '-' { }
543 delimiter_nowhite
544 : ',' { }
545 | ',' K_WHITE { }
548 noenforce_white
549 : { }
550 | K_WHITE { }
551 | delimiter_nowhite { }
554 skip_white
555 : { }
556 | K_WHITE { }
558 packet
559 : '{' noenforce_white payload noenforce_white '}' {
560 min_cpu = max_cpu = -1;
562 proto_packet_finish();
564 realloc_packet();
566 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
567 min_cpu = $3;
568 max_cpu = $5;
570 if (min_cpu > max_cpu) {
571 int tmp = min_cpu;
573 min_cpu = max_cpu;
574 max_cpu = tmp;
577 proto_packet_finish();
579 realloc_packet();
581 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
582 min_cpu = max_cpu = $3;
584 proto_packet_finish();
586 realloc_packet();
590 payload
591 : elem { }
592 | payload elem_delimiter { }
595 delimiter
596 : delimiter_nowhite { }
597 | K_WHITE { }
600 elem_delimiter
601 : delimiter elem { }
604 elem
605 : number { set_byte((uint8_t) $1); }
606 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
607 | fill { }
608 | rnd { }
609 | drnd { }
610 | seqinc { }
611 | seqdec { }
612 | dinc { }
613 | ddec { }
614 | csum { }
615 | const { }
616 | proto { proto_header_finish(hdr); }
617 | inline_comment { }
620 expression
621 : number
622 { $$ = $1; }
623 | expression '+' expression
624 { $$ = $1 + $3; }
625 | expression '-' expression
626 { $$ = $1 - $3; }
627 | expression '*' expression
628 { $$ = $1 * $3; }
629 | expression '/' expression
630 { $$ = $1 / $3; }
631 | expression '%' expression
632 { $$ = $1 % $3; }
633 | expression '&' expression
634 { $$ = $1 & $3; }
635 | expression '|' expression
636 { $$ = $1 | $3; }
637 | expression '^' expression
638 { $$ = $1 ^ $3; }
639 | expression '<' '<' expression
640 { $$ = $1 << $4; }
641 | expression '>' '>' expression
642 { $$ = $1 >> $4; }
643 | '-' expression
644 { $$ = -1 * $2; }
645 | '(' expression ')'
646 { $$ = $2;}
649 fill
650 : K_FILL '(' number delimiter number ')'
651 { set_fill($3, $5); }
654 const
655 : K_CONST8 '(' expression ')'
656 { set_byte((uint8_t) $3); }
657 | K_CONST16 '(' expression ')' {
658 uint16_t __c = cpu_to_be16((uint16_t) $3);
660 set_multi_byte((uint8_t *) &__c, sizeof(__c));
662 | K_CONST32 '(' expression ')' {
663 uint32_t __c = cpu_to_be32((uint32_t) $3);
665 set_multi_byte((uint8_t *) &__c, sizeof(__c));
667 | K_CONST64 '(' expression ')' {
668 uint64_t __c = cpu_to_be64((uint64_t) $3);
670 set_multi_byte((uint8_t *) &__c, sizeof(__c));
675 : K_RND '(' number ')'
676 { set_rnd($3); }
679 csum
680 : K_CSUMIP '(' number delimiter number ')'
681 { set_csum16($3, $5, CSUM_IP); }
682 | K_CSUMTCP '(' number delimiter number ')'
683 { set_csum16($3, $5, CSUM_TCP); }
684 | K_CSUMUDP '(' number delimiter number ')'
685 { set_csum16($3, $5, CSUM_UDP); }
686 | K_CSUMTCP6 '(' number delimiter number ')'
687 { set_csum16($3, $5, CSUM_TCP6); }
688 | K_CSUMUDP6 '(' number delimiter number ')'
689 { set_csum16($3, $5, CSUM_UDP6); }
692 seqinc
693 : K_SEQINC '(' number delimiter number ')'
694 { set_sequential_inc($3, $5, 1); }
695 | K_SEQINC '(' number delimiter number delimiter number ')'
696 { set_sequential_inc($3, $5, $7); }
699 seqdec
700 : K_SEQDEC '(' number delimiter number ')'
701 { set_sequential_dec($3, $5, 1); }
702 | K_SEQDEC '(' number delimiter number delimiter number ')'
703 { set_sequential_dec($3, $5, $7); }
706 drnd
707 : K_DRND '(' ')'
708 { set_dynamic_rnd(); }
709 | K_DRND '(' number ')'
711 int i, max = $3;
712 for (i = 0; i < max; ++i)
713 set_dynamic_rnd();
717 dinc
718 : K_DINC '(' number delimiter number ')'
719 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
720 | K_DINC '(' number delimiter number delimiter number ')'
721 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
724 ddec
725 : K_DDEC '(' number delimiter number ')'
726 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
727 | K_DDEC '(' number delimiter number delimiter number ')'
728 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
731 proto
732 : eth_proto { }
733 | pause_proto { }
734 | pfc_proto { }
735 | vlan_proto { }
736 | mpls_proto { }
737 | arp_proto { }
738 | ip4_proto { }
739 | ip6_proto { }
740 | icmp4_proto { }
741 | icmpv6_proto { }
742 | udp_proto { }
743 | tcp_proto { }
746 field_expr
747 : '[' skip_white number skip_white ']'
748 { field_index_validate(field_expr.field, $3, 1);
749 field_expr.type |= FIELD_EXPR_OFFSET;
750 field_expr.val.func.offset = $3;
751 field_expr.val.func.len = 1; }
752 | '[' skip_white number skip_white ':' skip_white number skip_white ']'
753 { field_index_validate(field_expr.field, $3, $7);
754 field_expr.type |= FIELD_EXPR_OFFSET;
755 field_expr.val.func.offset = $3;
756 field_expr.val.func.len = $7; }
759 field_value_expr
760 : number { field_expr.type |= FIELD_EXPR_NUMB;
761 field_expr.val.number = $1; }
762 | mac { field_expr.type |= FIELD_EXPR_MAC;
763 memcpy(field_expr.val.mac, $1, sizeof(field_expr.val.mac)); }
764 | ip4_addr { field_expr.type |= FIELD_EXPR_IP4_ADDR;
765 field_expr.val.ip4_addr = $1; }
766 | ip6_addr { field_expr.type |= FIELD_EXPR_IP6_ADDR;
767 field_expr.val.ip6_addr = $1; }
768 | K_DINC '(' ')' { field_expr.type |= FIELD_EXPR_INC;
769 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
770 field_expr.val.func.inc = 1; }
771 | K_DINC '(' number ')'
772 { field_expr.type |= FIELD_EXPR_INC;
773 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
774 field_expr.val.func.inc = $3; }
775 | K_DINC '(' number delimiter number ')'
776 { field_expr.type |= FIELD_EXPR_INC;
777 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
778 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
779 field_expr.val.func.min = $3;
780 field_expr.val.func.max = $5;
781 field_expr.val.func.inc = 1; }
782 | K_DINC '(' number delimiter number delimiter number ')'
783 { field_expr.type |= FIELD_EXPR_INC;
784 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
785 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
786 field_expr.val.func.min = $3;
787 field_expr.val.func.max = $5;
788 field_expr.val.func.inc = $7; }
789 | K_DRND '(' ')' { field_expr.type |= FIELD_EXPR_RND;
790 field_expr.val.func.type = PROTO_FIELD_FUNC_RND; }
791 | K_DRND '(' number delimiter number ')'
792 { field_expr.type |= FIELD_EXPR_RND;
793 field_expr.val.func.type = PROTO_FIELD_FUNC_RND;
794 field_expr.val.func.min = $3;
795 field_expr.val.func.max = $5; }
798 eth_proto
799 : eth '(' eth_param_list ')' { }
803 : K_ETH { proto_add(PROTO_ETH); }
806 eth_param_list
807 : { }
808 | eth_expr { }
809 | eth_expr delimiter eth_param_list { }
812 eth_type
813 : K_ETYPE { }
814 | K_TYPE { }
815 | K_PROT { }
818 eth_field
819 : K_DADDR { proto_field_set(ETH_DST_ADDR); }
820 | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
821 | eth_type { proto_field_set(ETH_TYPE); }
823 eth_expr
824 : eth_field field_expr skip_white '=' skip_white field_value_expr
825 { proto_field_expr_eval(); }
826 | eth_field skip_white '=' skip_white field_value_expr
827 { proto_field_expr_eval(); }
830 pause_proto
831 : pause '(' pause_param_list ')' { }
834 pause
835 : K_PAUSE { proto_add(PROTO_PAUSE); }
838 pause_param_list
839 : { }
840 | pause_expr { }
841 | pause_expr delimiter pause_param_list { }
844 pause_field
845 : K_CODE { proto_field_set(PAUSE_OPCODE); }
846 | K_TIME { proto_field_set(PAUSE_TIME); }
849 pause_expr
850 : pause_field field_expr skip_white '=' skip_white field_value_expr
851 { proto_field_expr_eval(); }
852 | pause_field skip_white '=' skip_white field_value_expr
853 { proto_field_expr_eval(); }
856 pfc_proto
857 : pfc '(' pfc_param_list ')' { }
861 : K_PFC { proto_add(PROTO_PFC); }
864 pfc_param_list
865 : { }
866 | pfc_expr { }
867 | pfc_expr delimiter pfc_param_list { }
870 pfc_field
871 : K_CODE { proto_field_set(PFC_OPCODE); }
872 | K_PRIO { proto_field_set(PFC_PRIO); }
873 | K_PRIO '(' number ')'
874 { if ($3 > 7) {
875 yyerror("pfc: Invalid prio(index) parameter");
876 panic("pfc: prio(0)..prio(7) is allowed only\n");
878 proto_field_set(PFC_PRIO_0 + $3); }
879 | K_TIME '(' number ')'
880 { if ($3 > 7) {
881 yyerror("pfc: Invalid time(index) parameter");
882 panic("pfc: time(0)..time(7) is allowed only\n");
884 proto_field_set(PFC_TIME_0 + $3); }
887 pfc_expr
888 : pfc_field field_expr skip_white '=' skip_white field_value_expr
889 { proto_field_expr_eval(); }
890 | pfc_field skip_white '=' skip_white field_value_expr
891 { proto_field_expr_eval(); }
894 vlan_proto
895 : vlan '(' vlan_param_list ')' { }
898 vlan
899 : K_VLAN { proto_add(PROTO_VLAN); }
902 vlan_param_list
903 : { }
904 | vlan_expr { }
905 | vlan_expr delimiter vlan_param_list { }
908 vlan_type
909 : K_TPID { }
910 | K_PROT
913 vlan_field
914 : vlan_type { proto_field_set(VLAN_TPID); }
915 | K_TCI { proto_field_set(VLAN_TCI); }
916 | K_PCP { proto_field_set(VLAN_PCP); }
917 | K_DEI { proto_field_set(VLAN_DEI); }
918 | K_ID { proto_field_set(VLAN_VID); }
921 vlan_expr
922 : vlan_field field_expr skip_white '=' skip_white field_value_expr
923 { proto_field_expr_eval(); }
924 | vlan_field skip_white '=' skip_white field_value_expr
925 { proto_field_expr_eval(); }
926 | K_1Q
927 { proto_hdr_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
928 | K_1AD
929 { proto_hdr_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
932 mpls_proto
933 : mpls '(' mpls_param_list ')' { }
936 mpls
937 : K_MPLS { proto_add(PROTO_MPLS); }
940 mpls_param_list
941 : { }
942 | mpls_expr { }
943 | mpls_expr delimiter mpls_param_list { }
946 mpls_tc
947 : K_TC { }
948 | K_EXP { }
951 mpls_field
952 : K_LABEL { proto_field_set(MPLS_LABEL); }
953 | mpls_tc { proto_field_set(MPLS_TC); }
954 | K_LAST { proto_field_set(MPLS_LAST); }
955 | K_TTL { proto_field_set(MPLS_TTL); }
958 mpls_expr
959 : mpls_field field_expr skip_white '=' skip_white field_value_expr
960 { proto_field_expr_eval(); }
961 | mpls_field skip_white '=' skip_white field_value_expr
962 { proto_field_expr_eval(); }
965 arp_proto
966 : arp '(' arp_param_list ')' { }
969 arp_param_list
970 : { }
971 | arp_expr { }
972 | arp_expr delimiter arp_param_list { }
975 arp_field
976 : K_HTYPE
977 { proto_field_set(ARP_HTYPE); }
978 | K_PTYPE
979 { proto_field_set(ARP_PTYPE); }
980 | K_SHA
981 { proto_field_set(ARP_SHA); }
982 | K_THA
983 { proto_field_set(ARP_THA); }
984 | K_SPA
985 { proto_field_set(ARP_SPA); }
986 | K_TPA
987 { proto_field_set(ARP_TPA); }
990 arp_expr
991 : arp_field field_expr skip_white '=' skip_white field_value_expr
992 { proto_field_expr_eval(); }
993 | arp_field skip_white '=' skip_white field_value_expr
994 { proto_field_expr_eval(); }
995 | K_OPER field_expr skip_white '=' skip_white field_value_expr
996 { proto_field_set(ARP_OPER);
997 proto_field_expr_eval(); }
998 | K_OPER skip_white '=' skip_white field_value_expr
999 { proto_field_set(ARP_OPER);
1000 proto_field_expr_eval(); }
1001 | K_OPER skip_white '=' skip_white K_REQUEST
1002 { proto_hdr_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
1003 | K_OPER skip_white '=' skip_white K_REPLY
1004 { proto_hdr_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
1005 | K_REQUEST
1006 { proto_hdr_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
1007 | K_REPLY
1008 { proto_hdr_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
1012 : K_ARP { proto_add(PROTO_ARP); }
1015 ip4_proto
1016 : ip4 '(' ip4_param_list ')' { }
1019 ip4_param_list
1020 : { }
1021 | ip4_expr { }
1022 | ip4_expr delimiter ip4_param_list { }
1025 ip4_field
1026 : K_VER { proto_field_set(IP4_VER); }
1027 | K_IHL { proto_field_set(IP4_IHL); }
1028 | K_DADDR { proto_field_set(IP4_DADDR); }
1029 | K_SADDR { proto_field_set(IP4_SADDR); }
1030 | K_PROT { proto_field_set(IP4_PROTO); }
1031 | K_TTL { proto_field_set(IP4_TTL); }
1032 | K_DSCP { proto_field_set(IP4_DSCP); }
1033 | K_ECN { proto_field_set(IP4_ECN); }
1034 | K_TOS { proto_field_set(IP4_TOS); }
1035 | K_LEN { proto_field_set(IP4_LEN); }
1036 | K_ID { proto_field_set(IP4_ID); }
1037 | K_FLAGS { proto_field_set(IP4_FLAGS); }
1038 | K_FRAG { proto_field_set(IP4_FRAG_OFFS); }
1039 | K_CSUM { proto_field_set(IP4_CSUM); }
1042 ip4_expr
1043 : ip4_field field_expr skip_white '=' skip_white field_value_expr
1044 { proto_field_expr_eval(); }
1045 | ip4_field skip_white '=' skip_white field_value_expr
1046 { proto_field_expr_eval(); }
1047 | K_DF { proto_hdr_field_set_be16(hdr, IP4_DF, 1); }
1048 | K_MF { proto_hdr_field_set_be16(hdr, IP4_MF, 1); }
1052 : K_IP4 { proto_add(PROTO_IP4); }
1055 ip6_proto
1056 : ip6 '(' ip6_param_list ')' { }
1059 ip6_param_list
1060 : { }
1061 | ip6_expr { }
1062 | ip6_expr delimiter ip6_param_list { }
1065 ip6_hop_limit
1066 : K_HOP_LIMIT { }
1067 | K_TTL { }
1070 ip6_field
1071 : K_VER { proto_field_set(IP6_VER); }
1072 | K_TC { proto_field_set(IP6_CLASS); }
1073 | K_FLOW { proto_field_set(IP6_FLOW_LBL); }
1074 | K_LEN { proto_field_set(IP6_LEN); }
1075 | K_NEXT_HDR { proto_field_set(IP6_NEXT_HDR); }
1076 | ip6_hop_limit { proto_field_set(IP6_HOP_LIMIT); }
1077 | K_SADDR { proto_field_set(IP6_SADDR); }
1078 | K_DADDR { proto_field_set(IP6_DADDR) ; }
1081 ip6_expr
1082 : ip6_field field_expr skip_white '=' skip_white field_value_expr
1083 { proto_field_expr_eval(); }
1084 | ip6_field skip_white '=' skip_white field_value_expr
1085 { proto_field_expr_eval(); }
1089 : K_IP6 { proto_add(PROTO_IP6); }
1092 icmp4_proto
1093 : icmp4 '(' icmp4_param_list ')' { }
1096 icmp4_param_list
1097 : { }
1098 | icmp4_expr { }
1099 | icmp4_expr delimiter icmp4_param_list { }
1102 icmp4_field
1103 : K_TYPE { proto_field_set(ICMPV4_TYPE); }
1104 | K_CODE { proto_field_set(ICMPV4_CODE); }
1105 | K_ID { proto_field_set(ICMPV4_ID); }
1106 | K_SEQ { proto_field_set(ICMPV4_SEQ); }
1107 | K_MTU { proto_field_set(ICMPV4_MTU); }
1108 | K_ADDR { proto_field_set(ICMPV4_REDIR_ADDR); }
1111 icmp4_expr
1112 : icmp4_field field_expr skip_white '=' skip_white field_value_expr
1113 { proto_field_expr_eval(); }
1114 | icmp4_field skip_white '=' skip_white field_value_expr
1115 { proto_field_expr_eval(); }
1116 | K_ECHO_REQUEST
1117 { proto_hdr_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
1118 proto_hdr_field_set_u8(hdr, ICMPV4_CODE, 0); }
1119 | K_ECHO_REPLY
1120 { proto_hdr_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
1121 proto_hdr_field_set_u8(hdr, ICMPV4_CODE, 0); }
1124 icmp4
1125 : K_ICMP4 { proto_add(PROTO_ICMP4); }
1128 icmpv6_proto
1129 : icmp6 '(' icmp6_param_list ')' { }
1132 icmp6_param_list
1133 : { }
1134 | icmp6_expr { }
1135 | icmp6_expr delimiter icmp6_param_list { }
1138 icmp6_field
1139 : K_CODE { proto_field_set(ICMPV6_CODE); }
1140 | K_CSUM { proto_field_set(ICMPV6_CSUM); }
1143 icmp6_expr
1144 : icmp6_field field_expr skip_white '=' skip_white field_value_expr
1145 { proto_field_expr_eval(); }
1146 | icmp6_field skip_white '=' skip_white field_value_expr
1147 { proto_field_expr_eval(); }
1148 | K_TYPE field_expr skip_white '=' skip_white field_value_expr
1149 { proto_field_set(ICMPV6_TYPE);
1150 proto_field_expr_eval(); }
1151 | K_TYPE skip_white '=' skip_white field_value_expr
1152 { proto_field_set(ICMPV6_TYPE);
1153 proto_field_expr_eval(); }
1154 | K_TYPE skip_white '=' K_ECHO_REQUEST
1155 { proto_hdr_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1156 | K_ECHO_REQUEST
1157 { proto_hdr_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1158 | K_TYPE skip_white '=' K_ECHO_REPLY
1159 { proto_hdr_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1160 | K_ECHO_REPLY
1161 { proto_hdr_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1163 icmp6
1164 : K_ICMP6 { proto_add(PROTO_ICMP6); }
1167 udp_proto
1168 : udp '(' udp_param_list ')' { }
1171 udp_param_list
1172 : { }
1173 | udp_expr { }
1174 | udp_expr delimiter udp_param_list { }
1177 udp_field
1178 : K_SPORT { proto_field_set(UDP_SPORT); }
1179 | K_DPORT { proto_field_set(UDP_DPORT); }
1180 | K_LEN { proto_field_set(UDP_LEN); }
1181 | K_CSUM { proto_field_set(UDP_CSUM); }
1184 udp_expr
1185 : udp_field field_expr skip_white '=' skip_white field_value_expr
1186 { proto_field_expr_eval(); }
1187 | udp_field skip_white '=' skip_white field_value_expr
1188 { proto_field_expr_eval(); }
1192 : K_UDP { proto_add(PROTO_UDP); }
1195 tcp_proto
1196 : tcp '(' tcp_param_list ')' { }
1199 tcp_param_list
1200 : { }
1201 | tcp_expr { }
1202 | tcp_expr delimiter tcp_param_list { }
1205 tcp_field
1206 : K_SPORT { proto_field_set(TCP_SPORT); }
1207 | K_DPORT { proto_field_set(TCP_DPORT); }
1208 | K_SEQ { proto_field_set(TCP_SEQ); }
1209 | K_ACK_SEQ { proto_field_set(TCP_ACK_SEQ); }
1210 | K_DOFF { proto_field_set(TCP_DOFF); }
1211 | K_WINDOW { proto_field_set(TCP_WINDOW); }
1212 | K_CSUM { proto_field_set(TCP_CSUM); }
1213 | K_URG_PTR { proto_field_set(TCP_URG_PTR); }
1216 tcp_expr
1217 : tcp_field field_expr skip_white '=' skip_white field_value_expr
1218 { proto_field_expr_eval(); }
1219 | tcp_field skip_white '=' skip_white field_value_expr
1220 { proto_field_expr_eval(); }
1221 | K_CWR { proto_hdr_field_set_be16(hdr, TCP_CWR, 1); }
1222 | K_ECE { proto_hdr_field_set_be16(hdr, TCP_ECE, 1); }
1223 | K_URG { proto_hdr_field_set_be16(hdr, TCP_URG, 1); }
1224 | K_ACK { proto_hdr_field_set_be16(hdr, TCP_ACK, 1); }
1225 | K_PSH { proto_hdr_field_set_be16(hdr, TCP_PSH, 1); }
1226 | K_RST { proto_hdr_field_set_be16(hdr, TCP_RST, 1); }
1227 | K_SYN { proto_hdr_field_set_be16(hdr, TCP_SYN, 1); }
1228 | K_FIN { proto_hdr_field_set_be16(hdr, TCP_FIN, 1); }
1232 : K_TCP { proto_add(PROTO_TCP); }
1237 static void finalize_packet(void)
1239 /* XXX hack ... we allocated one packet pointer too much */
1240 plen--;
1241 dlen--;
1244 static void dump_conf(void)
1246 size_t i, j;
1248 for (i = 0; i < plen; ++i) {
1249 printf("[%zu] pkt\n", i);
1250 printf(" len %zu cnts %zu rnds %zu\n",
1251 packets[i].len,
1252 packet_dyn[i].clen,
1253 packet_dyn[i].rlen);
1255 printf(" payload ");
1256 for (j = 0; j < packets[i].len; ++j)
1257 printf("%02x ", packets[i].payload[j]);
1258 printf("\n");
1260 for (j = 0; j < packet_dyn[i].clen; ++j)
1261 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
1262 packet_dyn[i].cnt[j].min,
1263 packet_dyn[i].cnt[j].max,
1264 packet_dyn[i].cnt[j].inc,
1265 (intmax_t)packet_dyn[i].cnt[j].off,
1266 packet_dyn[i].cnt[j].type == TYPE_INC ?
1267 "inc" : "dec");
1269 for (j = 0; j < packet_dyn[i].rlen; ++j)
1270 printf(" rnd%zu off %jd\n", j,
1271 (intmax_t)packet_dyn[i].rnd[j].off);
1275 void cleanup_packets(void)
1277 size_t i, j;
1279 for (i = 0; i < plen; ++i) {
1280 struct packet *pkt = &packets[i];
1282 if (pkt->len > 0)
1283 xfree(pkt->payload);
1285 for (j = 0; j < pkt->headers_count; j++) {
1286 struct proto_hdr *hdr = pkt->headers[j];
1288 if (hdr->fields)
1289 xfree(hdr->fields);
1290 xfree(hdr);
1294 free(packets);
1296 for (i = 0; i < dlen; ++i) {
1297 free(packet_dyn[i].cnt);
1298 free(packet_dyn[i].rnd);
1300 for (j = 0; j < packet_dyn[j].flen; j++)
1301 xfree(packet_dyn[i].fields[j]);
1303 free(packet_dyn[i].fields);
1306 free(packet_dyn);
1309 void compile_packets(char *file, bool verbose, unsigned int cpu,
1310 bool invoke_cpp, char *const cpp_argv[])
1312 char tmp_file[128];
1313 int ret = -1;
1315 if (access(file, R_OK)) {
1316 fprintf(stderr, "Cannot access %s: %s!\n", file, strerror(errno));
1317 die();
1320 memset(tmp_file, 0, sizeof(tmp_file));
1321 our_cpu = cpu;
1323 if (invoke_cpp) {
1324 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1325 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1326 goto err;
1328 file = tmp_file;
1331 if (!strncmp("-", file, strlen("-")))
1332 yyin = stdin;
1333 else
1334 yyin = fopen(file, "r");
1335 if (!yyin) {
1336 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1337 goto err;
1340 realloc_packet();
1341 if (yyparse() != 0)
1342 goto err;
1343 finalize_packet();
1345 if (our_cpu == 0 && verbose)
1346 dump_conf();
1348 ret = 0;
1349 err:
1350 if (yyin && yyin != stdin)
1351 fclose(yyin);
1353 if (invoke_cpp)
1354 unlink(tmp_file);
1355 if (ret)
1356 die();
1359 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1361 int ret = 1;
1363 our_cpu = cpu;
1364 realloc_packet();
1366 yy_scan_string(str);
1367 if (yyparse() != 0)
1368 goto err;
1370 finalize_packet();
1371 if (our_cpu == 0 && verbose)
1372 dump_conf();
1374 ret = 0;
1375 err:
1376 yylex_destroy();
1378 if (ret)
1379 die();
1382 void yyerror(const char *err)
1384 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);