trafgen: proto: Move proto headers into packet
[netsniff-ng.git] / trafgen_parser.y
blob035d9c1cca70a79ec8c51cb789196bca26dcdda7
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 uint32_t current_packet_id(void)
158 return packet_last;
161 struct packet *packet_get(uint32_t id)
163 return &packets[id];
166 static void set_byte(uint8_t val)
168 struct packet *pkt = &packets[packet_last];
170 if (test_ignore())
171 return;
173 pkt->len++;
174 pkt->payload = xrealloc(pkt->payload, pkt->len);
175 pkt->payload[payload_last] = val;
178 static void set_multi_byte(uint8_t *s, size_t len)
180 size_t i;
182 for (i = 0; i < len; ++i)
183 set_byte(s[i]);
186 void set_fill(uint8_t val, size_t len)
188 size_t i;
189 struct packet *pkt = &packets[packet_last];
191 if (test_ignore())
192 return;
194 pkt->len += len;
195 pkt->payload = xrealloc(pkt->payload, pkt->len);
196 for (i = 0; i < len; ++i)
197 pkt->payload[payload_last - i] = val;
200 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
202 struct packet *pkt = &packets[packet_last];
203 struct packet_dyn *pktd = &packet_dyn[packetd_last];
205 pkt->len += 2;
206 pkt->payload = xrealloc(pkt->payload, pkt->len);
208 pktd->slen++;
209 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
211 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
214 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
216 struct packet *pkt = &packets[packet_last];
217 uint16_t sum;
218 uint8_t *psum;
220 sum = htons(calc_csum(pkt->payload + from, to - from));
221 psum = (uint8_t *) &sum;
223 set_byte(psum[0]);
224 set_byte(psum[1]);
227 static inline bool is_dynamic_csum(enum csum which)
229 switch (which) {
230 case CSUM_UDP:
231 case CSUM_TCP:
232 case CSUM_UDP6:
233 case CSUM_TCP6:
234 return true;
235 default:
236 return false;
240 static void set_csum16(size_t from, size_t to, enum csum which)
242 struct packet *pkt = &packets[packet_last];
243 struct packet_dyn *pktd = &packet_dyn[packetd_last];
245 if (test_ignore())
246 return;
248 if (to < from) {
249 size_t tmp = to;
251 to = from;
252 from = tmp;
255 bug_on(!(from < to));
257 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
258 __set_csum16_dynamic(from, to, which);
259 else
260 __set_csum16_static(from, to, which);
263 static void set_rnd(size_t len)
265 size_t i;
266 struct packet *pkt = &packets[packet_last];
268 if (test_ignore())
269 return;
271 pkt->len += len;
272 pkt->payload = xrealloc(pkt->payload, pkt->len);
273 for (i = 0; i < len; ++i)
274 pkt->payload[payload_last - i] = (uint8_t) rand();
277 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
279 size_t i;
280 struct packet *pkt = &packets[packet_last];
282 if (test_ignore())
283 return;
285 pkt->len += len;
286 pkt->payload = xrealloc(pkt->payload, pkt->len);
287 for (i = 0; i < len; ++i) {
288 off_t off = len - 1 - i;
290 pkt->payload[payload_last - off] = start;
291 start += stepping;
295 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
297 size_t i;
298 struct packet *pkt = &packets[packet_last];
300 if (test_ignore())
301 return;
303 pkt->len += len;
304 pkt->payload = xrealloc(pkt->payload, pkt->len);
305 for (i = 0; i < len; ++i) {
306 int off = len - 1 - i;
308 pkt->payload[payload_last - off] = start;
309 start -= stepping;
313 static void set_dynamic_rnd(void)
315 struct packet *pkt = &packets[packet_last];
316 struct packet_dyn *pktd = &packet_dyn[packetd_last];
318 if (test_ignore())
319 return;
321 pkt->len++;
322 pkt->payload = xrealloc(pkt->payload, pkt->len);
324 pktd->rlen++;
325 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
327 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
330 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
331 int type)
333 struct packet *pkt = &packets[packet_last];
334 struct packet_dyn *pktd = &packet_dyn[packetd_last];
336 if (test_ignore())
337 return;
339 pkt->len++;
340 pkt->payload = xrealloc(pkt->payload, pkt->len);
342 pktd->clen++;
343 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
345 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
348 static void proto_add(enum proto_id pid)
350 hdr = proto_header_init(pid);
355 %union {
356 struct in_addr ip4_addr;
357 struct in6_addr ip6_addr;
358 long long int number;
359 uint8_t bytes[256];
360 char *str;
363 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
364 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
366 %token K_DADDR K_SADDR K_ETYPE K_TYPE
367 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
368 %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
369 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
370 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
371 %token K_SPORT K_DPORT
372 %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
373 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
374 %token K_LABEL K_TC K_LAST K_EXP
376 %token K_ADDR K_MTU
378 %token K_ETH
379 %token K_VLAN K_MPLS
380 %token K_ARP
381 %token K_IP4 K_IP6
382 %token K_ICMP4 K_ICMP6
383 %token K_UDP K_TCP
385 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
387 %token number string mac ip4_addr ip6_addr
389 %type <number> number expression
390 %type <str> string
391 %type <bytes> mac
392 %type <ip4_addr> ip4_addr
393 %type <ip6_addr> ip6_addr
395 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
399 packets
400 : { }
401 | packets packet { }
402 | packets inline_comment { }
403 | packets K_WHITE { }
406 inline_comment
407 : K_COMMENT { }
410 cpu_delim
411 : ':' { }
412 | '-' { }
415 delimiter_nowhite
416 : ',' { }
417 | ',' K_WHITE { }
420 noenforce_white
421 : { }
422 | K_WHITE { }
423 | delimiter_nowhite { }
426 skip_white
427 : { }
428 | K_WHITE { }
430 packet
431 : '{' noenforce_white payload noenforce_white '}' {
432 min_cpu = max_cpu = -1;
434 proto_packet_finish();
436 realloc_packet();
438 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
439 min_cpu = $3;
440 max_cpu = $5;
442 if (min_cpu > max_cpu) {
443 int tmp = min_cpu;
445 min_cpu = max_cpu;
446 max_cpu = tmp;
449 proto_packet_finish();
451 realloc_packet();
453 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
454 min_cpu = max_cpu = $3;
456 proto_packet_finish();
458 realloc_packet();
462 payload
463 : elem { }
464 | payload elem_delimiter { }
467 delimiter
468 : delimiter_nowhite { }
469 | K_WHITE { }
472 elem_delimiter
473 : delimiter elem { }
476 elem
477 : number { set_byte((uint8_t) $1); }
478 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
479 | fill { }
480 | rnd { }
481 | drnd { }
482 | seqinc { }
483 | seqdec { }
484 | dinc { }
485 | ddec { }
486 | csum { }
487 | const { }
488 | proto { proto_header_finish(hdr); }
489 | inline_comment { }
492 expression
493 : number
494 { $$ = $1; }
495 | expression '+' expression
496 { $$ = $1 + $3; }
497 | expression '-' expression
498 { $$ = $1 - $3; }
499 | expression '*' expression
500 { $$ = $1 * $3; }
501 | expression '/' expression
502 { $$ = $1 / $3; }
503 | expression '%' expression
504 { $$ = $1 % $3; }
505 | expression '&' expression
506 { $$ = $1 & $3; }
507 | expression '|' expression
508 { $$ = $1 | $3; }
509 | expression '^' expression
510 { $$ = $1 ^ $3; }
511 | expression '<' '<' expression
512 { $$ = $1 << $4; }
513 | expression '>' '>' expression
514 { $$ = $1 >> $4; }
515 | '-' expression
516 { $$ = -1 * $2; }
517 | '(' expression ')'
518 { $$ = $2;}
521 fill
522 : K_FILL '(' number delimiter number ')'
523 { set_fill($3, $5); }
526 const
527 : K_CONST8 '(' expression ')'
528 { set_byte((uint8_t) $3); }
529 | K_CONST16 '(' expression ')' {
530 uint16_t __c = cpu_to_be16((uint16_t) $3);
532 set_multi_byte((uint8_t *) &__c, sizeof(__c));
534 | K_CONST32 '(' expression ')' {
535 uint32_t __c = cpu_to_be32((uint32_t) $3);
537 set_multi_byte((uint8_t *) &__c, sizeof(__c));
539 | K_CONST64 '(' expression ')' {
540 uint64_t __c = cpu_to_be64((uint64_t) $3);
542 set_multi_byte((uint8_t *) &__c, sizeof(__c));
547 : K_RND '(' number ')'
548 { set_rnd($3); }
551 csum
552 : K_CSUMIP '(' number delimiter number ')'
553 { set_csum16($3, $5, CSUM_IP); }
554 | K_CSUMTCP '(' number delimiter number ')'
555 { set_csum16($3, $5, CSUM_TCP); }
556 | K_CSUMUDP '(' number delimiter number ')'
557 { set_csum16($3, $5, CSUM_UDP); }
558 | K_CSUMTCP6 '(' number delimiter number ')'
559 { set_csum16($3, $5, CSUM_TCP6); }
560 | K_CSUMUDP6 '(' number delimiter number ')'
561 { set_csum16($3, $5, CSUM_UDP6); }
564 seqinc
565 : K_SEQINC '(' number delimiter number ')'
566 { set_sequential_inc($3, $5, 1); }
567 | K_SEQINC '(' number delimiter number delimiter number ')'
568 { set_sequential_inc($3, $5, $7); }
571 seqdec
572 : K_SEQDEC '(' number delimiter number ')'
573 { set_sequential_dec($3, $5, 1); }
574 | K_SEQDEC '(' number delimiter number delimiter number ')'
575 { set_sequential_dec($3, $5, $7); }
578 drnd
579 : K_DRND '(' ')'
580 { set_dynamic_rnd(); }
581 | K_DRND '(' number ')'
583 int i, max = $3;
584 for (i = 0; i < max; ++i)
585 set_dynamic_rnd();
589 dinc
590 : K_DINC '(' number delimiter number ')'
591 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
592 | K_DINC '(' number delimiter number delimiter number ')'
593 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
596 ddec
597 : K_DDEC '(' number delimiter number ')'
598 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
599 | K_DDEC '(' number delimiter number delimiter number ')'
600 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
603 proto
604 : eth_proto { }
605 | vlan_proto { }
606 | mpls_proto { }
607 | arp_proto { }
608 | ip4_proto { }
609 | ip6_proto { }
610 | icmp4_proto { }
611 | icmpv6_proto { }
612 | udp_proto { }
613 | tcp_proto { }
616 eth_proto
617 : eth '(' eth_param_list ')' { }
621 : K_ETH { proto_add(PROTO_ETH); }
624 eth_param_list
625 : { }
626 | eth_field { }
627 | eth_field delimiter eth_param_list { }
630 eth_type
631 : K_ETYPE { }
632 | K_TYPE { }
633 | K_PROT { }
636 eth_field
637 : K_DADDR skip_white '=' skip_white mac
638 { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
639 | K_SADDR skip_white '=' skip_white mac
640 { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
641 | eth_type skip_white '=' skip_white number
642 { proto_field_set_be16(hdr, ETH_TYPE, $5); }
645 vlan_proto
646 : vlan '(' vlan_param_list ')' { }
649 vlan
650 : K_VLAN { proto_add(PROTO_VLAN); }
653 vlan_param_list
654 : { }
655 | vlan_field { }
656 | vlan_field delimiter vlan_param_list { }
659 vlan_type
660 : K_TPID { }
661 | K_PROT
664 vlan_field
665 : vlan_type skip_white '=' skip_white number
666 { proto_field_set_be16(hdr, VLAN_TPID, $5); }
667 | K_1Q
668 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
669 | K_1AD
670 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
671 | K_TCI skip_white '=' skip_white number
672 { proto_field_set_be16(hdr, VLAN_TCI, $5); }
673 | K_PCP skip_white '=' skip_white number
674 { proto_field_set_be16(hdr, VLAN_PCP, $5); }
675 | K_DEI skip_white '=' skip_white number
676 { proto_field_set_be16(hdr, VLAN_DEI, $5); }
677 | K_ID skip_white '=' skip_white number
678 { proto_field_set_be16(hdr, VLAN_VID, $5); }
681 mpls_proto
682 : mpls '(' mpls_param_list ')' { }
685 mpls
686 : K_MPLS { proto_add(PROTO_MPLS); }
689 mpls_param_list
690 : { }
691 | mpls_field { }
692 | mpls_field delimiter mpls_param_list { }
695 mpls_tc
696 : K_TC { }
697 | K_EXP { }
700 mpls_field
701 : K_LABEL skip_white '=' skip_white number
702 { proto_field_set_be32(hdr, MPLS_LABEL, $5); }
703 | mpls_tc skip_white '=' skip_white number
704 { proto_field_set_be32(hdr, MPLS_TC, $5); }
705 | K_LAST skip_white '=' skip_white number
706 { proto_field_set_be32(hdr, MPLS_LAST, $5); }
707 | K_TTL skip_white '=' skip_white number
708 { proto_field_set_be32(hdr, MPLS_TTL, $5); }
711 arp_proto
712 : arp '(' arp_param_list ')' { }
715 arp_param_list
716 : { }
717 | arp_field { }
718 | arp_field delimiter arp_param_list { }
721 arp_field
722 : K_OPER skip_white '=' skip_white K_REQUEST
723 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
724 | K_OPER skip_white '=' skip_white K_REPLY
725 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
726 | K_OPER skip_white '=' skip_white number
727 { proto_field_set_be16(hdr, ARP_OPER, $5); }
728 | K_REQUEST
729 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
730 | K_REPLY
731 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
732 | K_HTYPE skip_white '=' skip_white number
733 { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
734 | K_PTYPE skip_white '=' skip_white number
735 { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
736 | K_SHA skip_white '=' skip_white mac
737 { proto_field_set_bytes(hdr, ARP_SHA, $5); }
738 | K_THA skip_white '=' skip_white mac
739 { proto_field_set_bytes(hdr, ARP_THA, $5); }
740 | K_SPA skip_white '=' skip_white ip4_addr
741 { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
742 | K_TPA skip_white '=' skip_white ip4_addr
743 { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
746 : K_ARP { proto_add(PROTO_ARP); }
749 ip4_proto
750 : ip4 '(' ip4_param_list ')' { }
753 ip4_param_list
754 : { }
755 | ip4_field { }
756 | ip4_field delimiter ip4_param_list { }
759 ip4_field
760 : K_VER skip_white '=' skip_white number
761 { proto_field_set_u8(hdr, IP4_VER, $5); }
762 | K_IHL skip_white '=' skip_white number
763 { proto_field_set_u8(hdr, IP4_IHL, $5); }
764 | K_DADDR skip_white '=' skip_white ip4_addr
765 { proto_field_set_u32(hdr, IP4_DADDR, $5.s_addr); }
766 | K_SADDR skip_white '=' skip_white ip4_addr
767 { proto_field_set_u32(hdr, IP4_SADDR, $5.s_addr); }
768 | K_PROT skip_white '=' skip_white number
769 { proto_field_set_u8(hdr, IP4_PROTO, $5); }
770 | K_TTL skip_white '=' skip_white number
771 { proto_field_set_u8(hdr, IP4_TTL, $5); }
772 | K_DSCP skip_white '=' skip_white number
773 { proto_field_set_u8(hdr, IP4_DSCP, $5); }
774 | K_ECN skip_white '=' skip_white number
775 { proto_field_set_u8(hdr, IP4_ECN, $5); }
776 | K_TOS skip_white '=' skip_white number
777 { proto_field_set_u8(hdr, IP4_TOS, $5); }
778 | K_LEN skip_white '=' skip_white number
779 { proto_field_set_be16(hdr, IP4_LEN, $5); }
780 | K_ID skip_white '=' skip_white number
781 { proto_field_set_be16(hdr, IP4_ID, $5); }
782 | K_FLAGS skip_white '=' skip_white number
783 { proto_field_set_be16(hdr, IP4_FLAGS, $5); }
784 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
785 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
786 | K_FRAG skip_white '=' skip_white number
787 { proto_field_set_be16(hdr, IP4_FRAG_OFFS, $5); }
788 | K_CSUM skip_white '=' skip_white number
789 { proto_field_set_be16(hdr, IP4_CSUM, $5); }
793 : K_IP4 { proto_add(PROTO_IP4); }
796 ip6_proto
797 : ip6 '(' ip6_param_list ')' { }
800 ip6_param_list
801 : { }
802 | ip6_field { }
803 | ip6_field delimiter ip6_param_list { }
806 ip6_hop_limit
807 : K_HOP_LIMIT { }
808 | K_TTL { }
811 ip6_field
812 : K_VER skip_white '=' skip_white number
813 { proto_field_set_be32(hdr, IP6_VER, $5); }
814 | K_TC skip_white '=' skip_white number
815 { proto_field_set_be32(hdr, IP6_CLASS, $5); }
816 | K_FLOW skip_white '=' skip_white number
817 { proto_field_set_be32(hdr, IP6_FLOW_LBL, $5); }
818 | K_LEN skip_white '=' skip_white number
819 { proto_field_set_be16(hdr, IP6_LEN, $5); }
820 | K_NEXT_HDR skip_white '=' skip_white number
821 { proto_field_set_u8(hdr, IP6_NEXT_HDR, $5); }
822 | ip6_hop_limit skip_white '=' skip_white number
823 { proto_field_set_u8(hdr, IP6_HOP_LIMIT, $5); }
824 | K_SADDR skip_white '=' skip_white ip6_addr
825 { proto_field_set_bytes(hdr, IP6_SADDR, (uint8_t *)&($5.s6_addr)); }
826 | K_DADDR skip_white '=' skip_white ip6_addr
827 { proto_field_set_bytes(hdr, IP6_DADDR, (uint8_t *)&($5.s6_addr)); }
831 : K_IP6 { proto_add(PROTO_IP6); }
834 icmp4_proto
835 : icmp4 '(' icmp4_param_list ')' { }
838 icmp4_param_list
839 : { }
840 | icmp4_field { }
841 | icmp4_field delimiter icmp4_param_list { }
844 icmp4_field
845 : K_TYPE skip_white '=' skip_white number
846 { proto_field_set_u8(hdr, ICMPV4_TYPE, $5); }
847 | K_CODE skip_white '=' skip_white number
848 { proto_field_set_u8(hdr, ICMPV4_CODE, $5); }
849 | K_ID skip_white '=' skip_white number
850 { proto_field_set_be16(hdr, ICMPV4_ID, $5); }
851 | K_SEQ skip_white '=' skip_white number
852 { proto_field_set_be16(hdr, ICMPV4_SEQ, $5); }
853 | K_MTU skip_white '=' skip_white number
854 { proto_field_set_be16(hdr, ICMPV4_MTU, $5); }
855 | K_ADDR skip_white '=' skip_white ip4_addr
856 { proto_field_set_u32(hdr, ICMPV4_REDIR_ADDR, $5.s_addr); }
857 | K_ECHO_REQUEST
858 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
859 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
860 | K_ECHO_REPLY
861 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
862 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
865 icmp4
866 : K_ICMP4 { proto_add(PROTO_ICMP4); }
869 icmpv6_proto
870 : icmp6 '(' icmp6_param_list ')' { }
872 icmp6_param_list
873 : { }
874 | icmp6_field { }
875 | icmp6_field delimiter icmp6_param_list { }
878 icmp6_field
879 : K_TYPE skip_white '=' skip_white number
880 { proto_field_set_u8(hdr, ICMPV6_TYPE, $5); }
881 | K_TYPE skip_white '=' K_ECHO_REQUEST
882 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
883 | K_ECHO_REQUEST
884 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
885 | K_TYPE skip_white '=' K_ECHO_REPLY
886 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
887 | K_ECHO_REPLY
888 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
889 | K_CODE skip_white '=' skip_white number
890 { proto_field_set_u8(hdr, ICMPV6_CODE, $5); }
891 | K_CSUM skip_white '=' skip_white number
892 { proto_field_set_be16(hdr, ICMPV6_CSUM, $5); }
895 icmp6
896 : K_ICMP6 { proto_add(PROTO_ICMP6); }
899 udp_proto
900 : udp '(' udp_param_list ')' { }
903 udp_param_list
904 : { }
905 | udp_field { }
906 | udp_field delimiter udp_param_list { }
909 udp_field
910 : K_SPORT skip_white '=' skip_white number
911 { proto_field_set_be16(hdr, UDP_SPORT, $5); }
912 | K_DPORT skip_white '=' skip_white number
913 { proto_field_set_be16(hdr, UDP_DPORT, $5); }
914 | K_LEN skip_white '=' skip_white number
915 { proto_field_set_be16(hdr, UDP_LEN, $5); }
916 | K_CSUM skip_white '=' skip_white number
917 { proto_field_set_be16(hdr, UDP_CSUM, $5); }
921 : K_UDP { proto_add(PROTO_UDP); }
924 tcp_proto
925 : tcp '(' tcp_param_list ')' { }
928 tcp_param_list
929 : { }
930 | tcp_field { }
931 | tcp_field delimiter tcp_param_list { }
934 tcp_field
935 : K_SPORT skip_white '=' skip_white number
936 { proto_field_set_be16(hdr, TCP_SPORT, $5); }
937 | K_DPORT skip_white '=' skip_white number
938 { proto_field_set_be16(hdr, TCP_DPORT, $5); }
939 | K_SEQ skip_white '=' skip_white number
940 { proto_field_set_be32(hdr, TCP_SEQ, $5); }
941 | K_ACK_SEQ skip_white '=' skip_white number
942 { proto_field_set_be32(hdr, TCP_ACK_SEQ, $5); }
943 | K_DOFF skip_white '=' skip_white number
944 { proto_field_set_be16(hdr, TCP_DOFF, $5); }
945 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
946 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
947 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
948 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
949 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
950 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
951 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
952 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
953 | K_WINDOW skip_white '=' skip_white number
954 { proto_field_set_be16(hdr, TCP_WINDOW, $5); }
955 | K_CSUM skip_white '=' skip_white number
956 { proto_field_set_be16(hdr, TCP_CSUM, $5); }
957 | K_URG_PTR skip_white '=' skip_white number
958 { proto_field_set_be16(hdr, TCP_URG_PTR, $5); }
962 : K_TCP { proto_add(PROTO_TCP); }
967 static void finalize_packet(void)
969 /* XXX hack ... we allocated one packet pointer too much */
970 plen--;
971 dlen--;
974 static void dump_conf(void)
976 size_t i, j;
978 for (i = 0; i < plen; ++i) {
979 printf("[%zu] pkt\n", i);
980 printf(" len %zu cnts %zu rnds %zu\n",
981 packets[i].len,
982 packet_dyn[i].clen,
983 packet_dyn[i].rlen);
985 printf(" payload ");
986 for (j = 0; j < packets[i].len; ++j)
987 printf("%02x ", packets[i].payload[j]);
988 printf("\n");
990 for (j = 0; j < packet_dyn[i].clen; ++j)
991 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
992 packet_dyn[i].cnt[j].min,
993 packet_dyn[i].cnt[j].max,
994 packet_dyn[i].cnt[j].inc,
995 (intmax_t)packet_dyn[i].cnt[j].off,
996 packet_dyn[i].cnt[j].type == TYPE_INC ?
997 "inc" : "dec");
999 for (j = 0; j < packet_dyn[i].rlen; ++j)
1000 printf(" rnd%zu off %jd\n", j,
1001 (intmax_t)packet_dyn[i].rnd[j].off);
1005 void cleanup_packets(void)
1007 size_t i, j;
1009 for (i = 0; i < plen; ++i) {
1010 struct packet *pkt = &packets[i];
1012 if (pkt->len > 0)
1013 xfree(pkt->payload);
1015 for (j = 0; j < pkt->headers_count; j++) {
1016 struct proto_hdr *hdr = pkt->headers[j];
1018 if (hdr->fields)
1019 xfree(hdr->fields);
1020 xfree(hdr);
1024 free(packets);
1026 for (i = 0; i < dlen; ++i) {
1027 free(packet_dyn[i].cnt);
1028 free(packet_dyn[i].rnd);
1031 free(packet_dyn);
1034 void compile_packets(char *file, bool verbose, unsigned int cpu,
1035 bool invoke_cpp, char *const cpp_argv[])
1037 char tmp_file[128];
1038 int ret = -1;
1040 memset(tmp_file, 0, sizeof(tmp_file));
1041 our_cpu = cpu;
1043 if (invoke_cpp) {
1044 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1045 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1046 goto err;
1048 file = tmp_file;
1051 if (!strncmp("-", file, strlen("-")))
1052 yyin = stdin;
1053 else
1054 yyin = fopen(file, "r");
1055 if (!yyin) {
1056 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1057 goto err;
1060 realloc_packet();
1061 if (yyparse() != 0)
1062 goto err;
1063 finalize_packet();
1065 if (our_cpu == 0 && verbose)
1066 dump_conf();
1068 ret = 0;
1069 err:
1070 if (yyin && yyin != stdin)
1071 fclose(yyin);
1073 if (invoke_cpp)
1074 unlink(tmp_file);
1075 if (ret)
1076 die();
1079 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1081 int ret = 1;
1083 our_cpu = cpu;
1084 realloc_packet();
1086 yy_scan_string(str);
1087 if (yyparse() != 0)
1088 goto err;
1090 finalize_packet();
1091 if (our_cpu == 0 && verbose)
1092 dump_conf();
1094 ret = 0;
1095 err:
1096 yylex_destroy();
1098 if (ret)
1099 die();
1102 void yyerror(const char *err)
1104 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);