trafgen: proto: Add IPv6 header generation
[netsniff-ng-new.git] / trafgen_parser.y
blobd6c9e70dfcbeb46de7f91d08195a0b9418a4966a
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>
24 #include "xmalloc.h"
25 #include "trafgen_parser.tab.h"
26 #include "trafgen_conf.h"
27 #include "trafgen_proto.h"
28 #include "trafgen_l2.h"
29 #include "trafgen_l3.h"
30 #include "trafgen_l4.h"
31 #include "built_in.h"
32 #include "die.h"
33 #include "str.h"
34 #include "csum.h"
35 #include "cpp.h"
37 #define YYERROR_VERBOSE 0
38 #define YYDEBUG 0
39 #define YYENABLE_NLS 1
40 #define YYLTYPE_IS_TRIVIAL 1
41 #define ENABLE_NLS 1
43 extern FILE *yyin;
44 extern int yylex(void);
45 extern void yy_scan_string(char *);
46 extern void yylex_destroy();
47 extern void yyerror(const char *);
48 extern int yylineno;
49 extern char *yytext;
51 extern struct packet *packets;
52 extern size_t plen;
54 #define packet_last (plen - 1)
56 #define payload_last (packets[packet_last].len - 1)
58 extern struct packet_dyn *packet_dyn;
59 extern size_t dlen;
61 #define packetd_last (dlen - 1)
63 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
64 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
65 #define packetds_last (packet_dyn[packetd_last].slen - 1)
67 static int our_cpu, min_cpu = -1, max_cpu = -1;
69 static struct proto_hdr *hdr;
71 static inline int test_ignore(void)
73 if (min_cpu < 0 && max_cpu < 0)
74 return 0;
75 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
76 return 0;
77 else
78 return 1;
81 static inline void __init_new_packet_slot(struct packet *slot)
83 slot->payload = NULL;
84 slot->len = 0;
87 static inline void __init_new_counter_slot(struct packet_dyn *slot)
89 slot->cnt = NULL;
90 slot->clen = 0;
93 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
95 slot->rnd = NULL;
96 slot->rlen = 0;
99 static inline void __init_new_csum_slot(struct packet_dyn *slot)
101 slot->csum = NULL;
102 slot->slen = 0;
105 static inline void __setup_new_counter(struct counter *c, uint8_t start,
106 uint8_t stop, uint8_t stepping,
107 int type)
109 c->min = start;
110 c->max = stop;
111 c->inc = stepping;
112 c->val = (type == TYPE_INC) ? start : stop;
113 c->off = payload_last;
114 c->type = type;
117 static inline void __setup_new_randomizer(struct randomizer *r)
119 r->off = payload_last;
122 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
123 enum csum which)
125 s->off = payload_last - 1;
126 s->from = from;
127 s->to = to;
128 s->which = which;
131 static void realloc_packet(void)
133 if (test_ignore())
134 return;
136 plen++;
137 packets = xrealloc(packets, plen * sizeof(*packets));
139 __init_new_packet_slot(&packets[packet_last]);
141 dlen++;
142 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
144 __init_new_counter_slot(&packet_dyn[packetd_last]);
145 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
146 __init_new_csum_slot(&packet_dyn[packetd_last]);
149 struct packet *current_packet(void)
151 return &packets[packet_last];
154 static void set_byte(uint8_t val)
156 struct packet *pkt = &packets[packet_last];
158 if (test_ignore())
159 return;
161 pkt->len++;
162 pkt->payload = xrealloc(pkt->payload, pkt->len);
163 pkt->payload[payload_last] = val;
166 static void set_multi_byte(uint8_t *s, size_t len)
168 size_t i;
170 for (i = 0; i < len; ++i)
171 set_byte(s[i]);
174 void set_fill(uint8_t val, size_t len)
176 size_t i;
177 struct packet *pkt = &packets[packet_last];
179 if (test_ignore())
180 return;
182 pkt->len += len;
183 pkt->payload = xrealloc(pkt->payload, pkt->len);
184 for (i = 0; i < len; ++i)
185 pkt->payload[payload_last - i] = val;
188 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
190 struct packet *pkt = &packets[packet_last];
191 struct packet_dyn *pktd = &packet_dyn[packetd_last];
193 pkt->len += 2;
194 pkt->payload = xrealloc(pkt->payload, pkt->len);
196 pktd->slen++;
197 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
199 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
202 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
204 struct packet *pkt = &packets[packet_last];
205 uint16_t sum;
206 uint8_t *psum;
208 sum = htons(calc_csum(pkt->payload + from, to - from));
209 psum = (uint8_t *) &sum;
211 set_byte(psum[0]);
212 set_byte(psum[1]);
215 static inline bool is_dynamic_csum(enum csum which)
217 switch (which) {
218 case CSUM_UDP:
219 case CSUM_TCP:
220 case CSUM_UDP6:
221 case CSUM_TCP6:
222 return true;
223 default:
224 return false;
228 static void set_csum16(size_t from, size_t to, enum csum which)
230 struct packet *pkt = &packets[packet_last];
231 struct packet_dyn *pktd = &packet_dyn[packetd_last];
233 if (test_ignore())
234 return;
236 if (to < from) {
237 size_t tmp = to;
239 to = from;
240 from = tmp;
243 bug_on(!(from < to));
245 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
246 __set_csum16_dynamic(from, to, which);
247 else
248 __set_csum16_static(from, to, which);
251 static void set_rnd(size_t len)
253 size_t i;
254 struct packet *pkt = &packets[packet_last];
256 if (test_ignore())
257 return;
259 pkt->len += len;
260 pkt->payload = xrealloc(pkt->payload, pkt->len);
261 for (i = 0; i < len; ++i)
262 pkt->payload[payload_last - i] = (uint8_t) rand();
265 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
267 size_t i;
268 struct packet *pkt = &packets[packet_last];
270 if (test_ignore())
271 return;
273 pkt->len += len;
274 pkt->payload = xrealloc(pkt->payload, pkt->len);
275 for (i = 0; i < len; ++i) {
276 off_t off = len - 1 - i;
278 pkt->payload[payload_last - off] = start;
279 start += stepping;
283 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
285 size_t i;
286 struct packet *pkt = &packets[packet_last];
288 if (test_ignore())
289 return;
291 pkt->len += len;
292 pkt->payload = xrealloc(pkt->payload, pkt->len);
293 for (i = 0; i < len; ++i) {
294 int off = len - 1 - i;
296 pkt->payload[payload_last - off] = start;
297 start -= stepping;
301 static void set_dynamic_rnd(void)
303 struct packet *pkt = &packets[packet_last];
304 struct packet_dyn *pktd = &packet_dyn[packetd_last];
306 if (test_ignore())
307 return;
309 pkt->len++;
310 pkt->payload = xrealloc(pkt->payload, pkt->len);
312 pktd->rlen++;
313 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
315 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
318 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
319 int type)
321 struct packet *pkt = &packets[packet_last];
322 struct packet_dyn *pktd = &packet_dyn[packetd_last];
324 if (test_ignore())
325 return;
327 pkt->len++;
328 pkt->payload = xrealloc(pkt->payload, pkt->len);
330 pktd->clen++;
331 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
333 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
336 static void proto_add(enum proto_id pid)
338 hdr = proto_header_init(pid);
343 %union {
344 struct in_addr ip4_addr;
345 struct in6_addr ip6_addr;
346 long long int number;
347 uint8_t bytes[256];
348 char *str;
351 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
352 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
354 %token K_DADDR K_SADDR K_ETYPE
355 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
356 %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
357 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
358 %token K_SPORT K_DPORT
359 %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
360 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
361 %token K_LABEL K_TC K_LAST K_EXP
363 %token K_ETH
364 %token K_VLAN K_MPLS
365 %token K_ARP
366 %token K_IP4 K_IP6
367 %token K_UDP K_TCP
369 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
371 %token number string mac ip4_addr ip6_addr
373 %type <number> number expression
374 %type <str> string
375 %type <bytes> mac
376 %type <ip4_addr> ip4_addr
377 %type <ip6_addr> ip6_addr
379 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
383 packets
384 : { }
385 | packets packet { }
386 | packets inline_comment { }
387 | packets K_WHITE { }
390 inline_comment
391 : K_COMMENT { }
394 cpu_delim
395 : ':' { }
396 | '-' { }
399 delimiter_nowhite
400 : ',' { }
401 | ',' K_WHITE { }
404 noenforce_white
405 : { }
406 | K_WHITE { }
407 | delimiter_nowhite { }
410 skip_white
411 : { }
412 | K_WHITE { }
414 packet
415 : '{' noenforce_white payload noenforce_white '}' {
416 min_cpu = max_cpu = -1;
418 proto_packet_finish();
420 realloc_packet();
422 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
423 min_cpu = $3;
424 max_cpu = $5;
426 if (min_cpu > max_cpu) {
427 int tmp = min_cpu;
429 min_cpu = max_cpu;
430 max_cpu = tmp;
433 proto_packet_finish();
435 realloc_packet();
437 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
438 min_cpu = max_cpu = $3;
440 proto_packet_finish();
442 realloc_packet();
446 payload
447 : elem { }
448 | payload elem_delimiter { }
451 delimiter
452 : delimiter_nowhite { }
453 | K_WHITE { }
456 elem_delimiter
457 : delimiter elem { }
460 elem
461 : number { set_byte((uint8_t) $1); }
462 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
463 | fill { }
464 | rnd { }
465 | drnd { }
466 | seqinc { }
467 | seqdec { }
468 | dinc { }
469 | ddec { }
470 | csum { }
471 | const { }
472 | proto { proto_header_finish(hdr); }
473 | inline_comment { }
476 expression
477 : number
478 { $$ = $1; }
479 | expression '+' expression
480 { $$ = $1 + $3; }
481 | expression '-' expression
482 { $$ = $1 - $3; }
483 | expression '*' expression
484 { $$ = $1 * $3; }
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 << $4; }
497 | expression '>' '>' expression
498 { $$ = $1 >> $4; }
499 | '-' expression
500 { $$ = -1 * $2; }
501 | '(' expression ')'
502 { $$ = $2;}
505 fill
506 : K_FILL '(' number delimiter number ')'
507 { set_fill($3, $5); }
510 const
511 : K_CONST8 '(' expression ')'
512 { set_byte((uint8_t) $3); }
513 | K_CONST16 '(' expression ')' {
514 uint16_t __c = cpu_to_be16((uint16_t) $3);
516 set_multi_byte((uint8_t *) &__c, sizeof(__c));
518 | K_CONST32 '(' expression ')' {
519 uint32_t __c = cpu_to_be32((uint32_t) $3);
521 set_multi_byte((uint8_t *) &__c, sizeof(__c));
523 | K_CONST64 '(' expression ')' {
524 uint64_t __c = cpu_to_be64((uint64_t) $3);
526 set_multi_byte((uint8_t *) &__c, sizeof(__c));
531 : K_RND '(' number ')'
532 { set_rnd($3); }
535 csum
536 : K_CSUMIP '(' number delimiter number ')'
537 { set_csum16($3, $5, CSUM_IP); }
538 | K_CSUMTCP '(' number delimiter number ')'
539 { set_csum16($3, $5, CSUM_TCP); }
540 | K_CSUMUDP '(' number delimiter number ')'
541 { set_csum16($3, $5, CSUM_UDP); }
542 | K_CSUMTCP6 '(' number delimiter number ')'
543 { set_csum16($3, $5, CSUM_TCP6); }
544 | K_CSUMUDP6 '(' number delimiter number ')'
545 { set_csum16($3, $5, CSUM_UDP6); }
548 seqinc
549 : K_SEQINC '(' number delimiter number ')'
550 { set_sequential_inc($3, $5, 1); }
551 | K_SEQINC '(' number delimiter number delimiter number ')'
552 { set_sequential_inc($3, $5, $7); }
555 seqdec
556 : K_SEQDEC '(' number delimiter number ')'
557 { set_sequential_dec($3, $5, 1); }
558 | K_SEQDEC '(' number delimiter number delimiter number ')'
559 { set_sequential_dec($3, $5, $7); }
562 drnd
563 : K_DRND '(' ')'
564 { set_dynamic_rnd(); }
565 | K_DRND '(' number ')'
567 int i, max = $3;
568 for (i = 0; i < max; ++i)
569 set_dynamic_rnd();
573 dinc
574 : K_DINC '(' number delimiter number ')'
575 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
576 | K_DINC '(' number delimiter number delimiter number ')'
577 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
580 ddec
581 : K_DDEC '(' number delimiter number ')'
582 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
583 | K_DDEC '(' number delimiter number delimiter number ')'
584 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
587 proto
588 : eth_proto { }
589 | vlan_proto { }
590 | mpls_proto { }
591 | arp_proto { }
592 | ip4_proto { }
593 | ip6_proto { }
594 | udp_proto { }
595 | tcp_proto { }
598 eth_proto
599 : eth '(' eth_param_list ')' { }
603 : K_ETH { proto_add(PROTO_ETH); }
606 eth_param_list
607 : { }
608 | eth_field { }
609 | eth_field delimiter eth_param_list { }
612 eth_type
613 : K_ETYPE { }
614 | K_PROT { }
617 eth_field
618 : K_DADDR skip_white '=' skip_white mac
619 { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
620 | K_SADDR skip_white '=' skip_white mac
621 { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
622 | eth_type skip_white '=' skip_white number
623 { proto_field_set_be16(hdr, ETH_TYPE, $5); }
626 vlan_proto
627 : vlan '(' vlan_param_list ')' { }
630 vlan
631 : K_VLAN { proto_add(PROTO_VLAN); }
634 vlan_param_list
635 : { }
636 | vlan_field { }
637 | vlan_field delimiter vlan_param_list { }
640 vlan_type
641 : K_TPID { }
642 | K_PROT
645 vlan_field
646 : vlan_type skip_white '=' skip_white number
647 { proto_field_set_be16(hdr, VLAN_TPID, $5); }
648 | K_1Q
649 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
650 | K_1AD
651 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
652 | K_TCI skip_white '=' skip_white number
653 { proto_field_set_be16(hdr, VLAN_TCI, $5); }
654 | K_PCP skip_white '=' skip_white number
655 { proto_field_set_be16(hdr, VLAN_PCP, $5); }
656 | K_DEI skip_white '=' skip_white number
657 { proto_field_set_be16(hdr, VLAN_DEI, $5); }
658 | K_ID skip_white '=' skip_white number
659 { proto_field_set_be16(hdr, VLAN_VID, $5); }
662 mpls_proto
663 : mpls '(' mpls_param_list ')' { }
666 mpls
667 : K_MPLS { proto_add(PROTO_MPLS); }
670 mpls_param_list
671 : { }
672 | mpls_field { }
673 | mpls_field delimiter mpls_param_list { }
676 mpls_tc
677 : K_TC { }
678 | K_EXP { }
681 mpls_field
682 : K_LABEL skip_white '=' skip_white number
683 { proto_field_set_be32(hdr, MPLS_LABEL, $5); }
684 | mpls_tc skip_white '=' skip_white number
685 { proto_field_set_be32(hdr, MPLS_TC, $5); }
686 | K_LAST skip_white '=' skip_white number
687 { proto_field_set_be32(hdr, MPLS_LAST, $5); }
688 | K_TTL skip_white '=' skip_white number
689 { proto_field_set_be32(hdr, MPLS_TTL, $5); }
692 arp_proto
693 : arp '(' arp_param_list ')' { }
696 arp_param_list
697 : { }
698 | arp_field { }
699 | arp_field delimiter arp_param_list { }
702 arp_field
703 : K_OPER skip_white '=' skip_white K_REQUEST
704 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
705 | K_OPER skip_white '=' skip_white K_REPLY
706 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
707 | K_OPER skip_white '=' skip_white number
708 { proto_field_set_be16(hdr, ARP_OPER, $5); }
709 | K_REQUEST
710 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
711 | K_REPLY
712 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
713 | K_HTYPE skip_white '=' skip_white number
714 { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
715 | K_PTYPE skip_white '=' skip_white number
716 { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
717 | K_SHA skip_white '=' skip_white mac
718 { proto_field_set_bytes(hdr, ARP_SHA, $5); }
719 | K_THA skip_white '=' skip_white mac
720 { proto_field_set_bytes(hdr, ARP_THA, $5); }
721 | K_SPA skip_white '=' skip_white ip4_addr
722 { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
723 | K_TPA skip_white '=' skip_white ip4_addr
724 { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
727 : K_ARP { proto_add(PROTO_ARP); }
730 ip4_proto
731 : ip4 '(' ip4_param_list ')' { }
734 ip4_param_list
735 : { }
736 | ip4_field { }
737 | ip4_field delimiter ip4_param_list { }
740 ip4_field
741 : K_VER skip_white '=' skip_white number
742 { proto_field_set_u8(hdr, IP4_VER, $5); }
743 | K_IHL skip_white '=' skip_white number
744 { proto_field_set_u8(hdr, IP4_IHL, $5); }
745 | K_DADDR skip_white '=' skip_white ip4_addr
746 { proto_field_set_u32(hdr, IP4_DADDR, $5.s_addr); }
747 | K_SADDR skip_white '=' skip_white ip4_addr
748 { proto_field_set_u32(hdr, IP4_SADDR, $5.s_addr); }
749 | K_PROT skip_white '=' skip_white number
750 { proto_field_set_u8(hdr, IP4_PROTO, $5); }
751 | K_TTL skip_white '=' skip_white number
752 { proto_field_set_u8(hdr, IP4_TTL, $5); }
753 | K_DSCP skip_white '=' skip_white number
754 { proto_field_set_u8(hdr, IP4_DSCP, $5); }
755 | K_ECN skip_white '=' skip_white number
756 { proto_field_set_u8(hdr, IP4_ECN, $5); }
757 | K_TOS skip_white '=' skip_white number
758 { proto_field_set_u8(hdr, IP4_TOS, $5); }
759 | K_LEN skip_white '=' skip_white number
760 { proto_field_set_be16(hdr, IP4_LEN, $5); }
761 | K_ID skip_white '=' skip_white number
762 { proto_field_set_be16(hdr, IP4_ID, $5); }
763 | K_FLAGS skip_white '=' skip_white number
764 { proto_field_set_be16(hdr, IP4_FLAGS, $5); }
765 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
766 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
767 | K_FRAG skip_white '=' skip_white number
768 { proto_field_set_be16(hdr, IP4_FRAG_OFFS, $5); }
769 | K_CSUM skip_white '=' skip_white number
770 { proto_field_set_be16(hdr, IP4_CSUM, $5); }
774 : K_IP4 { proto_add(PROTO_IP4); }
777 ip6_proto
778 : ip6 '(' ip6_param_list ')' { }
781 ip6_param_list
782 : { }
783 | ip6_field { }
784 | ip6_field delimiter ip6_param_list { }
787 ip6_hop_limit
788 : K_HOP_LIMIT { }
789 | K_TTL { }
792 ip6_field
793 : K_VER skip_white '=' skip_white number
794 { proto_field_set_be32(hdr, IP6_VER, $5); }
795 | K_TC skip_white '=' skip_white number
796 { proto_field_set_be32(hdr, IP6_CLASS, $5); }
797 | K_FLOW skip_white '=' skip_white number
798 { proto_field_set_be32(hdr, IP6_FLOW_LBL, $5); }
799 | K_LEN skip_white '=' skip_white number
800 { proto_field_set_be16(hdr, IP6_LEN, $5); }
801 | K_NEXT_HDR skip_white '=' skip_white number
802 { proto_field_set_u8(hdr, IP6_NEXT_HDR, $5); }
803 | ip6_hop_limit skip_white '=' skip_white number
804 { proto_field_set_u8(hdr, IP6_HOP_LIMIT, $5); }
805 | K_SADDR skip_white '=' skip_white ip6_addr
806 { proto_field_set_bytes(hdr, IP6_SADDR, (uint8_t *)&($5.s6_addr)); }
807 | K_DADDR skip_white '=' skip_white ip6_addr
808 { proto_field_set_bytes(hdr, IP6_DADDR, (uint8_t *)&($5.s6_addr)); }
812 : K_IP6 { proto_add(PROTO_IP6); }
815 udp_proto
816 : udp '(' udp_param_list ')' { }
819 udp_param_list
820 : { }
821 | udp_field { }
822 | udp_field delimiter udp_param_list { }
825 udp_field
826 : K_SPORT skip_white '=' skip_white number
827 { proto_field_set_be16(hdr, UDP_SPORT, $5); }
828 | K_DPORT skip_white '=' skip_white number
829 { proto_field_set_be16(hdr, UDP_DPORT, $5); }
830 | K_LEN skip_white '=' skip_white number
831 { proto_field_set_be16(hdr, UDP_LEN, $5); }
832 | K_CSUM skip_white '=' skip_white number
833 { proto_field_set_be16(hdr, UDP_CSUM, $5); }
837 : K_UDP { proto_add(PROTO_UDP); }
840 tcp_proto
841 : tcp '(' tcp_param_list ')' { }
844 tcp_param_list
845 : { }
846 | tcp_field { }
847 | tcp_field delimiter tcp_param_list { }
850 tcp_field
851 : K_SPORT skip_white '=' skip_white number
852 { proto_field_set_be16(hdr, TCP_SPORT, $5); }
853 | K_DPORT skip_white '=' skip_white number
854 { proto_field_set_be16(hdr, TCP_DPORT, $5); }
855 | K_SEQ skip_white '=' skip_white number
856 { proto_field_set_be32(hdr, TCP_SEQ, $5); }
857 | K_ACK_SEQ skip_white '=' skip_white number
858 { proto_field_set_be32(hdr, TCP_ACK_SEQ, $5); }
859 | K_DOFF skip_white '=' skip_white number
860 { proto_field_set_be16(hdr, TCP_DOFF, $5); }
861 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
862 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
863 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
864 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
865 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
866 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
867 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
868 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
869 | K_WINDOW skip_white '=' skip_white number
870 { proto_field_set_be16(hdr, TCP_WINDOW, $5); }
871 | K_CSUM skip_white '=' skip_white number
872 { proto_field_set_be16(hdr, TCP_CSUM, $5); }
873 | K_URG_PTR skip_white '=' skip_white number
874 { proto_field_set_be16(hdr, TCP_URG_PTR, $5); }
878 : K_TCP { proto_add(PROTO_TCP); }
883 static void finalize_packet(void)
885 /* XXX hack ... we allocated one packet pointer too much */
886 plen--;
887 dlen--;
890 static void dump_conf(void)
892 size_t i, j;
894 for (i = 0; i < plen; ++i) {
895 printf("[%zu] pkt\n", i);
896 printf(" len %zu cnts %zu rnds %zu\n",
897 packets[i].len,
898 packet_dyn[i].clen,
899 packet_dyn[i].rlen);
901 printf(" payload ");
902 for (j = 0; j < packets[i].len; ++j)
903 printf("%02x ", packets[i].payload[j]);
904 printf("\n");
906 for (j = 0; j < packet_dyn[i].clen; ++j)
907 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
908 packet_dyn[i].cnt[j].min,
909 packet_dyn[i].cnt[j].max,
910 packet_dyn[i].cnt[j].inc,
911 (intmax_t)packet_dyn[i].cnt[j].off,
912 packet_dyn[i].cnt[j].type == TYPE_INC ?
913 "inc" : "dec");
915 for (j = 0; j < packet_dyn[i].rlen; ++j)
916 printf(" rnd%zu off %jd\n", j,
917 (intmax_t)packet_dyn[i].rnd[j].off);
921 void cleanup_packets(void)
923 size_t i;
925 for (i = 0; i < plen; ++i) {
926 if (packets[i].len > 0)
927 xfree(packets[i].payload);
930 free(packets);
932 for (i = 0; i < dlen; ++i) {
933 free(packet_dyn[i].cnt);
934 free(packet_dyn[i].rnd);
937 free(packet_dyn);
940 void compile_packets(char *file, bool verbose, unsigned int cpu,
941 bool invoke_cpp, char *const cpp_argv[])
943 char tmp_file[128];
944 int ret = -1;
946 memset(tmp_file, 0, sizeof(tmp_file));
947 our_cpu = cpu;
949 if (invoke_cpp) {
950 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
951 fprintf(stderr, "Failed to invoke C preprocessor!\n");
952 goto err;
954 file = tmp_file;
957 if (!strncmp("-", file, strlen("-")))
958 yyin = stdin;
959 else
960 yyin = fopen(file, "r");
961 if (!yyin) {
962 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
963 goto err;
966 realloc_packet();
967 if (yyparse() != 0)
968 goto err;
969 finalize_packet();
971 if (our_cpu == 0 && verbose)
972 dump_conf();
974 ret = 0;
975 err:
976 if (yyin && yyin != stdin)
977 fclose(yyin);
979 if (invoke_cpp)
980 unlink(tmp_file);
981 if (ret)
982 die();
985 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
987 int ret = 1;
989 our_cpu = cpu;
990 realloc_packet();
992 yy_scan_string(str);
993 if (yyparse() != 0)
994 goto err;
996 finalize_packet();
997 if (our_cpu == 0 && verbose)
998 dump_conf();
1000 ret = 0;
1001 err:
1002 yylex_destroy();
1004 if (ret)
1005 die();
1008 void yyerror(const char *err)
1010 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);