trafgen: parser: Split [e]type to separate keywords
[netsniff-ng.git] / trafgen_parser.y
blob19b26e6e24018db67c53f90f372f0dafbbe3b221
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/if_ether.h>
23 #include <linux/icmpv6.h>
25 #include "xmalloc.h"
26 #include "trafgen_parser.tab.h"
27 #include "trafgen_conf.h"
28 #include "trafgen_proto.h"
29 #include "trafgen_l2.h"
30 #include "trafgen_l3.h"
31 #include "trafgen_l4.h"
32 #include "built_in.h"
33 #include "die.h"
34 #include "str.h"
35 #include "csum.h"
36 #include "cpp.h"
38 #define YYERROR_VERBOSE 0
39 #define YYDEBUG 0
40 #define YYENABLE_NLS 1
41 #define YYLTYPE_IS_TRIVIAL 1
42 #define ENABLE_NLS 1
44 extern FILE *yyin;
45 extern int yylex(void);
46 extern void yy_scan_string(char *);
47 extern void yylex_destroy();
48 extern void yyerror(const char *);
49 extern int yylineno;
50 extern char *yytext;
52 extern struct packet *packets;
53 extern size_t plen;
55 #define packet_last (plen - 1)
57 #define payload_last (packets[packet_last].len - 1)
59 extern struct packet_dyn *packet_dyn;
60 extern size_t dlen;
62 #define packetd_last (dlen - 1)
64 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
65 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
66 #define packetds_last (packet_dyn[packetd_last].slen - 1)
68 static int our_cpu, min_cpu = -1, max_cpu = -1;
70 static struct proto_hdr *hdr;
72 static inline int test_ignore(void)
74 if (min_cpu < 0 && max_cpu < 0)
75 return 0;
76 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
77 return 0;
78 else
79 return 1;
82 static inline void __init_new_packet_slot(struct packet *slot)
84 slot->payload = NULL;
85 slot->len = 0;
88 static inline void __init_new_counter_slot(struct packet_dyn *slot)
90 slot->cnt = NULL;
91 slot->clen = 0;
94 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
96 slot->rnd = NULL;
97 slot->rlen = 0;
100 static inline void __init_new_csum_slot(struct packet_dyn *slot)
102 slot->csum = NULL;
103 slot->slen = 0;
106 static inline void __setup_new_counter(struct counter *c, uint8_t start,
107 uint8_t stop, uint8_t stepping,
108 int type)
110 c->min = start;
111 c->max = stop;
112 c->inc = stepping;
113 c->val = (type == TYPE_INC) ? start : stop;
114 c->off = payload_last;
115 c->type = type;
118 static inline void __setup_new_randomizer(struct randomizer *r)
120 r->off = payload_last;
123 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
124 enum csum which)
126 s->off = payload_last - 1;
127 s->from = from;
128 s->to = to;
129 s->which = which;
132 static void realloc_packet(void)
134 if (test_ignore())
135 return;
137 plen++;
138 packets = xrealloc(packets, plen * sizeof(*packets));
140 __init_new_packet_slot(&packets[packet_last]);
142 dlen++;
143 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
145 __init_new_counter_slot(&packet_dyn[packetd_last]);
146 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
147 __init_new_csum_slot(&packet_dyn[packetd_last]);
150 struct packet *current_packet(void)
152 return &packets[packet_last];
155 static void set_byte(uint8_t val)
157 struct packet *pkt = &packets[packet_last];
159 if (test_ignore())
160 return;
162 pkt->len++;
163 pkt->payload = xrealloc(pkt->payload, pkt->len);
164 pkt->payload[payload_last] = val;
167 static void set_multi_byte(uint8_t *s, size_t len)
169 size_t i;
171 for (i = 0; i < len; ++i)
172 set_byte(s[i]);
175 void set_fill(uint8_t val, size_t len)
177 size_t i;
178 struct packet *pkt = &packets[packet_last];
180 if (test_ignore())
181 return;
183 pkt->len += len;
184 pkt->payload = xrealloc(pkt->payload, pkt->len);
185 for (i = 0; i < len; ++i)
186 pkt->payload[payload_last - i] = val;
189 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
191 struct packet *pkt = &packets[packet_last];
192 struct packet_dyn *pktd = &packet_dyn[packetd_last];
194 pkt->len += 2;
195 pkt->payload = xrealloc(pkt->payload, pkt->len);
197 pktd->slen++;
198 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
200 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
203 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
205 struct packet *pkt = &packets[packet_last];
206 uint16_t sum;
207 uint8_t *psum;
209 sum = htons(calc_csum(pkt->payload + from, to - from));
210 psum = (uint8_t *) &sum;
212 set_byte(psum[0]);
213 set_byte(psum[1]);
216 static inline bool is_dynamic_csum(enum csum which)
218 switch (which) {
219 case CSUM_UDP:
220 case CSUM_TCP:
221 case CSUM_UDP6:
222 case CSUM_TCP6:
223 return true;
224 default:
225 return false;
229 static void set_csum16(size_t from, size_t to, enum csum which)
231 struct packet *pkt = &packets[packet_last];
232 struct packet_dyn *pktd = &packet_dyn[packetd_last];
234 if (test_ignore())
235 return;
237 if (to < from) {
238 size_t tmp = to;
240 to = from;
241 from = tmp;
244 bug_on(!(from < to));
246 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
247 __set_csum16_dynamic(from, to, which);
248 else
249 __set_csum16_static(from, to, which);
252 static void set_rnd(size_t len)
254 size_t i;
255 struct packet *pkt = &packets[packet_last];
257 if (test_ignore())
258 return;
260 pkt->len += len;
261 pkt->payload = xrealloc(pkt->payload, pkt->len);
262 for (i = 0; i < len; ++i)
263 pkt->payload[payload_last - i] = (uint8_t) rand();
266 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
268 size_t i;
269 struct packet *pkt = &packets[packet_last];
271 if (test_ignore())
272 return;
274 pkt->len += len;
275 pkt->payload = xrealloc(pkt->payload, pkt->len);
276 for (i = 0; i < len; ++i) {
277 off_t off = len - 1 - i;
279 pkt->payload[payload_last - off] = start;
280 start += stepping;
284 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
286 size_t i;
287 struct packet *pkt = &packets[packet_last];
289 if (test_ignore())
290 return;
292 pkt->len += len;
293 pkt->payload = xrealloc(pkt->payload, pkt->len);
294 for (i = 0; i < len; ++i) {
295 int off = len - 1 - i;
297 pkt->payload[payload_last - off] = start;
298 start -= stepping;
302 static void set_dynamic_rnd(void)
304 struct packet *pkt = &packets[packet_last];
305 struct packet_dyn *pktd = &packet_dyn[packetd_last];
307 if (test_ignore())
308 return;
310 pkt->len++;
311 pkt->payload = xrealloc(pkt->payload, pkt->len);
313 pktd->rlen++;
314 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
316 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
319 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
320 int type)
322 struct packet *pkt = &packets[packet_last];
323 struct packet_dyn *pktd = &packet_dyn[packetd_last];
325 if (test_ignore())
326 return;
328 pkt->len++;
329 pkt->payload = xrealloc(pkt->payload, pkt->len);
331 pktd->clen++;
332 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
334 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
337 static void proto_add(enum proto_id pid)
339 hdr = proto_header_init(pid);
344 %union {
345 struct in_addr ip4_addr;
346 struct in6_addr ip6_addr;
347 long long int number;
348 uint8_t bytes[256];
349 char *str;
352 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
353 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
355 %token K_DADDR K_SADDR K_ETYPE K_TYPE
356 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
357 %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
358 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
359 %token K_MTYPE K_CODE K_ECHO_REQUEST K_ECHO_REPLY
360 %token K_SPORT K_DPORT
361 %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
362 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
363 %token K_LABEL K_TC K_LAST K_EXP
365 %token K_ETH
366 %token K_VLAN K_MPLS
367 %token K_ARP
368 %token K_IP4 K_IP6
369 %token K_ICMP6
370 %token K_UDP K_TCP
372 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
374 %token number string mac ip4_addr ip6_addr
376 %type <number> number expression
377 %type <str> string
378 %type <bytes> mac
379 %type <ip4_addr> ip4_addr
380 %type <ip6_addr> ip6_addr
382 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
386 packets
387 : { }
388 | packets packet { }
389 | packets inline_comment { }
390 | packets K_WHITE { }
393 inline_comment
394 : K_COMMENT { }
397 cpu_delim
398 : ':' { }
399 | '-' { }
402 delimiter_nowhite
403 : ',' { }
404 | ',' K_WHITE { }
407 noenforce_white
408 : { }
409 | K_WHITE { }
410 | delimiter_nowhite { }
413 skip_white
414 : { }
415 | K_WHITE { }
417 packet
418 : '{' noenforce_white payload noenforce_white '}' {
419 min_cpu = max_cpu = -1;
421 proto_packet_finish();
423 realloc_packet();
425 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
426 min_cpu = $3;
427 max_cpu = $5;
429 if (min_cpu > max_cpu) {
430 int tmp = min_cpu;
432 min_cpu = max_cpu;
433 max_cpu = tmp;
436 proto_packet_finish();
438 realloc_packet();
440 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
441 min_cpu = max_cpu = $3;
443 proto_packet_finish();
445 realloc_packet();
449 payload
450 : elem { }
451 | payload elem_delimiter { }
454 delimiter
455 : delimiter_nowhite { }
456 | K_WHITE { }
459 elem_delimiter
460 : delimiter elem { }
463 elem
464 : number { set_byte((uint8_t) $1); }
465 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
466 | fill { }
467 | rnd { }
468 | drnd { }
469 | seqinc { }
470 | seqdec { }
471 | dinc { }
472 | ddec { }
473 | csum { }
474 | const { }
475 | proto { proto_header_finish(hdr); }
476 | inline_comment { }
479 expression
480 : number
481 { $$ = $1; }
482 | expression '+' expression
483 { $$ = $1 + $3; }
484 | expression '-' expression
485 { $$ = $1 - $3; }
486 | expression '*' expression
487 { $$ = $1 * $3; }
488 | expression '/' expression
489 { $$ = $1 / $3; }
490 | expression '%' expression
491 { $$ = $1 % $3; }
492 | expression '&' expression
493 { $$ = $1 & $3; }
494 | expression '|' expression
495 { $$ = $1 | $3; }
496 | expression '^' expression
497 { $$ = $1 ^ $3; }
498 | expression '<' '<' expression
499 { $$ = $1 << $4; }
500 | expression '>' '>' expression
501 { $$ = $1 >> $4; }
502 | '-' expression
503 { $$ = -1 * $2; }
504 | '(' expression ')'
505 { $$ = $2;}
508 fill
509 : K_FILL '(' number delimiter number ')'
510 { set_fill($3, $5); }
513 const
514 : K_CONST8 '(' expression ')'
515 { set_byte((uint8_t) $3); }
516 | K_CONST16 '(' expression ')' {
517 uint16_t __c = cpu_to_be16((uint16_t) $3);
519 set_multi_byte((uint8_t *) &__c, sizeof(__c));
521 | K_CONST32 '(' expression ')' {
522 uint32_t __c = cpu_to_be32((uint32_t) $3);
524 set_multi_byte((uint8_t *) &__c, sizeof(__c));
526 | K_CONST64 '(' expression ')' {
527 uint64_t __c = cpu_to_be64((uint64_t) $3);
529 set_multi_byte((uint8_t *) &__c, sizeof(__c));
534 : K_RND '(' number ')'
535 { set_rnd($3); }
538 csum
539 : K_CSUMIP '(' number delimiter number ')'
540 { set_csum16($3, $5, CSUM_IP); }
541 | K_CSUMTCP '(' number delimiter number ')'
542 { set_csum16($3, $5, CSUM_TCP); }
543 | K_CSUMUDP '(' number delimiter number ')'
544 { set_csum16($3, $5, CSUM_UDP); }
545 | K_CSUMTCP6 '(' number delimiter number ')'
546 { set_csum16($3, $5, CSUM_TCP6); }
547 | K_CSUMUDP6 '(' number delimiter number ')'
548 { set_csum16($3, $5, CSUM_UDP6); }
551 seqinc
552 : K_SEQINC '(' number delimiter number ')'
553 { set_sequential_inc($3, $5, 1); }
554 | K_SEQINC '(' number delimiter number delimiter number ')'
555 { set_sequential_inc($3, $5, $7); }
558 seqdec
559 : K_SEQDEC '(' number delimiter number ')'
560 { set_sequential_dec($3, $5, 1); }
561 | K_SEQDEC '(' number delimiter number delimiter number ')'
562 { set_sequential_dec($3, $5, $7); }
565 drnd
566 : K_DRND '(' ')'
567 { set_dynamic_rnd(); }
568 | K_DRND '(' number ')'
570 int i, max = $3;
571 for (i = 0; i < max; ++i)
572 set_dynamic_rnd();
576 dinc
577 : K_DINC '(' number delimiter number ')'
578 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
579 | K_DINC '(' number delimiter number delimiter number ')'
580 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
583 ddec
584 : K_DDEC '(' number delimiter number ')'
585 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
586 | K_DDEC '(' number delimiter number delimiter number ')'
587 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
590 proto
591 : eth_proto { }
592 | vlan_proto { }
593 | mpls_proto { }
594 | arp_proto { }
595 | ip4_proto { }
596 | ip6_proto { }
597 | icmpv6_proto { }
598 | udp_proto { }
599 | tcp_proto { }
602 eth_proto
603 : eth '(' eth_param_list ')' { }
607 : K_ETH { proto_add(PROTO_ETH); }
610 eth_param_list
611 : { }
612 | eth_field { }
613 | eth_field delimiter eth_param_list { }
616 eth_type
617 : K_ETYPE { }
618 | K_TYPE { }
619 | K_PROT { }
622 eth_field
623 : K_DADDR skip_white '=' skip_white mac
624 { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
625 | K_SADDR skip_white '=' skip_white mac
626 { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
627 | eth_type skip_white '=' skip_white number
628 { proto_field_set_be16(hdr, ETH_TYPE, $5); }
631 vlan_proto
632 : vlan '(' vlan_param_list ')' { }
635 vlan
636 : K_VLAN { proto_add(PROTO_VLAN); }
639 vlan_param_list
640 : { }
641 | vlan_field { }
642 | vlan_field delimiter vlan_param_list { }
645 vlan_type
646 : K_TPID { }
647 | K_PROT
650 vlan_field
651 : vlan_type skip_white '=' skip_white number
652 { proto_field_set_be16(hdr, VLAN_TPID, $5); }
653 | K_1Q
654 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
655 | K_1AD
656 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
657 | K_TCI skip_white '=' skip_white number
658 { proto_field_set_be16(hdr, VLAN_TCI, $5); }
659 | K_PCP skip_white '=' skip_white number
660 { proto_field_set_be16(hdr, VLAN_PCP, $5); }
661 | K_DEI skip_white '=' skip_white number
662 { proto_field_set_be16(hdr, VLAN_DEI, $5); }
663 | K_ID skip_white '=' skip_white number
664 { proto_field_set_be16(hdr, VLAN_VID, $5); }
667 mpls_proto
668 : mpls '(' mpls_param_list ')' { }
671 mpls
672 : K_MPLS { proto_add(PROTO_MPLS); }
675 mpls_param_list
676 : { }
677 | mpls_field { }
678 | mpls_field delimiter mpls_param_list { }
681 mpls_tc
682 : K_TC { }
683 | K_EXP { }
686 mpls_field
687 : K_LABEL skip_white '=' skip_white number
688 { proto_field_set_be32(hdr, MPLS_LABEL, $5); }
689 | mpls_tc skip_white '=' skip_white number
690 { proto_field_set_be32(hdr, MPLS_TC, $5); }
691 | K_LAST skip_white '=' skip_white number
692 { proto_field_set_be32(hdr, MPLS_LAST, $5); }
693 | K_TTL skip_white '=' skip_white number
694 { proto_field_set_be32(hdr, MPLS_TTL, $5); }
697 arp_proto
698 : arp '(' arp_param_list ')' { }
701 arp_param_list
702 : { }
703 | arp_field { }
704 | arp_field delimiter arp_param_list { }
707 arp_field
708 : K_OPER skip_white '=' skip_white K_REQUEST
709 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
710 | K_OPER skip_white '=' skip_white K_REPLY
711 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
712 | K_OPER skip_white '=' skip_white number
713 { proto_field_set_be16(hdr, ARP_OPER, $5); }
714 | K_REQUEST
715 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
716 | K_REPLY
717 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
718 | K_HTYPE skip_white '=' skip_white number
719 { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
720 | K_PTYPE skip_white '=' skip_white number
721 { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
722 | K_SHA skip_white '=' skip_white mac
723 { proto_field_set_bytes(hdr, ARP_SHA, $5); }
724 | K_THA skip_white '=' skip_white mac
725 { proto_field_set_bytes(hdr, ARP_THA, $5); }
726 | K_SPA skip_white '=' skip_white ip4_addr
727 { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
728 | K_TPA skip_white '=' skip_white ip4_addr
729 { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
732 : K_ARP { proto_add(PROTO_ARP); }
735 ip4_proto
736 : ip4 '(' ip4_param_list ')' { }
739 ip4_param_list
740 : { }
741 | ip4_field { }
742 | ip4_field delimiter ip4_param_list { }
745 ip4_field
746 : K_VER skip_white '=' skip_white number
747 { proto_field_set_u8(hdr, IP4_VER, $5); }
748 | K_IHL skip_white '=' skip_white number
749 { proto_field_set_u8(hdr, IP4_IHL, $5); }
750 | K_DADDR skip_white '=' skip_white ip4_addr
751 { proto_field_set_u32(hdr, IP4_DADDR, $5.s_addr); }
752 | K_SADDR skip_white '=' skip_white ip4_addr
753 { proto_field_set_u32(hdr, IP4_SADDR, $5.s_addr); }
754 | K_PROT skip_white '=' skip_white number
755 { proto_field_set_u8(hdr, IP4_PROTO, $5); }
756 | K_TTL skip_white '=' skip_white number
757 { proto_field_set_u8(hdr, IP4_TTL, $5); }
758 | K_DSCP skip_white '=' skip_white number
759 { proto_field_set_u8(hdr, IP4_DSCP, $5); }
760 | K_ECN skip_white '=' skip_white number
761 { proto_field_set_u8(hdr, IP4_ECN, $5); }
762 | K_TOS skip_white '=' skip_white number
763 { proto_field_set_u8(hdr, IP4_TOS, $5); }
764 | K_LEN skip_white '=' skip_white number
765 { proto_field_set_be16(hdr, IP4_LEN, $5); }
766 | K_ID skip_white '=' skip_white number
767 { proto_field_set_be16(hdr, IP4_ID, $5); }
768 | K_FLAGS skip_white '=' skip_white number
769 { proto_field_set_be16(hdr, IP4_FLAGS, $5); }
770 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
771 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
772 | K_FRAG skip_white '=' skip_white number
773 { proto_field_set_be16(hdr, IP4_FRAG_OFFS, $5); }
774 | K_CSUM skip_white '=' skip_white number
775 { proto_field_set_be16(hdr, IP4_CSUM, $5); }
779 : K_IP4 { proto_add(PROTO_IP4); }
782 ip6_proto
783 : ip6 '(' ip6_param_list ')' { }
786 ip6_param_list
787 : { }
788 | ip6_field { }
789 | ip6_field delimiter ip6_param_list { }
792 ip6_hop_limit
793 : K_HOP_LIMIT { }
794 | K_TTL { }
797 ip6_field
798 : K_VER skip_white '=' skip_white number
799 { proto_field_set_be32(hdr, IP6_VER, $5); }
800 | K_TC skip_white '=' skip_white number
801 { proto_field_set_be32(hdr, IP6_CLASS, $5); }
802 | K_FLOW skip_white '=' skip_white number
803 { proto_field_set_be32(hdr, IP6_FLOW_LBL, $5); }
804 | K_LEN skip_white '=' skip_white number
805 { proto_field_set_be16(hdr, IP6_LEN, $5); }
806 | K_NEXT_HDR skip_white '=' skip_white number
807 { proto_field_set_u8(hdr, IP6_NEXT_HDR, $5); }
808 | ip6_hop_limit skip_white '=' skip_white number
809 { proto_field_set_u8(hdr, IP6_HOP_LIMIT, $5); }
810 | K_SADDR skip_white '=' skip_white ip6_addr
811 { proto_field_set_bytes(hdr, IP6_SADDR, (uint8_t *)&($5.s6_addr)); }
812 | K_DADDR skip_white '=' skip_white ip6_addr
813 { proto_field_set_bytes(hdr, IP6_DADDR, (uint8_t *)&($5.s6_addr)); }
817 : K_IP6 { proto_add(PROTO_IP6); }
820 icmpv6_proto
821 : icmp6 '(' icmp6_param_list ')' { }
823 icmp6_param_list
824 : { }
825 | icmp6_field { }
826 | icmp6_field delimiter icmp6_param_list { }
829 icmp6_field
830 : K_MTYPE skip_white '=' skip_white number
831 { proto_field_set_u8(hdr, ICMPV6_TYPE, $5); }
832 | K_MTYPE skip_white '=' K_ECHO_REQUEST
833 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
834 | K_ECHO_REQUEST
835 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
836 | K_MTYPE skip_white '=' K_ECHO_REPLY
837 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
838 | K_ECHO_REPLY
839 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
840 | K_CODE skip_white '=' skip_white number
841 { proto_field_set_u8(hdr, ICMPV6_CODE, $5); }
842 | K_CSUM skip_white '=' skip_white number
843 { proto_field_set_be16(hdr, ICMPV6_CSUM, $5); }
846 icmp6
847 : K_ICMP6 { proto_add(PROTO_ICMP6); }
850 udp_proto
851 : udp '(' udp_param_list ')' { }
854 udp_param_list
855 : { }
856 | udp_field { }
857 | udp_field delimiter udp_param_list { }
860 udp_field
861 : K_SPORT skip_white '=' skip_white number
862 { proto_field_set_be16(hdr, UDP_SPORT, $5); }
863 | K_DPORT skip_white '=' skip_white number
864 { proto_field_set_be16(hdr, UDP_DPORT, $5); }
865 | K_LEN skip_white '=' skip_white number
866 { proto_field_set_be16(hdr, UDP_LEN, $5); }
867 | K_CSUM skip_white '=' skip_white number
868 { proto_field_set_be16(hdr, UDP_CSUM, $5); }
872 : K_UDP { proto_add(PROTO_UDP); }
875 tcp_proto
876 : tcp '(' tcp_param_list ')' { }
879 tcp_param_list
880 : { }
881 | tcp_field { }
882 | tcp_field delimiter tcp_param_list { }
885 tcp_field
886 : K_SPORT skip_white '=' skip_white number
887 { proto_field_set_be16(hdr, TCP_SPORT, $5); }
888 | K_DPORT skip_white '=' skip_white number
889 { proto_field_set_be16(hdr, TCP_DPORT, $5); }
890 | K_SEQ skip_white '=' skip_white number
891 { proto_field_set_be32(hdr, TCP_SEQ, $5); }
892 | K_ACK_SEQ skip_white '=' skip_white number
893 { proto_field_set_be32(hdr, TCP_ACK_SEQ, $5); }
894 | K_DOFF skip_white '=' skip_white number
895 { proto_field_set_be16(hdr, TCP_DOFF, $5); }
896 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
897 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
898 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
899 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
900 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
901 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
902 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
903 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
904 | K_WINDOW skip_white '=' skip_white number
905 { proto_field_set_be16(hdr, TCP_WINDOW, $5); }
906 | K_CSUM skip_white '=' skip_white number
907 { proto_field_set_be16(hdr, TCP_CSUM, $5); }
908 | K_URG_PTR skip_white '=' skip_white number
909 { proto_field_set_be16(hdr, TCP_URG_PTR, $5); }
913 : K_TCP { proto_add(PROTO_TCP); }
918 static void finalize_packet(void)
920 /* XXX hack ... we allocated one packet pointer too much */
921 plen--;
922 dlen--;
925 static void dump_conf(void)
927 size_t i, j;
929 for (i = 0; i < plen; ++i) {
930 printf("[%zu] pkt\n", i);
931 printf(" len %zu cnts %zu rnds %zu\n",
932 packets[i].len,
933 packet_dyn[i].clen,
934 packet_dyn[i].rlen);
936 printf(" payload ");
937 for (j = 0; j < packets[i].len; ++j)
938 printf("%02x ", packets[i].payload[j]);
939 printf("\n");
941 for (j = 0; j < packet_dyn[i].clen; ++j)
942 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
943 packet_dyn[i].cnt[j].min,
944 packet_dyn[i].cnt[j].max,
945 packet_dyn[i].cnt[j].inc,
946 (intmax_t)packet_dyn[i].cnt[j].off,
947 packet_dyn[i].cnt[j].type == TYPE_INC ?
948 "inc" : "dec");
950 for (j = 0; j < packet_dyn[i].rlen; ++j)
951 printf(" rnd%zu off %jd\n", j,
952 (intmax_t)packet_dyn[i].rnd[j].off);
956 void cleanup_packets(void)
958 size_t i;
960 for (i = 0; i < plen; ++i) {
961 if (packets[i].len > 0)
962 xfree(packets[i].payload);
965 free(packets);
967 for (i = 0; i < dlen; ++i) {
968 free(packet_dyn[i].cnt);
969 free(packet_dyn[i].rnd);
972 free(packet_dyn);
975 void compile_packets(char *file, bool verbose, unsigned int cpu,
976 bool invoke_cpp, char *const cpp_argv[])
978 char tmp_file[128];
979 int ret = -1;
981 memset(tmp_file, 0, sizeof(tmp_file));
982 our_cpu = cpu;
984 if (invoke_cpp) {
985 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
986 fprintf(stderr, "Failed to invoke C preprocessor!\n");
987 goto err;
989 file = tmp_file;
992 if (!strncmp("-", file, strlen("-")))
993 yyin = stdin;
994 else
995 yyin = fopen(file, "r");
996 if (!yyin) {
997 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
998 goto err;
1001 realloc_packet();
1002 if (yyparse() != 0)
1003 goto err;
1004 finalize_packet();
1006 if (our_cpu == 0 && verbose)
1007 dump_conf();
1009 ret = 0;
1010 err:
1011 if (yyin && yyin != stdin)
1012 fclose(yyin);
1014 if (invoke_cpp)
1015 unlink(tmp_file);
1016 if (ret)
1017 die();
1020 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1022 int ret = 1;
1024 our_cpu = cpu;
1025 realloc_packet();
1027 yy_scan_string(str);
1028 if (yyparse() != 0)
1029 goto err;
1031 finalize_packet();
1032 if (our_cpu == 0 && verbose)
1033 dump_conf();
1035 ret = 0;
1036 err:
1037 yylex_destroy();
1039 if (ret)
1040 die();
1043 void yyerror(const char *err)
1045 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);