trafgen: parser: Unify proto field value parsing
[netsniff-ng.git] / trafgen_parser.y
blob1e7bd5c6a54826334a022ff86a412375566667fb
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 enum field_expr_type_t {
73 FIELD_EXPR_UNKNOWN,
74 FIELD_EXPR_NUMB,
75 FIELD_EXPR_MAC,
76 FIELD_EXPR_IP4_ADDR,
77 FIELD_EXPR_IP6_ADDR,
80 struct proto_field_expr {
81 enum field_expr_type_t type;
82 struct proto_field *field;
84 union {
85 struct in_addr ip4_addr;
86 struct in6_addr ip6_addr;
87 long long int number;
88 uint8_t bytes[256];
89 } val;
92 static struct proto_field_expr field_expr;
93 static struct proto_hdr *hdr;
95 static inline int test_ignore(void)
97 if (min_cpu < 0 && max_cpu < 0)
98 return 0;
99 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
100 return 0;
101 else
102 return 1;
105 static inline void __init_new_packet_slot(struct packet *slot)
107 slot->payload = NULL;
108 slot->len = 0;
111 static inline void __init_new_counter_slot(struct packet_dyn *slot)
113 slot->cnt = NULL;
114 slot->clen = 0;
117 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
119 slot->rnd = NULL;
120 slot->rlen = 0;
123 static inline void __init_new_csum_slot(struct packet_dyn *slot)
125 slot->csum = NULL;
126 slot->slen = 0;
129 static inline void __setup_new_counter(struct counter *c, uint8_t start,
130 uint8_t stop, uint8_t stepping,
131 int type)
133 c->min = start;
134 c->max = stop;
135 c->inc = stepping;
136 c->val = (type == TYPE_INC) ? start : stop;
137 c->off = payload_last;
138 c->type = type;
141 static inline void __setup_new_randomizer(struct randomizer *r)
143 r->off = payload_last;
146 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
147 enum csum which)
149 s->off = payload_last - 1;
150 s->from = from;
151 s->to = to;
152 s->which = which;
155 static void realloc_packet(void)
157 if (test_ignore())
158 return;
160 plen++;
161 packets = xrealloc(packets, plen * sizeof(*packets));
163 __init_new_packet_slot(&packets[packet_last]);
165 dlen++;
166 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
168 __init_new_counter_slot(&packet_dyn[packetd_last]);
169 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
170 __init_new_csum_slot(&packet_dyn[packetd_last]);
173 struct packet *current_packet(void)
175 return &packets[packet_last];
178 uint32_t current_packet_id(void)
180 return packet_last;
183 struct packet *packet_get(uint32_t id)
185 return &packets[id];
188 static void set_byte(uint8_t val)
190 struct packet *pkt = &packets[packet_last];
192 if (test_ignore())
193 return;
195 pkt->len++;
196 pkt->payload = xrealloc(pkt->payload, pkt->len);
197 pkt->payload[payload_last] = val;
200 static void set_multi_byte(uint8_t *s, size_t len)
202 size_t i;
204 for (i = 0; i < len; ++i)
205 set_byte(s[i]);
208 void set_fill(uint8_t val, size_t len)
210 size_t i;
211 struct packet *pkt = &packets[packet_last];
213 if (test_ignore())
214 return;
216 pkt->len += len;
217 pkt->payload = xrealloc(pkt->payload, pkt->len);
218 for (i = 0; i < len; ++i)
219 pkt->payload[payload_last - i] = val;
222 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
224 struct packet *pkt = &packets[packet_last];
225 struct packet_dyn *pktd = &packet_dyn[packetd_last];
227 pkt->len += 2;
228 pkt->payload = xrealloc(pkt->payload, pkt->len);
230 pktd->slen++;
231 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
233 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
236 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
238 struct packet *pkt = &packets[packet_last];
239 uint16_t sum;
240 uint8_t *psum;
242 sum = htons(calc_csum(pkt->payload + from, to - from));
243 psum = (uint8_t *) &sum;
245 set_byte(psum[0]);
246 set_byte(psum[1]);
249 static inline bool is_dynamic_csum(enum csum which)
251 switch (which) {
252 case CSUM_UDP:
253 case CSUM_TCP:
254 case CSUM_UDP6:
255 case CSUM_TCP6:
256 return true;
257 default:
258 return false;
262 static void set_csum16(size_t from, size_t to, enum csum which)
264 struct packet *pkt = &packets[packet_last];
265 struct packet_dyn *pktd = &packet_dyn[packetd_last];
267 if (test_ignore())
268 return;
270 if (to < from) {
271 size_t tmp = to;
273 to = from;
274 from = tmp;
277 bug_on(!(from < to));
279 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
280 __set_csum16_dynamic(from, to, which);
281 else
282 __set_csum16_static(from, to, which);
285 static void set_rnd(size_t len)
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 pkt->payload[payload_last - i] = (uint8_t) rand();
299 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
301 size_t i;
302 struct packet *pkt = &packets[packet_last];
304 if (test_ignore())
305 return;
307 pkt->len += len;
308 pkt->payload = xrealloc(pkt->payload, pkt->len);
309 for (i = 0; i < len; ++i) {
310 off_t off = len - 1 - i;
312 pkt->payload[payload_last - off] = start;
313 start += stepping;
317 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
319 size_t i;
320 struct packet *pkt = &packets[packet_last];
322 if (test_ignore())
323 return;
325 pkt->len += len;
326 pkt->payload = xrealloc(pkt->payload, pkt->len);
327 for (i = 0; i < len; ++i) {
328 int off = len - 1 - i;
330 pkt->payload[payload_last - off] = start;
331 start -= stepping;
335 static void set_dynamic_rnd(void)
337 struct packet *pkt = &packets[packet_last];
338 struct packet_dyn *pktd = &packet_dyn[packetd_last];
340 if (test_ignore())
341 return;
343 pkt->len++;
344 pkt->payload = xrealloc(pkt->payload, pkt->len);
346 pktd->rlen++;
347 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
349 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
352 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
353 int type)
355 struct packet *pkt = &packets[packet_last];
356 struct packet_dyn *pktd = &packet_dyn[packetd_last];
358 if (test_ignore())
359 return;
361 pkt->len++;
362 pkt->payload = xrealloc(pkt->payload, pkt->len);
364 pktd->clen++;
365 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
367 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
370 static void proto_add(enum proto_id pid)
372 hdr = proto_header_push(pid);
375 static void proto_field_set(uint32_t fid)
377 field_expr.field = proto_field_by_id(hdr, fid);
380 static void proto_field_expr_eval(void)
382 struct proto_field *field = field_expr.field;
384 switch (field_expr.type) {
385 case FIELD_EXPR_NUMB:
386 if (field->len == 1)
387 proto_field_set_u8(hdr, field->id, field_expr.val.number);
388 else if (field->len == 2)
389 proto_field_set_be16(hdr, field->id, field_expr.val.number);
390 else if (field->len == 4)
391 proto_field_set_be32(hdr, field->id, field_expr.val.number);
392 else
393 bug();
394 break;
396 case FIELD_EXPR_MAC:
397 proto_field_set_bytes(hdr, field->id, field_expr.val.bytes);
398 break;
400 case FIELD_EXPR_IP4_ADDR:
401 proto_field_set_u32(hdr, field->id, field_expr.val.ip4_addr.s_addr);
402 break;
404 case FIELD_EXPR_IP6_ADDR:
405 proto_field_set_bytes(hdr, field->id,
406 (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
407 break;
409 case FIELD_EXPR_UNKNOWN:
410 default:
411 bug();
414 memset(&field_expr, 0, sizeof(field_expr));
419 %union {
420 struct in_addr ip4_addr;
421 struct in6_addr ip6_addr;
422 long long int number;
423 uint8_t bytes[256];
424 char *str;
427 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
428 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
430 %token K_DADDR K_SADDR K_ETYPE K_TYPE
431 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
432 %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
433 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
434 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
435 %token K_SPORT K_DPORT
436 %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
437 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
438 %token K_LABEL K_TC K_LAST K_EXP
440 %token K_ADDR K_MTU
442 %token K_ETH
443 %token K_VLAN K_MPLS
444 %token K_ARP
445 %token K_IP4 K_IP6
446 %token K_ICMP4 K_ICMP6
447 %token K_UDP K_TCP
449 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
451 %token number string mac ip4_addr ip6_addr
453 %type <number> number expression
454 %type <str> string
455 %type <bytes> mac
456 %type <ip4_addr> ip4_addr
457 %type <ip6_addr> ip6_addr
459 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
463 packets
464 : { }
465 | packets packet { }
466 | packets inline_comment { }
467 | packets K_WHITE { }
470 inline_comment
471 : K_COMMENT { }
474 cpu_delim
475 : ':' { }
476 | '-' { }
479 delimiter_nowhite
480 : ',' { }
481 | ',' K_WHITE { }
484 noenforce_white
485 : { }
486 | K_WHITE { }
487 | delimiter_nowhite { }
490 skip_white
491 : { }
492 | K_WHITE { }
494 packet
495 : '{' noenforce_white payload noenforce_white '}' {
496 min_cpu = max_cpu = -1;
498 proto_packet_finish();
500 realloc_packet();
502 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
503 min_cpu = $3;
504 max_cpu = $5;
506 if (min_cpu > max_cpu) {
507 int tmp = min_cpu;
509 min_cpu = max_cpu;
510 max_cpu = tmp;
513 proto_packet_finish();
515 realloc_packet();
517 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
518 min_cpu = max_cpu = $3;
520 proto_packet_finish();
522 realloc_packet();
526 payload
527 : elem { }
528 | payload elem_delimiter { }
531 delimiter
532 : delimiter_nowhite { }
533 | K_WHITE { }
536 elem_delimiter
537 : delimiter elem { }
540 elem
541 : number { set_byte((uint8_t) $1); }
542 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
543 | fill { }
544 | rnd { }
545 | drnd { }
546 | seqinc { }
547 | seqdec { }
548 | dinc { }
549 | ddec { }
550 | csum { }
551 | const { }
552 | proto { proto_header_finish(hdr); }
553 | inline_comment { }
556 expression
557 : number
558 { $$ = $1; }
559 | expression '+' expression
560 { $$ = $1 + $3; }
561 | expression '-' expression
562 { $$ = $1 - $3; }
563 | expression '*' expression
564 { $$ = $1 * $3; }
565 | expression '/' expression
566 { $$ = $1 / $3; }
567 | expression '%' expression
568 { $$ = $1 % $3; }
569 | expression '&' expression
570 { $$ = $1 & $3; }
571 | expression '|' expression
572 { $$ = $1 | $3; }
573 | expression '^' expression
574 { $$ = $1 ^ $3; }
575 | expression '<' '<' expression
576 { $$ = $1 << $4; }
577 | expression '>' '>' expression
578 { $$ = $1 >> $4; }
579 | '-' expression
580 { $$ = -1 * $2; }
581 | '(' expression ')'
582 { $$ = $2;}
585 fill
586 : K_FILL '(' number delimiter number ')'
587 { set_fill($3, $5); }
590 const
591 : K_CONST8 '(' expression ')'
592 { set_byte((uint8_t) $3); }
593 | K_CONST16 '(' expression ')' {
594 uint16_t __c = cpu_to_be16((uint16_t) $3);
596 set_multi_byte((uint8_t *) &__c, sizeof(__c));
598 | K_CONST32 '(' expression ')' {
599 uint32_t __c = cpu_to_be32((uint32_t) $3);
601 set_multi_byte((uint8_t *) &__c, sizeof(__c));
603 | K_CONST64 '(' expression ')' {
604 uint64_t __c = cpu_to_be64((uint64_t) $3);
606 set_multi_byte((uint8_t *) &__c, sizeof(__c));
611 : K_RND '(' number ')'
612 { set_rnd($3); }
615 csum
616 : K_CSUMIP '(' number delimiter number ')'
617 { set_csum16($3, $5, CSUM_IP); }
618 | K_CSUMTCP '(' number delimiter number ')'
619 { set_csum16($3, $5, CSUM_TCP); }
620 | K_CSUMUDP '(' number delimiter number ')'
621 { set_csum16($3, $5, CSUM_UDP); }
622 | K_CSUMTCP6 '(' number delimiter number ')'
623 { set_csum16($3, $5, CSUM_TCP6); }
624 | K_CSUMUDP6 '(' number delimiter number ')'
625 { set_csum16($3, $5, CSUM_UDP6); }
628 seqinc
629 : K_SEQINC '(' number delimiter number ')'
630 { set_sequential_inc($3, $5, 1); }
631 | K_SEQINC '(' number delimiter number delimiter number ')'
632 { set_sequential_inc($3, $5, $7); }
635 seqdec
636 : K_SEQDEC '(' number delimiter number ')'
637 { set_sequential_dec($3, $5, 1); }
638 | K_SEQDEC '(' number delimiter number delimiter number ')'
639 { set_sequential_dec($3, $5, $7); }
642 drnd
643 : K_DRND '(' ')'
644 { set_dynamic_rnd(); }
645 | K_DRND '(' number ')'
647 int i, max = $3;
648 for (i = 0; i < max; ++i)
649 set_dynamic_rnd();
653 dinc
654 : K_DINC '(' number delimiter number ')'
655 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
656 | K_DINC '(' number delimiter number delimiter number ')'
657 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
660 ddec
661 : K_DDEC '(' number delimiter number ')'
662 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
663 | K_DDEC '(' number delimiter number delimiter number ')'
664 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
667 proto
668 : eth_proto { }
669 | vlan_proto { }
670 | mpls_proto { }
671 | arp_proto { }
672 | ip4_proto { }
673 | ip6_proto { }
674 | icmp4_proto { }
675 | icmpv6_proto { }
676 | udp_proto { }
677 | tcp_proto { }
680 field_expr
681 : number { field_expr.type = FIELD_EXPR_NUMB;
682 field_expr.val.number = $1; }
683 | mac { field_expr.type = FIELD_EXPR_MAC;
684 memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); }
685 | ip4_addr { field_expr.type = FIELD_EXPR_IP4_ADDR;
686 field_expr.val.ip4_addr = $1; }
687 | ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
688 field_expr.val.ip6_addr = $1; }
691 eth_proto
692 : eth '(' eth_param_list ')' { }
696 : K_ETH { proto_add(PROTO_ETH); }
699 eth_param_list
700 : { }
701 | eth_expr { }
702 | eth_expr delimiter eth_param_list { }
705 eth_type
706 : K_ETYPE { }
707 | K_TYPE { }
708 | K_PROT { }
711 eth_field
712 : K_DADDR { proto_field_set(ETH_DST_ADDR); }
713 | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
714 | eth_type { proto_field_set(ETH_TYPE); }
716 eth_expr
717 : eth_field skip_white '=' skip_white field_expr
718 { proto_field_expr_eval(); }
721 vlan_proto
722 : vlan '(' vlan_param_list ')' { }
725 vlan
726 : K_VLAN { proto_add(PROTO_VLAN); }
729 vlan_param_list
730 : { }
731 | vlan_expr { }
732 | vlan_expr delimiter vlan_param_list { }
735 vlan_type
736 : K_TPID { }
737 | K_PROT
740 vlan_field
741 : vlan_type { proto_field_set(VLAN_TPID); }
742 | K_TCI { proto_field_set(VLAN_TCI); }
743 | K_PCP { proto_field_set(VLAN_PCP); }
744 | K_DEI { proto_field_set(VLAN_DEI); }
745 | K_ID { proto_field_set(VLAN_VID); }
748 vlan_expr
749 : vlan_field skip_white '=' skip_white field_expr
750 { proto_field_expr_eval(); }
751 | K_1Q
752 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
753 | K_1AD
754 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
757 mpls_proto
758 : mpls '(' mpls_param_list ')' { }
761 mpls
762 : K_MPLS { proto_add(PROTO_MPLS); }
765 mpls_param_list
766 : { }
767 | mpls_expr { }
768 | mpls_expr delimiter mpls_param_list { }
771 mpls_tc
772 : K_TC { }
773 | K_EXP { }
776 mpls_field
777 : K_LABEL { proto_field_set(MPLS_LABEL); }
778 | mpls_tc { proto_field_set(MPLS_TC); }
779 | K_LAST { proto_field_set(MPLS_LAST); }
780 | K_TTL { proto_field_set(MPLS_TTL); }
783 mpls_expr
784 : mpls_field skip_white '=' skip_white field_expr
785 { proto_field_expr_eval(); }
787 arp_proto
788 : arp '(' arp_param_list ')' { }
791 arp_param_list
792 : { }
793 | arp_expr { }
794 | arp_expr delimiter arp_param_list { }
797 arp_field
798 : K_HTYPE
799 { proto_field_set(ARP_HTYPE); }
800 | K_PTYPE
801 { proto_field_set(ARP_PTYPE); }
802 | K_SHA
803 { proto_field_set(ARP_SHA); }
804 | K_THA
805 { proto_field_set(ARP_THA); }
806 | K_SPA
807 { proto_field_set(ARP_SPA); }
808 | K_TPA
809 { proto_field_set(ARP_TPA); }
812 arp_expr
813 : arp_field skip_white '=' skip_white field_expr
814 { proto_field_expr_eval(); }
815 | K_OPER skip_white '=' skip_white field_expr
816 { proto_field_set(ARP_OPER);
817 proto_field_expr_eval(); }
818 | K_OPER skip_white '=' skip_white K_REQUEST
819 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
820 | K_OPER skip_white '=' skip_white K_REPLY
821 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
822 | K_REQUEST
823 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
824 | K_REPLY
825 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
828 : K_ARP { proto_add(PROTO_ARP); }
831 ip4_proto
832 : ip4 '(' ip4_param_list ')' { }
835 ip4_param_list
836 : { }
837 | ip4_expr { }
838 | ip4_expr delimiter ip4_param_list { }
841 ip4_field
842 : K_VER { proto_field_set(IP4_VER); }
843 | K_IHL { proto_field_set(IP4_IHL); }
844 | K_DADDR { proto_field_set(IP4_DADDR); }
845 | K_SADDR { proto_field_set(IP4_SADDR); }
846 | K_PROT { proto_field_set(IP4_PROTO); }
847 | K_TTL { proto_field_set(IP4_TTL); }
848 | K_DSCP { proto_field_set(IP4_DSCP); }
849 | K_ECN { proto_field_set(IP4_ECN); }
850 | K_TOS { proto_field_set(IP4_TOS); }
851 | K_LEN { proto_field_set(IP4_LEN); }
852 | K_ID { proto_field_set(IP4_ID); }
853 | K_FLAGS { proto_field_set(IP4_FLAGS); }
854 | K_FRAG { proto_field_set(IP4_FRAG_OFFS); }
855 | K_CSUM { proto_field_set(IP4_CSUM); }
858 ip4_expr
859 : ip4_field skip_white '=' skip_white field_expr
860 { proto_field_expr_eval(); }
861 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
862 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
866 : K_IP4 { proto_add(PROTO_IP4); }
869 ip6_proto
870 : ip6 '(' ip6_param_list ')' { }
873 ip6_param_list
874 : { }
875 | ip6_expr { }
876 | ip6_expr delimiter ip6_param_list { }
879 ip6_hop_limit
880 : K_HOP_LIMIT { }
881 | K_TTL { }
884 ip6_field
885 : K_VER { proto_field_set(IP6_VER); }
886 | K_TC { proto_field_set(IP6_CLASS); }
887 | K_FLOW { proto_field_set(IP6_FLOW_LBL); }
888 | K_LEN { proto_field_set(IP6_LEN); }
889 | K_NEXT_HDR { proto_field_set(IP6_NEXT_HDR); }
890 | ip6_hop_limit { proto_field_set(IP6_HOP_LIMIT); }
891 | K_SADDR { proto_field_set(IP6_SADDR); }
892 | K_DADDR { proto_field_set(IP6_DADDR) ; }
895 ip6_expr
896 : ip6_field skip_white '=' skip_white field_expr
897 { proto_field_expr_eval(); }
901 : K_IP6 { proto_add(PROTO_IP6); }
904 icmp4_proto
905 : icmp4 '(' icmp4_param_list ')' { }
908 icmp4_param_list
909 : { }
910 | icmp4_expr { }
911 | icmp4_expr delimiter icmp4_param_list { }
914 icmp4_field
915 : K_TYPE { proto_field_set(ICMPV4_TYPE); }
916 | K_CODE { proto_field_set(ICMPV4_CODE); }
917 | K_ID { proto_field_set(ICMPV4_ID); }
918 | K_SEQ { proto_field_set(ICMPV4_SEQ); }
919 | K_MTU { proto_field_set(ICMPV4_MTU); }
920 | K_ADDR { proto_field_set(ICMPV4_REDIR_ADDR); }
923 icmp4_expr
924 : icmp4_field skip_white '=' skip_white field_expr
925 { proto_field_expr_eval(); }
926 | K_ECHO_REQUEST
927 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
928 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
929 | K_ECHO_REPLY
930 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
931 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
934 icmp4
935 : K_ICMP4 { proto_add(PROTO_ICMP4); }
938 icmpv6_proto
939 : icmp6 '(' icmp6_param_list ')' { }
941 icmp6_param_list
942 : { }
943 | icmp6_expr { }
944 | icmp6_expr delimiter icmp6_param_list { }
947 icmp6_field
948 : K_CODE { proto_field_set(ICMPV6_CODE); }
949 | K_CSUM { proto_field_set(ICMPV6_CSUM); }
952 icmp6_expr
953 : icmp6_field skip_white '=' skip_white field_expr
954 { proto_field_expr_eval(); }
955 | K_TYPE skip_white '=' skip_white field_expr
956 { proto_field_set(ICMPV6_TYPE);
957 proto_field_expr_eval(); }
958 | K_TYPE skip_white '=' K_ECHO_REQUEST
959 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
960 | K_ECHO_REQUEST
961 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
962 | K_TYPE skip_white '=' K_ECHO_REPLY
963 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
964 | K_ECHO_REPLY
965 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
967 icmp6
968 : K_ICMP6 { proto_add(PROTO_ICMP6); }
971 udp_proto
972 : udp '(' udp_param_list ')' { }
975 udp_param_list
976 : { }
977 | udp_expr { }
978 | udp_expr delimiter udp_param_list { }
981 udp_field
982 : K_SPORT { proto_field_set(UDP_SPORT); }
983 | K_DPORT { proto_field_set(UDP_DPORT); }
984 | K_LEN { proto_field_set(UDP_LEN); }
985 | K_CSUM { proto_field_set(UDP_CSUM); }
988 udp_expr
989 : udp_field skip_white '=' skip_white field_expr
990 { proto_field_expr_eval(); }
994 : K_UDP { proto_add(PROTO_UDP); }
997 tcp_proto
998 : tcp '(' tcp_param_list ')' { }
1001 tcp_param_list
1002 : { }
1003 | tcp_expr { }
1004 | tcp_expr delimiter tcp_param_list { }
1007 tcp_field
1008 : K_SPORT { proto_field_set(TCP_SPORT); }
1009 | K_DPORT { proto_field_set(TCP_DPORT); }
1010 | K_SEQ { proto_field_set(TCP_SEQ); }
1011 | K_ACK_SEQ { proto_field_set(TCP_ACK_SEQ); }
1012 | K_DOFF { proto_field_set(TCP_DOFF); }
1013 | K_WINDOW { proto_field_set(TCP_WINDOW); }
1014 | K_CSUM { proto_field_set(TCP_CSUM); }
1015 | K_URG_PTR { proto_field_set(TCP_URG_PTR); }
1018 tcp_expr
1019 : tcp_field skip_white '=' skip_white field_expr
1020 { proto_field_expr_eval(); }
1021 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
1022 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
1023 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
1024 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
1025 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
1026 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
1027 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
1028 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
1032 : K_TCP { proto_add(PROTO_TCP); }
1037 static void finalize_packet(void)
1039 /* XXX hack ... we allocated one packet pointer too much */
1040 plen--;
1041 dlen--;
1044 static void dump_conf(void)
1046 size_t i, j;
1048 for (i = 0; i < plen; ++i) {
1049 printf("[%zu] pkt\n", i);
1050 printf(" len %zu cnts %zu rnds %zu\n",
1051 packets[i].len,
1052 packet_dyn[i].clen,
1053 packet_dyn[i].rlen);
1055 printf(" payload ");
1056 for (j = 0; j < packets[i].len; ++j)
1057 printf("%02x ", packets[i].payload[j]);
1058 printf("\n");
1060 for (j = 0; j < packet_dyn[i].clen; ++j)
1061 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
1062 packet_dyn[i].cnt[j].min,
1063 packet_dyn[i].cnt[j].max,
1064 packet_dyn[i].cnt[j].inc,
1065 (intmax_t)packet_dyn[i].cnt[j].off,
1066 packet_dyn[i].cnt[j].type == TYPE_INC ?
1067 "inc" : "dec");
1069 for (j = 0; j < packet_dyn[i].rlen; ++j)
1070 printf(" rnd%zu off %jd\n", j,
1071 (intmax_t)packet_dyn[i].rnd[j].off);
1075 void cleanup_packets(void)
1077 size_t i, j;
1079 for (i = 0; i < plen; ++i) {
1080 struct packet *pkt = &packets[i];
1082 if (pkt->len > 0)
1083 xfree(pkt->payload);
1085 for (j = 0; j < pkt->headers_count; j++) {
1086 struct proto_hdr *hdr = pkt->headers[j];
1088 if (hdr->fields)
1089 xfree(hdr->fields);
1090 xfree(hdr);
1094 free(packets);
1096 for (i = 0; i < dlen; ++i) {
1097 free(packet_dyn[i].cnt);
1098 free(packet_dyn[i].rnd);
1101 free(packet_dyn);
1104 void compile_packets(char *file, bool verbose, unsigned int cpu,
1105 bool invoke_cpp, char *const cpp_argv[])
1107 char tmp_file[128];
1108 int ret = -1;
1110 if (access(file, R_OK)) {
1111 fprintf(stderr, "Cannot access %s: %s!\n", file, strerror(errno));
1112 die();
1115 memset(tmp_file, 0, sizeof(tmp_file));
1116 our_cpu = cpu;
1118 if (invoke_cpp) {
1119 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1120 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1121 goto err;
1123 file = tmp_file;
1126 if (!strncmp("-", file, strlen("-")))
1127 yyin = stdin;
1128 else
1129 yyin = fopen(file, "r");
1130 if (!yyin) {
1131 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1132 goto err;
1135 realloc_packet();
1136 if (yyparse() != 0)
1137 goto err;
1138 finalize_packet();
1140 if (our_cpu == 0 && verbose)
1141 dump_conf();
1143 ret = 0;
1144 err:
1145 if (yyin && yyin != stdin)
1146 fclose(yyin);
1148 if (invoke_cpp)
1149 unlink(tmp_file);
1150 if (ret)
1151 die();
1154 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1156 int ret = 1;
1158 our_cpu = cpu;
1159 realloc_packet();
1161 yy_scan_string(str);
1162 if (yyparse() != 0)
1163 goto err;
1165 finalize_packet();
1166 if (our_cpu == 0 && verbose)
1167 dump_conf();
1169 ret = 0;
1170 err:
1171 yylex_destroy();
1173 if (ret)
1174 die();
1177 void yyerror(const char *err)
1179 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);