AUTHORS: Add Paolo Abeni for his contribution
[netsniff-ng-new.git] / trafgen_parser.y
blob0fe8674983fc66fcfb5aecaafc8963b2a1b4777e
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 <signal.h>
16 #include <stdint.h>
17 #include <errno.h>
18 #include <stdbool.h>
19 #include <libgen.h>
20 #include <net/if_arp.h>
21 #include <netinet/in.h>
22 #include <linux/icmp.h>
23 #include <linux/if_ether.h>
24 #include <linux/icmpv6.h>
26 #include "xmalloc.h"
27 #include "trafgen_parser.tab.h"
28 #include "trafgen_conf.h"
29 #include "trafgen_proto.h"
30 #include "trafgen_l2.h"
31 #include "trafgen_l3.h"
32 #include "trafgen_l4.h"
33 #include "built_in.h"
34 #include "die.h"
35 #include "str.h"
36 #include "csum.h"
37 #include "cpp.h"
39 #define YYERROR_VERBOSE 0
40 #define YYDEBUG 0
41 #define YYENABLE_NLS 1
42 #define YYLTYPE_IS_TRIVIAL 1
43 #define ENABLE_NLS 1
45 extern FILE *yyin;
46 extern int yylex(void);
47 extern void yy_scan_string(char *);
48 extern void yylex_destroy();
49 extern void yyerror(const char *);
50 extern int yylineno;
51 extern char *yytext;
53 extern struct packet *packets;
54 extern size_t plen;
56 #define packet_last (plen - 1)
58 #define payload_last (packets[packet_last].len - 1)
60 extern struct packet_dyn *packet_dyn;
61 extern size_t dlen;
63 #define packetd_last (dlen - 1)
65 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
66 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
67 #define packetds_last (packet_dyn[packetd_last].slen - 1)
69 static int our_cpu, min_cpu = -1, max_cpu = -1;
71 static struct proto_hdr *hdr;
73 static inline int test_ignore(void)
75 if (min_cpu < 0 && max_cpu < 0)
76 return 0;
77 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
78 return 0;
79 else
80 return 1;
83 static inline void __init_new_packet_slot(struct packet *slot)
85 slot->payload = NULL;
86 slot->len = 0;
89 static inline void __init_new_counter_slot(struct packet_dyn *slot)
91 slot->cnt = NULL;
92 slot->clen = 0;
95 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
97 slot->rnd = NULL;
98 slot->rlen = 0;
101 static inline void __init_new_csum_slot(struct packet_dyn *slot)
103 slot->csum = NULL;
104 slot->slen = 0;
107 static inline void __setup_new_counter(struct counter *c, uint8_t start,
108 uint8_t stop, uint8_t stepping,
109 int type)
111 c->min = start;
112 c->max = stop;
113 c->inc = stepping;
114 c->val = (type == TYPE_INC) ? start : stop;
115 c->off = payload_last;
116 c->type = type;
119 static inline void __setup_new_randomizer(struct randomizer *r)
121 r->off = payload_last;
124 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
125 enum csum which)
127 s->off = payload_last - 1;
128 s->from = from;
129 s->to = to;
130 s->which = which;
133 static void realloc_packet(void)
135 if (test_ignore())
136 return;
138 plen++;
139 packets = xrealloc(packets, plen * sizeof(*packets));
141 __init_new_packet_slot(&packets[packet_last]);
143 dlen++;
144 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
146 __init_new_counter_slot(&packet_dyn[packetd_last]);
147 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
148 __init_new_csum_slot(&packet_dyn[packetd_last]);
151 struct packet *current_packet(void)
153 return &packets[packet_last];
156 static void set_byte(uint8_t val)
158 struct packet *pkt = &packets[packet_last];
160 if (test_ignore())
161 return;
163 pkt->len++;
164 pkt->payload = xrealloc(pkt->payload, pkt->len);
165 pkt->payload[payload_last] = val;
168 static void set_multi_byte(uint8_t *s, size_t len)
170 size_t i;
172 for (i = 0; i < len; ++i)
173 set_byte(s[i]);
176 void set_fill(uint8_t val, size_t len)
178 size_t i;
179 struct packet *pkt = &packets[packet_last];
181 if (test_ignore())
182 return;
184 pkt->len += len;
185 pkt->payload = xrealloc(pkt->payload, pkt->len);
186 for (i = 0; i < len; ++i)
187 pkt->payload[payload_last - i] = val;
190 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
192 struct packet *pkt = &packets[packet_last];
193 struct packet_dyn *pktd = &packet_dyn[packetd_last];
195 pkt->len += 2;
196 pkt->payload = xrealloc(pkt->payload, pkt->len);
198 pktd->slen++;
199 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
201 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
204 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
206 struct packet *pkt = &packets[packet_last];
207 uint16_t sum;
208 uint8_t *psum;
210 sum = htons(calc_csum(pkt->payload + from, to - from));
211 psum = (uint8_t *) &sum;
213 set_byte(psum[0]);
214 set_byte(psum[1]);
217 static inline bool is_dynamic_csum(enum csum which)
219 switch (which) {
220 case CSUM_UDP:
221 case CSUM_TCP:
222 case CSUM_UDP6:
223 case CSUM_TCP6:
224 return true;
225 default:
226 return false;
230 static void set_csum16(size_t from, size_t to, enum csum which)
232 struct packet *pkt = &packets[packet_last];
233 struct packet_dyn *pktd = &packet_dyn[packetd_last];
235 if (test_ignore())
236 return;
238 if (to < from) {
239 size_t tmp = to;
241 to = from;
242 from = tmp;
245 bug_on(!(from < to));
247 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
248 __set_csum16_dynamic(from, to, which);
249 else
250 __set_csum16_static(from, to, which);
253 static void set_rnd(size_t len)
255 size_t i;
256 struct packet *pkt = &packets[packet_last];
258 if (test_ignore())
259 return;
261 pkt->len += len;
262 pkt->payload = xrealloc(pkt->payload, pkt->len);
263 for (i = 0; i < len; ++i)
264 pkt->payload[payload_last - i] = (uint8_t) rand();
267 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
269 size_t i;
270 struct packet *pkt = &packets[packet_last];
272 if (test_ignore())
273 return;
275 pkt->len += len;
276 pkt->payload = xrealloc(pkt->payload, pkt->len);
277 for (i = 0; i < len; ++i) {
278 off_t off = len - 1 - i;
280 pkt->payload[payload_last - off] = start;
281 start += stepping;
285 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
287 size_t i;
288 struct packet *pkt = &packets[packet_last];
290 if (test_ignore())
291 return;
293 pkt->len += len;
294 pkt->payload = xrealloc(pkt->payload, pkt->len);
295 for (i = 0; i < len; ++i) {
296 int off = len - 1 - i;
298 pkt->payload[payload_last - off] = start;
299 start -= stepping;
303 static void set_dynamic_rnd(void)
305 struct packet *pkt = &packets[packet_last];
306 struct packet_dyn *pktd = &packet_dyn[packetd_last];
308 if (test_ignore())
309 return;
311 pkt->len++;
312 pkt->payload = xrealloc(pkt->payload, pkt->len);
314 pktd->rlen++;
315 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
317 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
320 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
321 int type)
323 struct packet *pkt = &packets[packet_last];
324 struct packet_dyn *pktd = &packet_dyn[packetd_last];
326 if (test_ignore())
327 return;
329 pkt->len++;
330 pkt->payload = xrealloc(pkt->payload, pkt->len);
332 pktd->clen++;
333 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
335 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
338 static void proto_add(enum proto_id pid)
340 hdr = proto_header_init(pid);
345 %union {
346 struct in_addr ip4_addr;
347 struct in6_addr ip6_addr;
348 long long int number;
349 uint8_t bytes[256];
350 char *str;
353 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
354 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
356 %token K_DADDR K_SADDR K_ETYPE K_TYPE
357 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
358 %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
359 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
360 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
361 %token K_SPORT K_DPORT
362 %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
363 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
364 %token K_LABEL K_TC K_LAST K_EXP
366 %token K_ADDR K_MTU
368 %token K_ETH
369 %token K_VLAN K_MPLS
370 %token K_ARP
371 %token K_IP4 K_IP6
372 %token K_ICMP4 K_ICMP6
373 %token K_UDP K_TCP
375 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
377 %token number string mac ip4_addr ip6_addr
379 %type <number> number expression
380 %type <str> string
381 %type <bytes> mac
382 %type <ip4_addr> ip4_addr
383 %type <ip6_addr> ip6_addr
385 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
389 packets
390 : { }
391 | packets packet { }
392 | packets inline_comment { }
393 | packets K_WHITE { }
396 inline_comment
397 : K_COMMENT { }
400 cpu_delim
401 : ':' { }
402 | '-' { }
405 delimiter_nowhite
406 : ',' { }
407 | ',' K_WHITE { }
410 noenforce_white
411 : { }
412 | K_WHITE { }
413 | delimiter_nowhite { }
416 skip_white
417 : { }
418 | K_WHITE { }
420 packet
421 : '{' noenforce_white payload noenforce_white '}' {
422 min_cpu = max_cpu = -1;
424 proto_packet_finish();
426 realloc_packet();
428 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
429 min_cpu = $3;
430 max_cpu = $5;
432 if (min_cpu > max_cpu) {
433 int tmp = min_cpu;
435 min_cpu = max_cpu;
436 max_cpu = tmp;
439 proto_packet_finish();
441 realloc_packet();
443 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
444 min_cpu = max_cpu = $3;
446 proto_packet_finish();
448 realloc_packet();
452 payload
453 : elem { }
454 | payload elem_delimiter { }
457 delimiter
458 : delimiter_nowhite { }
459 | K_WHITE { }
462 elem_delimiter
463 : delimiter elem { }
466 elem
467 : number { set_byte((uint8_t) $1); }
468 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
469 | fill { }
470 | rnd { }
471 | drnd { }
472 | seqinc { }
473 | seqdec { }
474 | dinc { }
475 | ddec { }
476 | csum { }
477 | const { }
478 | proto { proto_header_finish(hdr); }
479 | inline_comment { }
482 expression
483 : number
484 { $$ = $1; }
485 | expression '+' expression
486 { $$ = $1 + $3; }
487 | expression '-' expression
488 { $$ = $1 - $3; }
489 | expression '*' expression
490 { $$ = $1 * $3; }
491 | expression '/' expression
492 { $$ = $1 / $3; }
493 | expression '%' expression
494 { $$ = $1 % $3; }
495 | expression '&' expression
496 { $$ = $1 & $3; }
497 | expression '|' expression
498 { $$ = $1 | $3; }
499 | expression '^' expression
500 { $$ = $1 ^ $3; }
501 | expression '<' '<' expression
502 { $$ = $1 << $4; }
503 | expression '>' '>' expression
504 { $$ = $1 >> $4; }
505 | '-' expression
506 { $$ = -1 * $2; }
507 | '(' expression ')'
508 { $$ = $2;}
511 fill
512 : K_FILL '(' number delimiter number ')'
513 { set_fill($3, $5); }
516 const
517 : K_CONST8 '(' expression ')'
518 { set_byte((uint8_t) $3); }
519 | K_CONST16 '(' expression ')' {
520 uint16_t __c = cpu_to_be16((uint16_t) $3);
522 set_multi_byte((uint8_t *) &__c, sizeof(__c));
524 | K_CONST32 '(' expression ')' {
525 uint32_t __c = cpu_to_be32((uint32_t) $3);
527 set_multi_byte((uint8_t *) &__c, sizeof(__c));
529 | K_CONST64 '(' expression ')' {
530 uint64_t __c = cpu_to_be64((uint64_t) $3);
532 set_multi_byte((uint8_t *) &__c, sizeof(__c));
537 : K_RND '(' number ')'
538 { set_rnd($3); }
541 csum
542 : K_CSUMIP '(' number delimiter number ')'
543 { set_csum16($3, $5, CSUM_IP); }
544 | K_CSUMTCP '(' number delimiter number ')'
545 { set_csum16($3, $5, CSUM_TCP); }
546 | K_CSUMUDP '(' number delimiter number ')'
547 { set_csum16($3, $5, CSUM_UDP); }
548 | K_CSUMTCP6 '(' number delimiter number ')'
549 { set_csum16($3, $5, CSUM_TCP6); }
550 | K_CSUMUDP6 '(' number delimiter number ')'
551 { set_csum16($3, $5, CSUM_UDP6); }
554 seqinc
555 : K_SEQINC '(' number delimiter number ')'
556 { set_sequential_inc($3, $5, 1); }
557 | K_SEQINC '(' number delimiter number delimiter number ')'
558 { set_sequential_inc($3, $5, $7); }
561 seqdec
562 : K_SEQDEC '(' number delimiter number ')'
563 { set_sequential_dec($3, $5, 1); }
564 | K_SEQDEC '(' number delimiter number delimiter number ')'
565 { set_sequential_dec($3, $5, $7); }
568 drnd
569 : K_DRND '(' ')'
570 { set_dynamic_rnd(); }
571 | K_DRND '(' number ')'
573 int i, max = $3;
574 for (i = 0; i < max; ++i)
575 set_dynamic_rnd();
579 dinc
580 : K_DINC '(' number delimiter number ')'
581 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
582 | K_DINC '(' number delimiter number delimiter number ')'
583 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
586 ddec
587 : K_DDEC '(' number delimiter number ')'
588 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
589 | K_DDEC '(' number delimiter number delimiter number ')'
590 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
593 proto
594 : eth_proto { }
595 | vlan_proto { }
596 | mpls_proto { }
597 | arp_proto { }
598 | ip4_proto { }
599 | ip6_proto { }
600 | icmp4_proto { }
601 | icmpv6_proto { }
602 | udp_proto { }
603 | tcp_proto { }
606 eth_proto
607 : eth '(' eth_param_list ')' { }
611 : K_ETH { proto_add(PROTO_ETH); }
614 eth_param_list
615 : { }
616 | eth_field { }
617 | eth_field delimiter eth_param_list { }
620 eth_type
621 : K_ETYPE { }
622 | K_TYPE { }
623 | K_PROT { }
626 eth_field
627 : K_DADDR skip_white '=' skip_white mac
628 { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
629 | K_SADDR skip_white '=' skip_white mac
630 { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
631 | eth_type skip_white '=' skip_white number
632 { proto_field_set_be16(hdr, ETH_TYPE, $5); }
635 vlan_proto
636 : vlan '(' vlan_param_list ')' { }
639 vlan
640 : K_VLAN { proto_add(PROTO_VLAN); }
643 vlan_param_list
644 : { }
645 | vlan_field { }
646 | vlan_field delimiter vlan_param_list { }
649 vlan_type
650 : K_TPID { }
651 | K_PROT
654 vlan_field
655 : vlan_type skip_white '=' skip_white number
656 { proto_field_set_be16(hdr, VLAN_TPID, $5); }
657 | K_1Q
658 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
659 | K_1AD
660 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
661 | K_TCI skip_white '=' skip_white number
662 { proto_field_set_be16(hdr, VLAN_TCI, $5); }
663 | K_PCP skip_white '=' skip_white number
664 { proto_field_set_be16(hdr, VLAN_PCP, $5); }
665 | K_DEI skip_white '=' skip_white number
666 { proto_field_set_be16(hdr, VLAN_DEI, $5); }
667 | K_ID skip_white '=' skip_white number
668 { proto_field_set_be16(hdr, VLAN_VID, $5); }
671 mpls_proto
672 : mpls '(' mpls_param_list ')' { }
675 mpls
676 : K_MPLS { proto_add(PROTO_MPLS); }
679 mpls_param_list
680 : { }
681 | mpls_field { }
682 | mpls_field delimiter mpls_param_list { }
685 mpls_tc
686 : K_TC { }
687 | K_EXP { }
690 mpls_field
691 : K_LABEL skip_white '=' skip_white number
692 { proto_field_set_be32(hdr, MPLS_LABEL, $5); }
693 | mpls_tc skip_white '=' skip_white number
694 { proto_field_set_be32(hdr, MPLS_TC, $5); }
695 | K_LAST skip_white '=' skip_white number
696 { proto_field_set_be32(hdr, MPLS_LAST, $5); }
697 | K_TTL skip_white '=' skip_white number
698 { proto_field_set_be32(hdr, MPLS_TTL, $5); }
701 arp_proto
702 : arp '(' arp_param_list ')' { }
705 arp_param_list
706 : { }
707 | arp_field { }
708 | arp_field delimiter arp_param_list { }
711 arp_field
712 : K_OPER skip_white '=' skip_white K_REQUEST
713 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
714 | K_OPER skip_white '=' skip_white K_REPLY
715 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
716 | K_OPER skip_white '=' skip_white number
717 { proto_field_set_be16(hdr, ARP_OPER, $5); }
718 | K_REQUEST
719 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
720 | K_REPLY
721 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
722 | K_HTYPE skip_white '=' skip_white number
723 { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
724 | K_PTYPE skip_white '=' skip_white number
725 { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
726 | K_SHA skip_white '=' skip_white mac
727 { proto_field_set_bytes(hdr, ARP_SHA, $5); }
728 | K_THA skip_white '=' skip_white mac
729 { proto_field_set_bytes(hdr, ARP_THA, $5); }
730 | K_SPA skip_white '=' skip_white ip4_addr
731 { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
732 | K_TPA skip_white '=' skip_white ip4_addr
733 { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
736 : K_ARP { proto_add(PROTO_ARP); }
739 ip4_proto
740 : ip4 '(' ip4_param_list ')' { }
743 ip4_param_list
744 : { }
745 | ip4_field { }
746 | ip4_field delimiter ip4_param_list { }
749 ip4_field
750 : K_VER skip_white '=' skip_white number
751 { proto_field_set_u8(hdr, IP4_VER, $5); }
752 | K_IHL skip_white '=' skip_white number
753 { proto_field_set_u8(hdr, IP4_IHL, $5); }
754 | K_DADDR skip_white '=' skip_white ip4_addr
755 { proto_field_set_u32(hdr, IP4_DADDR, $5.s_addr); }
756 | K_SADDR skip_white '=' skip_white ip4_addr
757 { proto_field_set_u32(hdr, IP4_SADDR, $5.s_addr); }
758 | K_PROT skip_white '=' skip_white number
759 { proto_field_set_u8(hdr, IP4_PROTO, $5); }
760 | K_TTL skip_white '=' skip_white number
761 { proto_field_set_u8(hdr, IP4_TTL, $5); }
762 | K_DSCP skip_white '=' skip_white number
763 { proto_field_set_u8(hdr, IP4_DSCP, $5); }
764 | K_ECN skip_white '=' skip_white number
765 { proto_field_set_u8(hdr, IP4_ECN, $5); }
766 | K_TOS skip_white '=' skip_white number
767 { proto_field_set_u8(hdr, IP4_TOS, $5); }
768 | K_LEN skip_white '=' skip_white number
769 { proto_field_set_be16(hdr, IP4_LEN, $5); }
770 | K_ID skip_white '=' skip_white number
771 { proto_field_set_be16(hdr, IP4_ID, $5); }
772 | K_FLAGS skip_white '=' skip_white number
773 { proto_field_set_be16(hdr, IP4_FLAGS, $5); }
774 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
775 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
776 | K_FRAG skip_white '=' skip_white number
777 { proto_field_set_be16(hdr, IP4_FRAG_OFFS, $5); }
778 | K_CSUM skip_white '=' skip_white number
779 { proto_field_set_be16(hdr, IP4_CSUM, $5); }
783 : K_IP4 { proto_add(PROTO_IP4); }
786 ip6_proto
787 : ip6 '(' ip6_param_list ')' { }
790 ip6_param_list
791 : { }
792 | ip6_field { }
793 | ip6_field delimiter ip6_param_list { }
796 ip6_hop_limit
797 : K_HOP_LIMIT { }
798 | K_TTL { }
801 ip6_field
802 : K_VER skip_white '=' skip_white number
803 { proto_field_set_be32(hdr, IP6_VER, $5); }
804 | K_TC skip_white '=' skip_white number
805 { proto_field_set_be32(hdr, IP6_CLASS, $5); }
806 | K_FLOW skip_white '=' skip_white number
807 { proto_field_set_be32(hdr, IP6_FLOW_LBL, $5); }
808 | K_LEN skip_white '=' skip_white number
809 { proto_field_set_be16(hdr, IP6_LEN, $5); }
810 | K_NEXT_HDR skip_white '=' skip_white number
811 { proto_field_set_u8(hdr, IP6_NEXT_HDR, $5); }
812 | ip6_hop_limit skip_white '=' skip_white number
813 { proto_field_set_u8(hdr, IP6_HOP_LIMIT, $5); }
814 | K_SADDR skip_white '=' skip_white ip6_addr
815 { proto_field_set_bytes(hdr, IP6_SADDR, (uint8_t *)&($5.s6_addr)); }
816 | K_DADDR skip_white '=' skip_white ip6_addr
817 { proto_field_set_bytes(hdr, IP6_DADDR, (uint8_t *)&($5.s6_addr)); }
821 : K_IP6 { proto_add(PROTO_IP6); }
824 icmp4_proto
825 : icmp4 '(' icmp4_param_list ')' { }
828 icmp4_param_list
829 : { }
830 | icmp4_field { }
831 | icmp4_field delimiter icmp4_param_list { }
834 icmp4_field
835 : K_TYPE skip_white '=' skip_white number
836 { proto_field_set_u8(hdr, ICMPV4_TYPE, $5); }
837 | K_CODE skip_white '=' skip_white number
838 { proto_field_set_u8(hdr, ICMPV4_CODE, $5); }
839 | K_ID skip_white '=' skip_white number
840 { proto_field_set_be16(hdr, ICMPV4_ID, $5); }
841 | K_SEQ skip_white '=' skip_white number
842 { proto_field_set_be16(hdr, ICMPV4_SEQ, $5); }
843 | K_MTU skip_white '=' skip_white number
844 { proto_field_set_be16(hdr, ICMPV4_MTU, $5); }
845 | K_ADDR skip_white '=' skip_white ip4_addr
846 { proto_field_set_u32(hdr, ICMPV4_REDIR_ADDR, $5.s_addr); }
847 | K_ECHO_REQUEST
848 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
849 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
850 | K_ECHO_REPLY
851 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
852 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
855 icmp4
856 : K_ICMP4 { proto_add(PROTO_ICMP4); }
859 icmpv6_proto
860 : icmp6 '(' icmp6_param_list ')' { }
862 icmp6_param_list
863 : { }
864 | icmp6_field { }
865 | icmp6_field delimiter icmp6_param_list { }
868 icmp6_field
869 : K_TYPE skip_white '=' skip_white number
870 { proto_field_set_u8(hdr, ICMPV6_TYPE, $5); }
871 | K_TYPE skip_white '=' K_ECHO_REQUEST
872 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
873 | K_ECHO_REQUEST
874 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
875 | K_TYPE skip_white '=' K_ECHO_REPLY
876 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
877 | K_ECHO_REPLY
878 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
879 | K_CODE skip_white '=' skip_white number
880 { proto_field_set_u8(hdr, ICMPV6_CODE, $5); }
881 | K_CSUM skip_white '=' skip_white number
882 { proto_field_set_be16(hdr, ICMPV6_CSUM, $5); }
885 icmp6
886 : K_ICMP6 { proto_add(PROTO_ICMP6); }
889 udp_proto
890 : udp '(' udp_param_list ')' { }
893 udp_param_list
894 : { }
895 | udp_field { }
896 | udp_field delimiter udp_param_list { }
899 udp_field
900 : K_SPORT skip_white '=' skip_white number
901 { proto_field_set_be16(hdr, UDP_SPORT, $5); }
902 | K_DPORT skip_white '=' skip_white number
903 { proto_field_set_be16(hdr, UDP_DPORT, $5); }
904 | K_LEN skip_white '=' skip_white number
905 { proto_field_set_be16(hdr, UDP_LEN, $5); }
906 | K_CSUM skip_white '=' skip_white number
907 { proto_field_set_be16(hdr, UDP_CSUM, $5); }
911 : K_UDP { proto_add(PROTO_UDP); }
914 tcp_proto
915 : tcp '(' tcp_param_list ')' { }
918 tcp_param_list
919 : { }
920 | tcp_field { }
921 | tcp_field delimiter tcp_param_list { }
924 tcp_field
925 : K_SPORT skip_white '=' skip_white number
926 { proto_field_set_be16(hdr, TCP_SPORT, $5); }
927 | K_DPORT skip_white '=' skip_white number
928 { proto_field_set_be16(hdr, TCP_DPORT, $5); }
929 | K_SEQ skip_white '=' skip_white number
930 { proto_field_set_be32(hdr, TCP_SEQ, $5); }
931 | K_ACK_SEQ skip_white '=' skip_white number
932 { proto_field_set_be32(hdr, TCP_ACK_SEQ, $5); }
933 | K_DOFF skip_white '=' skip_white number
934 { proto_field_set_be16(hdr, TCP_DOFF, $5); }
935 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
936 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
937 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
938 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
939 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
940 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
941 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
942 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
943 | K_WINDOW skip_white '=' skip_white number
944 { proto_field_set_be16(hdr, TCP_WINDOW, $5); }
945 | K_CSUM skip_white '=' skip_white number
946 { proto_field_set_be16(hdr, TCP_CSUM, $5); }
947 | K_URG_PTR skip_white '=' skip_white number
948 { proto_field_set_be16(hdr, TCP_URG_PTR, $5); }
952 : K_TCP { proto_add(PROTO_TCP); }
957 static void finalize_packet(void)
959 /* XXX hack ... we allocated one packet pointer too much */
960 plen--;
961 dlen--;
964 static void dump_conf(void)
966 size_t i, j;
968 for (i = 0; i < plen; ++i) {
969 printf("[%zu] pkt\n", i);
970 printf(" len %zu cnts %zu rnds %zu\n",
971 packets[i].len,
972 packet_dyn[i].clen,
973 packet_dyn[i].rlen);
975 printf(" payload ");
976 for (j = 0; j < packets[i].len; ++j)
977 printf("%02x ", packets[i].payload[j]);
978 printf("\n");
980 for (j = 0; j < packet_dyn[i].clen; ++j)
981 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
982 packet_dyn[i].cnt[j].min,
983 packet_dyn[i].cnt[j].max,
984 packet_dyn[i].cnt[j].inc,
985 (intmax_t)packet_dyn[i].cnt[j].off,
986 packet_dyn[i].cnt[j].type == TYPE_INC ?
987 "inc" : "dec");
989 for (j = 0; j < packet_dyn[i].rlen; ++j)
990 printf(" rnd%zu off %jd\n", j,
991 (intmax_t)packet_dyn[i].rnd[j].off);
995 void cleanup_packets(void)
997 size_t i;
999 for (i = 0; i < plen; ++i) {
1000 if (packets[i].len > 0)
1001 xfree(packets[i].payload);
1004 free(packets);
1006 for (i = 0; i < dlen; ++i) {
1007 free(packet_dyn[i].cnt);
1008 free(packet_dyn[i].rnd);
1011 free(packet_dyn);
1014 void compile_packets(char *file, bool verbose, unsigned int cpu,
1015 bool invoke_cpp, char *const cpp_argv[])
1017 char tmp_file[128];
1018 int ret = -1;
1020 memset(tmp_file, 0, sizeof(tmp_file));
1021 our_cpu = cpu;
1023 if (invoke_cpp) {
1024 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1025 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1026 goto err;
1028 file = tmp_file;
1031 if (!strncmp("-", file, strlen("-")))
1032 yyin = stdin;
1033 else
1034 yyin = fopen(file, "r");
1035 if (!yyin) {
1036 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1037 goto err;
1040 realloc_packet();
1041 if (yyparse() != 0)
1042 goto err;
1043 finalize_packet();
1045 if (our_cpu == 0 && verbose)
1046 dump_conf();
1048 ret = 0;
1049 err:
1050 if (yyin && yyin != stdin)
1051 fclose(yyin);
1053 if (invoke_cpp)
1054 unlink(tmp_file);
1055 if (ret)
1056 die();
1059 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1061 int ret = 1;
1063 our_cpu = cpu;
1064 realloc_packet();
1066 yy_scan_string(str);
1067 if (yyparse() != 0)
1068 goto err;
1070 finalize_packet();
1071 if (our_cpu == 0 && verbose)
1072 dump_conf();
1074 ret = 0;
1075 err:
1076 yylex_destroy();
1078 if (ret)
1079 die();
1082 void yyerror(const char *err)
1084 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);