summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Kochan <vadim4j@gmail.com>2016-01-26 22:25:07 +0200
committerTobias Klauser <tklauser@distanz.ch>2016-01-28 16:30:50 +0100
commit6b845387e5bf5f2b7c584900c87ac41daa1acf36 (patch)
tree1fcdc23e9addc14207f70d146a5f14b52c9a2dd9
parentfac5a67eb5d4928f7efbf1f0d731a7e93f0f8193 (diff)
trafgen: parser: Add syntax to generate ARP header fields
Add function 'arp()' to support generating ARP header fields from the trafgen configuration language. Supported fields: htype hardware type, default: 1 (Ethernet) ptype protocol type, default: 0x0800 (IP) op|oper operation (req|request, reply, <num>), default: 1 (request) sha|smac sender MAC address, default: device MAC spa|sip sender IP address, default: device IP tha|tmac target MAC address, default: 00:00:00:00:00:00 tpa|tip target IP address, default: 0.0.0.0 Note: setting hlen and tlen is not supported, these will by set to hlen=6 and plen=4 in any case. Example usage: { arp(op=request, sip=1.1.1.1, smac=11:22:33:44:55:66, tip=42.42.42.42) } { arp() } Signed-off-by: Vadim Kochan <vadim4j@gmail.com> [tk: document keywords in commit message] Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--trafgen_lexer.l17
-rw-r--r--trafgen_parser.y48
2 files changed, 64 insertions, 1 deletions
diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index d209116..5467c70 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -15,6 +15,7 @@
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
+#include <arpa/inet.h>
#include "trafgen_parser.tab.h"
#include "xmalloc.h"
@@ -78,6 +79,7 @@ number_ascii ([a-zA-Z])
mac_hex ([a-fA-F0-9]+)
mac ({mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex})
+ip_addr ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)
%%
@@ -107,7 +109,18 @@ mac ({mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex})
"saddr"|"sa" { return K_SADDR; }
"prot"[o]? { return K_PROT; }
+"sha"|"smac" { return K_SHA; }
+"spa"|"sip" { return K_SPA; }
+"tha"|"tmac" { return K_THA; }
+"tpa"|"tip" { return K_TPA; }
+"req"|"request" { return K_REQUEST; }
+"reply" { return K_REPLY; }
+"op"|"oper" { return K_OPER; }
+"htype" { return K_HTYPE; }
+"ptype" { return K_PTYPE; }
+
"eth" { return K_ETH; }
+"arp" { return K_ARP; }
[ ]*"-"[ ]* { return '-'; }
[ ]*"+"[ ]* { return '+'; }
@@ -161,6 +174,10 @@ mac ({mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex})
panic("Failed to parse MAC address %s\n", yytext);
return mac; }
+{ip_addr} { if (inet_pton(AF_INET, yytext, &yylval.ip_addr) != 1)
+ panic("Failed to parse IPv4 address %s\n", yytext);
+ return ip_addr; };
+
"'\\x"[a-fA-F0-9]{2}"'" { yylval.number = strtol(yytext + 3, NULL, 16);
return number; }
diff --git a/trafgen_parser.y b/trafgen_parser.y
index df1b1a6..16f9025 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -17,6 +17,8 @@
#include <errno.h>
#include <stdbool.h>
#include <libgen.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
#include "xmalloc.h"
#include "trafgen_parser.tab.h"
@@ -337,6 +339,7 @@ static void proto_add(enum proto_id pid)
%}
%union {
+ struct in_addr ip_addr;
long long int number;
uint8_t bytes[256];
char *str;
@@ -346,15 +349,19 @@ static void proto_add(enum proto_id pid)
%token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
%token K_DADDR K_SADDR K_PROT
+%token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
+
%token K_ETH
+%token K_ARP
%token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
-%token number string mac
+%token number string mac ip_addr
%type <number> number expression
%type <str> string
%type <bytes> mac
+%type <ip_addr> ip_addr
%left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
@@ -566,6 +573,7 @@ ddec
proto
: eth_proto { }
+ | arp_proto { }
;
eth_proto
@@ -591,6 +599,44 @@ eth_field
{ proto_field_set_be16(hdr, ETH_PROTO_ID, $5); }
;
+arp_proto
+ : arp '(' arp_param_list ')' { }
+ ;
+
+arp_param_list
+ : { }
+ | arp_field { }
+ | arp_field delimiter arp_param_list { }
+ ;
+
+arp_field
+ : K_OPER skip_white '=' skip_white K_REQUEST
+ { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
+ | K_OPER skip_white '=' skip_white K_REPLY
+ { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
+ | K_OPER skip_white '=' skip_white number
+ { proto_field_set_be16(hdr, ARP_OPER, $5); }
+ | K_REQUEST
+ { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
+ | K_REPLY
+ { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
+ | K_HTYPE skip_white '=' skip_white number
+ { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
+ | K_PTYPE skip_white '=' skip_white number
+ { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
+ | K_SHA skip_white '=' skip_white mac
+ { proto_field_set_bytes(hdr, ARP_SHA, $5); }
+ | K_THA skip_white '=' skip_white mac
+ { proto_field_set_bytes(hdr, ARP_THA, $5); }
+ | K_SPA skip_white '=' skip_white ip_addr
+ { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
+ | K_TPA skip_white '=' skip_white ip_addr
+ { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
+ ;
+arp
+ : K_ARP { proto_add(PROTO_ARP); }
+ ;
+
%%
static void finalize_packet(void)