colorize: Squash colorize macros into colors.h
[netsniff-ng.git] / trafgen_parser.y
blobcd87c12c5eeb3f2003bb84bc58834b9252690895
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 static struct proto_hdr *hdr;
74 static inline int test_ignore(void)
76 if (min_cpu < 0 && max_cpu < 0)
77 return 0;
78 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
79 return 0;
80 else
81 return 1;
84 static inline void __init_new_packet_slot(struct packet *slot)
86 slot->payload = NULL;
87 slot->len = 0;
90 static inline void __init_new_counter_slot(struct packet_dyn *slot)
92 slot->cnt = NULL;
93 slot->clen = 0;
96 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
98 slot->rnd = NULL;
99 slot->rlen = 0;
102 static inline void __init_new_csum_slot(struct packet_dyn *slot)
104 slot->csum = NULL;
105 slot->slen = 0;
108 static inline void __setup_new_counter(struct counter *c, uint8_t start,
109 uint8_t stop, uint8_t stepping,
110 int type)
112 c->min = start;
113 c->max = stop;
114 c->inc = stepping;
115 c->val = (type == TYPE_INC) ? start : stop;
116 c->off = payload_last;
117 c->type = type;
120 static inline void __setup_new_randomizer(struct randomizer *r)
122 r->off = payload_last;
125 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
126 enum csum which)
128 s->off = payload_last - 1;
129 s->from = from;
130 s->to = to;
131 s->which = which;
134 static void realloc_packet(void)
136 if (test_ignore())
137 return;
139 plen++;
140 packets = xrealloc(packets, plen * sizeof(*packets));
142 __init_new_packet_slot(&packets[packet_last]);
144 dlen++;
145 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
147 __init_new_counter_slot(&packet_dyn[packetd_last]);
148 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
149 __init_new_csum_slot(&packet_dyn[packetd_last]);
152 struct packet *current_packet(void)
154 return &packets[packet_last];
157 uint32_t current_packet_id(void)
159 return packet_last;
162 struct packet *packet_get(uint32_t id)
164 return &packets[id];
167 static void set_byte(uint8_t val)
169 struct packet *pkt = &packets[packet_last];
171 if (test_ignore())
172 return;
174 pkt->len++;
175 pkt->payload = xrealloc(pkt->payload, pkt->len);
176 pkt->payload[payload_last] = val;
179 static void set_multi_byte(uint8_t *s, size_t len)
181 size_t i;
183 for (i = 0; i < len; ++i)
184 set_byte(s[i]);
187 void set_fill(uint8_t val, size_t len)
189 size_t i;
190 struct packet *pkt = &packets[packet_last];
192 if (test_ignore())
193 return;
195 pkt->len += len;
196 pkt->payload = xrealloc(pkt->payload, pkt->len);
197 for (i = 0; i < len; ++i)
198 pkt->payload[payload_last - i] = val;
201 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
203 struct packet *pkt = &packets[packet_last];
204 struct packet_dyn *pktd = &packet_dyn[packetd_last];
206 pkt->len += 2;
207 pkt->payload = xrealloc(pkt->payload, pkt->len);
209 pktd->slen++;
210 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
212 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
215 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
217 struct packet *pkt = &packets[packet_last];
218 uint16_t sum;
219 uint8_t *psum;
221 sum = htons(calc_csum(pkt->payload + from, to - from));
222 psum = (uint8_t *) &sum;
224 set_byte(psum[0]);
225 set_byte(psum[1]);
228 static inline bool is_dynamic_csum(enum csum which)
230 switch (which) {
231 case CSUM_UDP:
232 case CSUM_TCP:
233 case CSUM_UDP6:
234 case CSUM_TCP6:
235 return true;
236 default:
237 return false;
241 static void set_csum16(size_t from, size_t to, enum csum which)
243 struct packet *pkt = &packets[packet_last];
244 struct packet_dyn *pktd = &packet_dyn[packetd_last];
246 if (test_ignore())
247 return;
249 if (to < from) {
250 size_t tmp = to;
252 to = from;
253 from = tmp;
256 bug_on(!(from < to));
258 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
259 __set_csum16_dynamic(from, to, which);
260 else
261 __set_csum16_static(from, to, which);
264 static void set_rnd(size_t len)
266 size_t i;
267 struct packet *pkt = &packets[packet_last];
269 if (test_ignore())
270 return;
272 pkt->len += len;
273 pkt->payload = xrealloc(pkt->payload, pkt->len);
274 for (i = 0; i < len; ++i)
275 pkt->payload[payload_last - i] = (uint8_t) rand();
278 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
280 size_t i;
281 struct packet *pkt = &packets[packet_last];
283 if (test_ignore())
284 return;
286 pkt->len += len;
287 pkt->payload = xrealloc(pkt->payload, pkt->len);
288 for (i = 0; i < len; ++i) {
289 off_t off = len - 1 - i;
291 pkt->payload[payload_last - off] = start;
292 start += stepping;
296 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
298 size_t i;
299 struct packet *pkt = &packets[packet_last];
301 if (test_ignore())
302 return;
304 pkt->len += len;
305 pkt->payload = xrealloc(pkt->payload, pkt->len);
306 for (i = 0; i < len; ++i) {
307 int off = len - 1 - i;
309 pkt->payload[payload_last - off] = start;
310 start -= stepping;
314 static void set_dynamic_rnd(void)
316 struct packet *pkt = &packets[packet_last];
317 struct packet_dyn *pktd = &packet_dyn[packetd_last];
319 if (test_ignore())
320 return;
322 pkt->len++;
323 pkt->payload = xrealloc(pkt->payload, pkt->len);
325 pktd->rlen++;
326 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
328 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
331 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
332 int type)
334 struct packet *pkt = &packets[packet_last];
335 struct packet_dyn *pktd = &packet_dyn[packetd_last];
337 if (test_ignore())
338 return;
340 pkt->len++;
341 pkt->payload = xrealloc(pkt->payload, pkt->len);
343 pktd->clen++;
344 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
346 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
349 static void proto_add(enum proto_id pid)
351 hdr = proto_header_init(pid);
356 %union {
357 struct in_addr ip4_addr;
358 struct in6_addr ip6_addr;
359 long long int number;
360 uint8_t bytes[256];
361 char *str;
364 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
365 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
367 %token K_DADDR K_SADDR K_ETYPE K_TYPE
368 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
369 %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
370 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
371 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
372 %token K_SPORT K_DPORT
373 %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
374 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
375 %token K_LABEL K_TC K_LAST K_EXP
377 %token K_ADDR K_MTU
379 %token K_ETH
380 %token K_VLAN K_MPLS
381 %token K_ARP
382 %token K_IP4 K_IP6
383 %token K_ICMP4 K_ICMP6
384 %token K_UDP K_TCP
386 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
388 %token number string mac ip4_addr ip6_addr
390 %type <number> number expression
391 %type <str> string
392 %type <bytes> mac
393 %type <ip4_addr> ip4_addr
394 %type <ip6_addr> ip6_addr
396 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
400 packets
401 : { }
402 | packets packet { }
403 | packets inline_comment { }
404 | packets K_WHITE { }
407 inline_comment
408 : K_COMMENT { }
411 cpu_delim
412 : ':' { }
413 | '-' { }
416 delimiter_nowhite
417 : ',' { }
418 | ',' K_WHITE { }
421 noenforce_white
422 : { }
423 | K_WHITE { }
424 | delimiter_nowhite { }
427 skip_white
428 : { }
429 | K_WHITE { }
431 packet
432 : '{' noenforce_white payload noenforce_white '}' {
433 min_cpu = max_cpu = -1;
435 proto_packet_finish();
437 realloc_packet();
439 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
440 min_cpu = $3;
441 max_cpu = $5;
443 if (min_cpu > max_cpu) {
444 int tmp = min_cpu;
446 min_cpu = max_cpu;
447 max_cpu = tmp;
450 proto_packet_finish();
452 realloc_packet();
454 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
455 min_cpu = max_cpu = $3;
457 proto_packet_finish();
459 realloc_packet();
463 payload
464 : elem { }
465 | payload elem_delimiter { }
468 delimiter
469 : delimiter_nowhite { }
470 | K_WHITE { }
473 elem_delimiter
474 : delimiter elem { }
477 elem
478 : number { set_byte((uint8_t) $1); }
479 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
480 | fill { }
481 | rnd { }
482 | drnd { }
483 | seqinc { }
484 | seqdec { }
485 | dinc { }
486 | ddec { }
487 | csum { }
488 | const { }
489 | proto { proto_header_finish(hdr); }
490 | inline_comment { }
493 expression
494 : number
495 { $$ = $1; }
496 | expression '+' expression
497 { $$ = $1 + $3; }
498 | expression '-' expression
499 { $$ = $1 - $3; }
500 | expression '*' expression
501 { $$ = $1 * $3; }
502 | expression '/' expression
503 { $$ = $1 / $3; }
504 | expression '%' expression
505 { $$ = $1 % $3; }
506 | expression '&' expression
507 { $$ = $1 & $3; }
508 | expression '|' expression
509 { $$ = $1 | $3; }
510 | expression '^' expression
511 { $$ = $1 ^ $3; }
512 | expression '<' '<' expression
513 { $$ = $1 << $4; }
514 | expression '>' '>' expression
515 { $$ = $1 >> $4; }
516 | '-' expression
517 { $$ = -1 * $2; }
518 | '(' expression ')'
519 { $$ = $2;}
522 fill
523 : K_FILL '(' number delimiter number ')'
524 { set_fill($3, $5); }
527 const
528 : K_CONST8 '(' expression ')'
529 { set_byte((uint8_t) $3); }
530 | K_CONST16 '(' expression ')' {
531 uint16_t __c = cpu_to_be16((uint16_t) $3);
533 set_multi_byte((uint8_t *) &__c, sizeof(__c));
535 | K_CONST32 '(' expression ')' {
536 uint32_t __c = cpu_to_be32((uint32_t) $3);
538 set_multi_byte((uint8_t *) &__c, sizeof(__c));
540 | K_CONST64 '(' expression ')' {
541 uint64_t __c = cpu_to_be64((uint64_t) $3);
543 set_multi_byte((uint8_t *) &__c, sizeof(__c));
548 : K_RND '(' number ')'
549 { set_rnd($3); }
552 csum
553 : K_CSUMIP '(' number delimiter number ')'
554 { set_csum16($3, $5, CSUM_IP); }
555 | K_CSUMTCP '(' number delimiter number ')'
556 { set_csum16($3, $5, CSUM_TCP); }
557 | K_CSUMUDP '(' number delimiter number ')'
558 { set_csum16($3, $5, CSUM_UDP); }
559 | K_CSUMTCP6 '(' number delimiter number ')'
560 { set_csum16($3, $5, CSUM_TCP6); }
561 | K_CSUMUDP6 '(' number delimiter number ')'
562 { set_csum16($3, $5, CSUM_UDP6); }
565 seqinc
566 : K_SEQINC '(' number delimiter number ')'
567 { set_sequential_inc($3, $5, 1); }
568 | K_SEQINC '(' number delimiter number delimiter number ')'
569 { set_sequential_inc($3, $5, $7); }
572 seqdec
573 : K_SEQDEC '(' number delimiter number ')'
574 { set_sequential_dec($3, $5, 1); }
575 | K_SEQDEC '(' number delimiter number delimiter number ')'
576 { set_sequential_dec($3, $5, $7); }
579 drnd
580 : K_DRND '(' ')'
581 { set_dynamic_rnd(); }
582 | K_DRND '(' number ')'
584 int i, max = $3;
585 for (i = 0; i < max; ++i)
586 set_dynamic_rnd();
590 dinc
591 : K_DINC '(' number delimiter number ')'
592 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
593 | K_DINC '(' number delimiter number delimiter number ')'
594 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
597 ddec
598 : K_DDEC '(' number delimiter number ')'
599 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
600 | K_DDEC '(' number delimiter number delimiter number ')'
601 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
604 proto
605 : eth_proto { }
606 | vlan_proto { }
607 | mpls_proto { }
608 | arp_proto { }
609 | ip4_proto { }
610 | ip6_proto { }
611 | icmp4_proto { }
612 | icmpv6_proto { }
613 | udp_proto { }
614 | tcp_proto { }
617 eth_proto
618 : eth '(' eth_param_list ')' { }
622 : K_ETH { proto_add(PROTO_ETH); }
625 eth_param_list
626 : { }
627 | eth_field { }
628 | eth_field delimiter eth_param_list { }
631 eth_type
632 : K_ETYPE { }
633 | K_TYPE { }
634 | K_PROT { }
637 eth_field
638 : K_DADDR skip_white '=' skip_white mac
639 { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
640 | K_SADDR skip_white '=' skip_white mac
641 { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
642 | eth_type skip_white '=' skip_white number
643 { proto_field_set_be16(hdr, ETH_TYPE, $5); }
646 vlan_proto
647 : vlan '(' vlan_param_list ')' { }
650 vlan
651 : K_VLAN { proto_add(PROTO_VLAN); }
654 vlan_param_list
655 : { }
656 | vlan_field { }
657 | vlan_field delimiter vlan_param_list { }
660 vlan_type
661 : K_TPID { }
662 | K_PROT
665 vlan_field
666 : vlan_type skip_white '=' skip_white number
667 { proto_field_set_be16(hdr, VLAN_TPID, $5); }
668 | K_1Q
669 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
670 | K_1AD
671 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
672 | K_TCI skip_white '=' skip_white number
673 { proto_field_set_be16(hdr, VLAN_TCI, $5); }
674 | K_PCP skip_white '=' skip_white number
675 { proto_field_set_be16(hdr, VLAN_PCP, $5); }
676 | K_DEI skip_white '=' skip_white number
677 { proto_field_set_be16(hdr, VLAN_DEI, $5); }
678 | K_ID skip_white '=' skip_white number
679 { proto_field_set_be16(hdr, VLAN_VID, $5); }
682 mpls_proto
683 : mpls '(' mpls_param_list ')' { }
686 mpls
687 : K_MPLS { proto_add(PROTO_MPLS); }
690 mpls_param_list
691 : { }
692 | mpls_field { }
693 | mpls_field delimiter mpls_param_list { }
696 mpls_tc
697 : K_TC { }
698 | K_EXP { }
701 mpls_field
702 : K_LABEL skip_white '=' skip_white number
703 { proto_field_set_be32(hdr, MPLS_LABEL, $5); }
704 | mpls_tc skip_white '=' skip_white number
705 { proto_field_set_be32(hdr, MPLS_TC, $5); }
706 | K_LAST skip_white '=' skip_white number
707 { proto_field_set_be32(hdr, MPLS_LAST, $5); }
708 | K_TTL skip_white '=' skip_white number
709 { proto_field_set_be32(hdr, MPLS_TTL, $5); }
712 arp_proto
713 : arp '(' arp_param_list ')' { }
716 arp_param_list
717 : { }
718 | arp_field { }
719 | arp_field delimiter arp_param_list { }
722 arp_field
723 : K_OPER skip_white '=' skip_white K_REQUEST
724 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
725 | K_OPER skip_white '=' skip_white K_REPLY
726 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
727 | K_OPER skip_white '=' skip_white number
728 { proto_field_set_be16(hdr, ARP_OPER, $5); }
729 | K_REQUEST
730 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
731 | K_REPLY
732 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
733 | K_HTYPE skip_white '=' skip_white number
734 { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
735 | K_PTYPE skip_white '=' skip_white number
736 { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
737 | K_SHA skip_white '=' skip_white mac
738 { proto_field_set_bytes(hdr, ARP_SHA, $5); }
739 | K_THA skip_white '=' skip_white mac
740 { proto_field_set_bytes(hdr, ARP_THA, $5); }
741 | K_SPA skip_white '=' skip_white ip4_addr
742 { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
743 | K_TPA skip_white '=' skip_white ip4_addr
744 { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
747 : K_ARP { proto_add(PROTO_ARP); }
750 ip4_proto
751 : ip4 '(' ip4_param_list ')' { }
754 ip4_param_list
755 : { }
756 | ip4_field { }
757 | ip4_field delimiter ip4_param_list { }
760 ip4_field
761 : K_VER skip_white '=' skip_white number
762 { proto_field_set_u8(hdr, IP4_VER, $5); }
763 | K_IHL skip_white '=' skip_white number
764 { proto_field_set_u8(hdr, IP4_IHL, $5); }
765 | K_DADDR skip_white '=' skip_white ip4_addr
766 { proto_field_set_u32(hdr, IP4_DADDR, $5.s_addr); }
767 | K_SADDR skip_white '=' skip_white ip4_addr
768 { proto_field_set_u32(hdr, IP4_SADDR, $5.s_addr); }
769 | K_PROT skip_white '=' skip_white number
770 { proto_field_set_u8(hdr, IP4_PROTO, $5); }
771 | K_TTL skip_white '=' skip_white number
772 { proto_field_set_u8(hdr, IP4_TTL, $5); }
773 | K_DSCP skip_white '=' skip_white number
774 { proto_field_set_u8(hdr, IP4_DSCP, $5); }
775 | K_ECN skip_white '=' skip_white number
776 { proto_field_set_u8(hdr, IP4_ECN, $5); }
777 | K_TOS skip_white '=' skip_white number
778 { proto_field_set_u8(hdr, IP4_TOS, $5); }
779 | K_LEN skip_white '=' skip_white number
780 { proto_field_set_be16(hdr, IP4_LEN, $5); }
781 | K_ID skip_white '=' skip_white number
782 { proto_field_set_be16(hdr, IP4_ID, $5); }
783 | K_FLAGS skip_white '=' skip_white number
784 { proto_field_set_be16(hdr, IP4_FLAGS, $5); }
785 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
786 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
787 | K_FRAG skip_white '=' skip_white number
788 { proto_field_set_be16(hdr, IP4_FRAG_OFFS, $5); }
789 | K_CSUM skip_white '=' skip_white number
790 { proto_field_set_be16(hdr, IP4_CSUM, $5); }
794 : K_IP4 { proto_add(PROTO_IP4); }
797 ip6_proto
798 : ip6 '(' ip6_param_list ')' { }
801 ip6_param_list
802 : { }
803 | ip6_field { }
804 | ip6_field delimiter ip6_param_list { }
807 ip6_hop_limit
808 : K_HOP_LIMIT { }
809 | K_TTL { }
812 ip6_field
813 : K_VER skip_white '=' skip_white number
814 { proto_field_set_be32(hdr, IP6_VER, $5); }
815 | K_TC skip_white '=' skip_white number
816 { proto_field_set_be32(hdr, IP6_CLASS, $5); }
817 | K_FLOW skip_white '=' skip_white number
818 { proto_field_set_be32(hdr, IP6_FLOW_LBL, $5); }
819 | K_LEN skip_white '=' skip_white number
820 { proto_field_set_be16(hdr, IP6_LEN, $5); }
821 | K_NEXT_HDR skip_white '=' skip_white number
822 { proto_field_set_u8(hdr, IP6_NEXT_HDR, $5); }
823 | ip6_hop_limit skip_white '=' skip_white number
824 { proto_field_set_u8(hdr, IP6_HOP_LIMIT, $5); }
825 | K_SADDR skip_white '=' skip_white ip6_addr
826 { proto_field_set_bytes(hdr, IP6_SADDR, (uint8_t *)&($5.s6_addr)); }
827 | K_DADDR skip_white '=' skip_white ip6_addr
828 { proto_field_set_bytes(hdr, IP6_DADDR, (uint8_t *)&($5.s6_addr)); }
832 : K_IP6 { proto_add(PROTO_IP6); }
835 icmp4_proto
836 : icmp4 '(' icmp4_param_list ')' { }
839 icmp4_param_list
840 : { }
841 | icmp4_field { }
842 | icmp4_field delimiter icmp4_param_list { }
845 icmp4_field
846 : K_TYPE skip_white '=' skip_white number
847 { proto_field_set_u8(hdr, ICMPV4_TYPE, $5); }
848 | K_CODE skip_white '=' skip_white number
849 { proto_field_set_u8(hdr, ICMPV4_CODE, $5); }
850 | K_ID skip_white '=' skip_white number
851 { proto_field_set_be16(hdr, ICMPV4_ID, $5); }
852 | K_SEQ skip_white '=' skip_white number
853 { proto_field_set_be16(hdr, ICMPV4_SEQ, $5); }
854 | K_MTU skip_white '=' skip_white number
855 { proto_field_set_be16(hdr, ICMPV4_MTU, $5); }
856 | K_ADDR skip_white '=' skip_white ip4_addr
857 { proto_field_set_u32(hdr, ICMPV4_REDIR_ADDR, $5.s_addr); }
858 | K_ECHO_REQUEST
859 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
860 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
861 | K_ECHO_REPLY
862 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
863 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
866 icmp4
867 : K_ICMP4 { proto_add(PROTO_ICMP4); }
870 icmpv6_proto
871 : icmp6 '(' icmp6_param_list ')' { }
873 icmp6_param_list
874 : { }
875 | icmp6_field { }
876 | icmp6_field delimiter icmp6_param_list { }
879 icmp6_field
880 : K_TYPE skip_white '=' skip_white number
881 { proto_field_set_u8(hdr, ICMPV6_TYPE, $5); }
882 | K_TYPE skip_white '=' K_ECHO_REQUEST
883 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
884 | K_ECHO_REQUEST
885 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
886 | K_TYPE skip_white '=' K_ECHO_REPLY
887 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
888 | K_ECHO_REPLY
889 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
890 | K_CODE skip_white '=' skip_white number
891 { proto_field_set_u8(hdr, ICMPV6_CODE, $5); }
892 | K_CSUM skip_white '=' skip_white number
893 { proto_field_set_be16(hdr, ICMPV6_CSUM, $5); }
896 icmp6
897 : K_ICMP6 { proto_add(PROTO_ICMP6); }
900 udp_proto
901 : udp '(' udp_param_list ')' { }
904 udp_param_list
905 : { }
906 | udp_field { }
907 | udp_field delimiter udp_param_list { }
910 udp_field
911 : K_SPORT skip_white '=' skip_white number
912 { proto_field_set_be16(hdr, UDP_SPORT, $5); }
913 | K_DPORT skip_white '=' skip_white number
914 { proto_field_set_be16(hdr, UDP_DPORT, $5); }
915 | K_LEN skip_white '=' skip_white number
916 { proto_field_set_be16(hdr, UDP_LEN, $5); }
917 | K_CSUM skip_white '=' skip_white number
918 { proto_field_set_be16(hdr, UDP_CSUM, $5); }
922 : K_UDP { proto_add(PROTO_UDP); }
925 tcp_proto
926 : tcp '(' tcp_param_list ')' { }
929 tcp_param_list
930 : { }
931 | tcp_field { }
932 | tcp_field delimiter tcp_param_list { }
935 tcp_field
936 : K_SPORT skip_white '=' skip_white number
937 { proto_field_set_be16(hdr, TCP_SPORT, $5); }
938 | K_DPORT skip_white '=' skip_white number
939 { proto_field_set_be16(hdr, TCP_DPORT, $5); }
940 | K_SEQ skip_white '=' skip_white number
941 { proto_field_set_be32(hdr, TCP_SEQ, $5); }
942 | K_ACK_SEQ skip_white '=' skip_white number
943 { proto_field_set_be32(hdr, TCP_ACK_SEQ, $5); }
944 | K_DOFF skip_white '=' skip_white number
945 { proto_field_set_be16(hdr, TCP_DOFF, $5); }
946 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
947 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
948 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
949 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
950 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
951 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
952 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
953 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
954 | K_WINDOW skip_white '=' skip_white number
955 { proto_field_set_be16(hdr, TCP_WINDOW, $5); }
956 | K_CSUM skip_white '=' skip_white number
957 { proto_field_set_be16(hdr, TCP_CSUM, $5); }
958 | K_URG_PTR skip_white '=' skip_white number
959 { proto_field_set_be16(hdr, TCP_URG_PTR, $5); }
963 : K_TCP { proto_add(PROTO_TCP); }
968 static void finalize_packet(void)
970 /* XXX hack ... we allocated one packet pointer too much */
971 plen--;
972 dlen--;
975 static void dump_conf(void)
977 size_t i, j;
979 for (i = 0; i < plen; ++i) {
980 printf("[%zu] pkt\n", i);
981 printf(" len %zu cnts %zu rnds %zu\n",
982 packets[i].len,
983 packet_dyn[i].clen,
984 packet_dyn[i].rlen);
986 printf(" payload ");
987 for (j = 0; j < packets[i].len; ++j)
988 printf("%02x ", packets[i].payload[j]);
989 printf("\n");
991 for (j = 0; j < packet_dyn[i].clen; ++j)
992 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
993 packet_dyn[i].cnt[j].min,
994 packet_dyn[i].cnt[j].max,
995 packet_dyn[i].cnt[j].inc,
996 (intmax_t)packet_dyn[i].cnt[j].off,
997 packet_dyn[i].cnt[j].type == TYPE_INC ?
998 "inc" : "dec");
1000 for (j = 0; j < packet_dyn[i].rlen; ++j)
1001 printf(" rnd%zu off %jd\n", j,
1002 (intmax_t)packet_dyn[i].rnd[j].off);
1006 void cleanup_packets(void)
1008 size_t i, j;
1010 for (i = 0; i < plen; ++i) {
1011 struct packet *pkt = &packets[i];
1013 if (pkt->len > 0)
1014 xfree(pkt->payload);
1016 for (j = 0; j < pkt->headers_count; j++) {
1017 struct proto_hdr *hdr = pkt->headers[j];
1019 if (hdr->fields)
1020 xfree(hdr->fields);
1021 xfree(hdr);
1025 free(packets);
1027 for (i = 0; i < dlen; ++i) {
1028 free(packet_dyn[i].cnt);
1029 free(packet_dyn[i].rnd);
1032 free(packet_dyn);
1035 void compile_packets(char *file, bool verbose, unsigned int cpu,
1036 bool invoke_cpp, char *const cpp_argv[])
1038 char tmp_file[128];
1039 int ret = -1;
1041 if (access(file, R_OK)) {
1042 fprintf(stderr, "Cannot access %s: %s!\n", file, strerror(errno));
1043 die();
1046 memset(tmp_file, 0, sizeof(tmp_file));
1047 our_cpu = cpu;
1049 if (invoke_cpp) {
1050 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1051 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1052 goto err;
1054 file = tmp_file;
1057 if (!strncmp("-", file, strlen("-")))
1058 yyin = stdin;
1059 else
1060 yyin = fopen(file, "r");
1061 if (!yyin) {
1062 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1063 goto err;
1066 realloc_packet();
1067 if (yyparse() != 0)
1068 goto err;
1069 finalize_packet();
1071 if (our_cpu == 0 && verbose)
1072 dump_conf();
1074 ret = 0;
1075 err:
1076 if (yyin && yyin != stdin)
1077 fclose(yyin);
1079 if (invoke_cpp)
1080 unlink(tmp_file);
1081 if (ret)
1082 die();
1085 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1087 int ret = 1;
1089 our_cpu = cpu;
1090 realloc_packet();
1092 yy_scan_string(str);
1093 if (yyparse() != 0)
1094 goto err;
1096 finalize_packet();
1097 if (our_cpu == 0 && verbose)
1098 dump_conf();
1100 ret = 0;
1101 err:
1102 yylex_destroy();
1104 if (ret)
1105 die();
1108 void yyerror(const char *err)
1110 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);