[netsniff-ng] Re: [PATCH 00/13] trafgen: Add proto header generation

2016-01-25 Thread Tobias Klauser
On 2016-01-25 at 10:06:04 +0100, Vadim Kochan  wrote:
> On Mon, Jan 25, 2016 at 09:56:37AM +0100, Tobias Klauser wrote:
> > On 2016-01-21 at 00:19:48 +0100, Vadim Kochan  wrote:
> > > Add new trafgen proto generation framework which allows to describe
> > > proto header fields and easy build the proto header by set/get proto
> > > header fields value.
> > 
> > This is great, thanks a lot for doing this! I only had the chance to
> > have a quick look at the series and couldn't find any major problems,
> > except for one thing: Please add a patch for trafgen.8, adding a section
> > which shortly describes the keywords, supported protocols, default
> > values for fields not specified etc. Having the user dig through git
> > commit messages or parser grammars to figure out how to use these
> > features is not very nice :)
> > 
> > Once you add that I think we can safely apply the series and fix any
> > remaining issues in follow-up patches. I'll also reply to some of the
> > patches with some minor comments which you might want to consider for v2
> > along with the changes you already announced.
> > 
> > Thanks!
> 
> BTW, I reworked to make possible to specify headers in any order and
> multiple times (which was not possible in previous version), so it
> allows to make such constructions like:
> 
> { ip(), ip(proto=0x1) }
> 
> which builds ip-in-ip header (including Ethernet). And now user
> responsible to specify the order of headers, but lower layers still will
> be added automatically if they were not specified by user.
> 
> Regarding man changes, well I did not include it because I am not good
> in English so to do not block this series in case of English issues I
> decided to work on it separately, but OK - I will try to document it.

I'm not a native English speaker/writer either, so no worries :) We can
still wordsmith on the documentation later on, or based on your patch.
The important part to me is that the keywords and the rules for protocol
default values are documented somewhere.

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 10/16] trafgen: l2: Add ARP header generation logic

2016-01-25 Thread Vadim Kochan
Add ARP proto header fields generation via src mac, src ip,
dst mac, dst ip & operaion.

By default Ethernet proto will be initialized, and ARP Announcement
request is filled.

Signed-off-by: Vadim Kochan 
---
 trafgen_l2.c | 52 
 trafgen_l2.h | 12 
 2 files changed, 64 insertions(+)

diff --git a/trafgen_l2.c b/trafgen_l2.c
index 1082049..a95ba91 100644
--- a/trafgen_l2.c
+++ b/trafgen_l2.c
@@ -3,10 +3,15 @@
  * Subject to the GPL, version 2.
  */
 
+#include 
+#include 
+
 #include "built_in.h"
 #include "trafgen_l2.h"
 #include "trafgen_proto.h"
 
+#define ETH_BCAST { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+
 struct proto_field eth_fields[] = {
{ .id = ETH_DST_ADDR, .len = 6, },
{ .id = ETH_SRC_ADDR, .len = 6, .offset = 6 },
@@ -26,7 +31,54 @@ static struct proto_hdr eth_hdr = {
.header_init= eth_header_init,
 };
 
+static struct proto_field arp_fields[] = {
+   { .id = ARP_HTYPE, .len = 2 },
+   { .id = ARP_PTYPE, .len = 2, .offset = 2 },
+   { .id = ARP_HLEN,  .len = 1, .offset = 4 },
+   { .id = ARP_PLEN,  .len = 1, .offset = 5 },
+   { .id = ARP_OPER,  .len = 2, .offset = 6 },
+   { .id = ARP_SHA,   .len = 6, .offset = 8 },
+   { .id = ARP_SPA,   .len = 4, .offset = 14 },
+   { .id = ARP_THA,   .len = 6, .offset = 18 },
+   { .id = ARP_TPA,   .len = 4, .offset = 24 },
+};
+
+static void arp_header_init(struct proto_hdr *hdr)
+{
+   struct proto_hdr *lower;
+
+   proto_lower_default_add(PROTO_ETH);
+
+   lower = proto_current_header();
+
+   if (lower->id == PROTO_ETH) {
+   uint8_t bcast[6] = ETH_BCAST;
+
+   proto_field_set_default_bytes(lower, ETH_DST_ADDR, bcast);
+   proto_field_set_default_be16(lower, ETH_PROTO_ID, ETH_P_ARP);
+   }
+
+   proto_header_fields_add(hdr, arp_fields, array_size(arp_fields));
+
+   /* Generate Announce request by default */
+   proto_field_set_default_be16(hdr, ARP_HTYPE, ARPHRD_ETHER);
+   proto_field_set_default_be16(hdr, ARP_PTYPE, ETH_P_IP);
+   proto_field_set_default_u8(hdr, ARP_HLEN, 6);
+   proto_field_set_default_u8(hdr, ARP_PLEN, 4);
+   proto_field_set_default_be16(hdr, ARP_OPER, ARPOP_REQUEST);
+   proto_field_set_default_dev_mac(hdr, ARP_SHA);
+   proto_field_set_default_dev_ipv4(hdr, ARP_SPA);
+   proto_field_set_default_dev_ipv4(hdr, ARP_TPA);
+}
+
+static struct proto_hdr arp_hdr = {
+   .id = PROTO_ARP,
+   .layer  = PROTO_L2,
+   .header_init= arp_header_init,
+};
+
 void protos_l2_init(void)
 {
proto_header_register(_hdr);
+   proto_header_register(_hdr);
 }
diff --git a/trafgen_l2.h b/trafgen_l2.h
index 75d3d33..63cef2f 100644
--- a/trafgen_l2.h
+++ b/trafgen_l2.h
@@ -7,6 +7,18 @@ enum eth_field {
ETH_PROTO_ID,
 };
 
+enum arp_field {
+   ARP_HTYPE,
+   ARP_PTYPE,
+   ARP_HLEN,
+   ARP_PLEN,
+   ARP_OPER,
+   ARP_SHA,
+   ARP_SPA,
+   ARP_THA,
+   ARP_TPA,
+};
+
 extern void protos_l2_init(void);
 
 #endif /* TRAFGEN_L2_I_H */
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 16/16] trafgen: man: Add help for Ethernet, ARP, IPv4, UDP headers

2016-01-25 Thread Vadim Kochan
Add description (basic syntax, proto header fields) for newer added
proto headers:

Ethernet, ARP, IPv4, UDP.

Signed-off-by: Vadim Kochan 
---
 trafgen.8 | 174 ++
 1 file changed, 174 insertions(+)

diff --git a/trafgen.8 b/trafgen.8
index ce82a5b..ae68a38 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -271,6 +271,180 @@ configuration, e.g. const16(0xaa) will result in ''00 
aa''. Within c*()
 functions, it is possible to do some arithmetics: -,+,*,/,%,&,|,<<,>>,^
 E.g. const161<<8)+0x32)|0b110)*2) will be evaluated to ''02 6c''.
 .PP
+IV) Proto header functions, fill protocol header with specified parameters.
+The protocol header follows the generic syntax:
+.in +8
+.sp
+(=,=,...,,...)
+.sp
+.in -8
+.in +4
+Parameter might be ignored and specified in any order, once parameter is set
+- the default value is ignored. So just proto header might be specified.
+.sp
+All required lower layer headers will be filled automatically in case if they
+were not specified by the user. The headers will be filled in the order as they
+were specified. Each header will be filled with some mimimum required set of 
fields.
+.in -4
+.sp
+.in +4
+Supported proto headers:
+.sp
+
+.in +4
+.I Ethernet
+:
+.B eth(da=, sa=, prot[o]=)
+.sp
+.in +15
+.B da|daddr
+- set destination MAC address (default 00:00:00:00:00:00).
+.sp
+.B sa|saddr
+- set source MAC address (default device's MAC address).
+.sp
+.B prot|proto
+- set Ethernet type/proro number (default 0).
+.in -15
+.in -4
+
+.in +4
+.I ARP
+:
+.B arp(op=, smac=, sip=, tmac=, 
tip=)
+.sp
+.in +15
+.B op
+- set ARP operation type (request/reply/response) (default request).
+.sp
+.B smac|sha
+- set sender HW (MAC) address (default device's MAC address).
+.sp
+.B sip|spa
+- set sender proto (IPv4) address (default device's IPv4 address).
+.sp
+.B tmac|tha
+- set target HW (MAC) address (default 00:00:00:00:00:00).
+.sp
+.B tip|tpa
+- set target proto (IPv4) address (default device's IPv4 address).
+.in -15
+.sp
+.in +4
+By default ARP Announcement request packet is filled, Ethernet destination MAC
+set to broadcast.
+.in -4
+.in -4
+
+.in +4
+.I IPv4
+:
+.B ip4|ipv4(ihl=, ver=, len=, csum=,
+.B ttl=, tos=, dscp=, ecn=,
+.in +15
+.B id=, flags=, frag=, df, mf, da=, 
sa=,
+.B prot[o]=)
+.in -15
+.sp
+.in +15
+.B ver|version
+- set version field (default 4).
+.sp
+.B ihl
+- set header length in the numbers of 4 bytes (default 5).
+.sp
+.B tos
+- set TOS (Type Of Service) field (default 0).
+.sp
+.B dscp
+- set DSCP (DiffServ) field (default 0).
+.sp
+.B ecn
+- set ECN field (default 0).
+.sp
+.B len|length
+- set total length of header and data (calculated by default).
+.sp
+.B id
+- set IPv4 datagram identificator (default 0).
+.sp
+.B flags
+- set IPv4 flags value (DF,MF) (default 0).
+.sp
+.B df
+- set DF (dont fragment) flag (default 0).
+.sp
+.B mf
+- set MF (more fragment) flag (default 0).
+.sp
+.B frag
+- set fragment offset field in numbers of 8 bytes (default 0).
+.sp
+.B ttl
+- set TTL (time to live) field (default 0).
+.sp
+.B csum
+- set header checksum field (calculated by default).
+.sp
+.B sa|saddr
+- set source IPv4 address (default device's IPv4 address).
+.sp
+.B da|daddr
+- set destination IPv4 address (default 0.0.0.0).
+.sp
+.B prot|proto
+- set IPv4 proro number (default 0).
+.in -15
+.sp
+.in +4
+By default if lower header is Ethernet - ether type is set to IPv4,
+if lower header is IPv4 - proto is set to value 0x4 (IP-in-IP).
+.in -4
+.in -4
+
+.in +4
+.I UDP
+:
+.B udp(sp=, dp=, len=, csum=)
+.sp
+.in +15
+.B sp|sport
+- set source UDP port (default 0).
+.sp
+.B dp|dport
+- set destination UDP port (default 0).
+.sp
+.B len|length
+- set length field of UDP header and data (calculated by default).
+.sp
+.B csum
+- set checksum field calculated on IPv4 pseudo header (calculated by default).
+.sp
+.in -15
+.in +4
+By default if lower header is IPv4 - proto is set to UDP.
+.in -4
+.in -4
+
+Example of some invalid DNS packet:
+.sp
+.in +4
+{
+.in +4
+eth(da=11:22:33:44:55:66),
+.sp
+ip4(da=2.2.2.2),
+.sp
+udp(sp=111, dp=53),
+.sp
+fill(0xff, 10),
+.in -4
+}
+.in -4
+
+.in -4
+
+.PP
 Furthermore, there are two types of comments in trafgen configuration files:
 .PP
   1. Multi-line C-style comments:/* put comment here */
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 08/16] trafgen: parser: Add syntax to generate Ethernet header

2016-01-25 Thread Vadim Kochan
Add syntax for generating Ethernet header fields like:

{ eth(prot=0x0800, da=11:22:33:44:55:66), fill(0xff, 60) }
{ eth(prot=0x0800) }
{ eth() }

It is important that proto_init is called before fields will be filled
to initialize the specified proto with header fields.

Signed-off-by: Vadim Kochan 
---
 trafgen_lexer.l  | 15 +++
 trafgen_parser.y | 57 +++-
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index 6c27b0c..ac4fec1 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -19,6 +19,7 @@
 #include "trafgen_parser.tab.h"
 #include "xmalloc.h"
 #include "built_in.h"
+#include "str.h"
 
 extern void yyerror(const char *);
 
@@ -75,6 +76,9 @@ number_bin([0]?[b][0-1]+)
 number_dec (([0])|([1-9][0-9]*))
 number_ascii   ([a-zA-Z])
 
+mac_hex([a-fA-F0-9]+)
+mac({mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex})
+
 %%
 
 "cpu"  { return K_CPU; }
@@ -99,6 +103,12 @@ number_ascii([a-zA-Z])
 "const32"|"c32"{ return K_CONST32; }
 "const64"|"c64"{ return K_CONST64; }
 
+"daddr"|"da"   { return K_DADDR; }
+"saddr"|"sa"   { return K_SADDR; }
+"prot"[o]? { return K_PROT; }
+
+"eth"  { return K_ETH; }
+
 [ ]*"-"[ ]*{ return '-'; }
 [ ]*"+"[ ]*{ return '+'; }
 [ ]*"*"[ ]*{ return '*'; }
@@ -117,6 +127,7 @@ number_ascii([a-zA-Z])
 "]"{ return ']'; }
 ","{ return ','; }
 ":"{ return ':'; }
+"="{ return '='; }
 
 "\n"   { yylineno++; }
 
@@ -146,6 +157,10 @@ number_ascii   ([a-zA-Z])
 {number_ascii} { yylval.number = (uint8_t) (*yytext);
  return number; }
 
+{mac}  { if (str2mac(yytext, yylval.bytes))
+   panic("Failed to parse MAC addres %s\n", yytext);
+ return mac; }
+
 "'\\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 4725f7c..df1b1a6 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -21,6 +21,8 @@
 #include "xmalloc.h"
 #include "trafgen_parser.tab.h"
 #include "trafgen_conf.h"
+#include "trafgen_proto.h"
+#include "trafgen_l2.h"
 #include "built_in.h"
 #include "die.h"
 #include "str.h"
@@ -59,6 +61,8 @@ extern size_t dlen;
 
 static int our_cpu, min_cpu = -1, max_cpu = -1;
 
+static struct proto_hdr *hdr;
+
 static inline int test_ignore(void)
 {
if (min_cpu < 0 && max_cpu < 0)
@@ -324,22 +328,33 @@ static void set_dynamic_incdec(uint8_t start, uint8_t 
stop, uint8_t stepping,
__setup_new_counter(>cnt[packetdc_last], start, stop, stepping, 
type);
 }
 
+static void proto_add(enum proto_id pid)
+{
+   proto_header_init(pid);
+   hdr = proto_current_header();
+}
+
 %}
 
 %union {
long long int number;
+   uint8_t bytes[256];
char *str;
 }
 
 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
 %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_ETH
+
 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
 
-%token number string
+%token number string mac
 
 %type  number expression
 %type  string
+%type  mac
 
 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
 
@@ -372,9 +387,16 @@ noenforce_white
| delimiter_nowhite { }
;
 
+skip_white
+   : { }
+   | K_WHITE { }
+   ;
 packet
: '{' noenforce_white payload noenforce_white '}' {
min_cpu = max_cpu = -1;
+
+   proto_packet_finish();
+
realloc_packet();
}
| K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' 
noenforce_white payload noenforce_white '}' {
@@ -388,10 +410,15 @@ packet
max_cpu = tmp;
}
 
+   proto_packet_finish();
+
realloc_packet();
}
| K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload 
noenforce_white '}' {
min_cpu = max_cpu = $3;
+
+   proto_packet_finish();
+
realloc_packet();
}
;
@@ -422,6 +449,7 @@ elem
| ddec { }
| csum { }
| const { }
+   | proto { proto_header_finish(hdr); }
| inline_comment { }
;
 
@@ -536,6 +564,33 @@ ddec
{ set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
;
 
+proto
+   : eth_proto { }
+   ;
+
+eth_proto
+   : eth '(' eth_param_list ')' { }
+   ;
+
+eth
+   : K_ETH { proto_add(PROTO_ETH); }
+   ;
+
+eth_param_list
+   : { }
+   | eth_field { }
+   | eth_field delimiter eth_param_list { }
+  

[netsniff-ng] [PATCH v2 09/16] trafgen: proto: Add func to fill field with device ipv4 addr

2016-01-25 Thread Vadim Kochan
Add helper which fill device's ipv4 addr to the specified proto field.

It will be used by such protos like ARP, IPv4, etc.

Signed-off-by: Vadim Kochan 
---
 trafgen_proto.c | 32 
 trafgen_proto.h |  3 +++
 2 files changed, 35 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index efa6803..dac806e 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "dev.h"
@@ -326,6 +327,37 @@ void proto_field_set_default_dev_mac(struct proto_hdr 
*hdr, uint32_t fid)
__proto_field_set_dev_mac(hdr, fid, true);
 }
 
+static void __proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
+  bool is_default)
+{
+   struct sockaddr_storage ss = { };
+   struct sockaddr_in *ss4;
+   uint32_t ip_addr;
+   int ret;
+
+   if (proto_field_is_set(hdr, fid))
+   return;
+
+   ret = device_address(hdr->ctx->dev, AF_INET, );
+   if (ret < 0)
+   panic("Could not get device IPv4 address\n");
+
+   ss4 = (struct sockaddr_in *) 
+   ip_addr = ss4->sin_addr.s_addr;
+
+   __proto_field_set_bytes(hdr, fid, (uint8_t *)_addr, is_default, 
false);
+}
+
+void proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
+{
+   __proto_field_set_dev_ipv4(hdr, fid, false);
+}
+
+void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
+{
+   __proto_field_set_dev_ipv4(hdr, fid, true);
+}
+
 void protos_init(char *dev)
 {
struct proto_hdr *p;
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 4041c27..b0578e3 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -96,4 +96,7 @@ extern void proto_field_set_default_be32(struct proto_hdr 
*hdr, uint32_t fid,
 extern void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid);
 extern void proto_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t 
fid);
 
+extern void proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid);
+extern void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t 
fid);
+
 #endif /* TRAFGEN_PROTO_I_H */
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 14/16] trafgen: l4: Add UDP header generation logic

2016-01-25 Thread Vadim Kochan
Add trafgen_l4.c module with implementation
of UDP header fields gneration.

UDP proto generation logic automaticaly sets by default
IPPROTO_UDP to the lower proto if it is IPv4, also cscum is
calculated if it is not set by user.

Signed-off-by: Vadim Kochan 
---
 trafgen/Makefile |  1 +
 trafgen_l4.c | 71 
 trafgen_l4.h | 14 +++
 trafgen_proto.c  |  2 ++
 4 files changed, 88 insertions(+)
 create mode 100644 trafgen_l4.c
 create mode 100644 trafgen_l4.h

diff --git a/trafgen/Makefile b/trafgen/Makefile
index 4f342ca..3f78f07 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -22,6 +22,7 @@ trafgen-objs =xmalloc.o \
trafgen_proto.o \
trafgen_l2.o \
trafgen_l3.o \
+   trafgen_l4.o \
trafgen_lexer.yy.o \
trafgen_parser.tab.o \
trafgen.o
diff --git a/trafgen_l4.c b/trafgen_l4.c
new file mode 100644
index 000..286e54a
--- /dev/null
+++ b/trafgen_l4.c
@@ -0,0 +1,71 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include 
+#include 
+
+#include "die.h"
+#include "csum.h"
+#include "built_in.h"
+#include "trafgen_l3.h"
+#include "trafgen_l4.h"
+#include "trafgen_conf.h"
+#include "trafgen_proto.h"
+
+static struct proto_field udp_fields[] = {
+   { .id = UDP_SPORT,  .len = 2,   .offset = 0 },
+   { .id = UDP_DPORT,  .len = 2,   .offset = 2 },
+   { .id = UDP_LEN,.len = 2,   .offset = 4 },
+   { .id = UDP_CSUM,   .len = 2,   .offset = 6 },
+};
+
+static void udp_header_init(struct proto_hdr *hdr)
+{
+   struct proto_hdr *lower;
+
+   proto_lower_default_add(PROTO_IP4);
+
+   lower = proto_current_header();
+
+   if (lower->id == PROTO_IP4)
+   proto_field_set_default_u8(lower, IP4_PROTO, IPPROTO_UDP);
+
+   proto_header_fields_add(hdr, udp_fields, array_size(udp_fields));
+}
+
+static void udp_packet_finish(struct proto_hdr *hdr)
+{
+   struct proto_hdr *lower = proto_lower_header(hdr);
+   struct packet *pkt = current_packet();
+   uint16_t total_len;
+   uint16_t csum;
+
+   total_len = pkt->len - hdr->pkt_offset;
+   proto_field_set_default_be16(hdr, UDP_LEN, total_len);
+
+   if (proto_field_is_set(hdr, UDP_CSUM))
+   return;
+
+   if (!lower || lower->id != PROTO_IP4)
+   return;
+
+   total_len = proto_field_get_u16(hdr, UDP_LEN);
+   csum = p4_csum((void *) proto_header_ptr(lower), proto_header_ptr(hdr),
+   total_len, IPPROTO_UDP);
+
+   proto_field_set_be16(hdr, UDP_CSUM, bswap_16(csum));
+}
+
+static struct proto_hdr udp_hdr = {
+   .id = PROTO_UDP,
+   .layer  = PROTO_L4,
+   .header_init= udp_header_init,
+   .packet_finish  = udp_packet_finish,
+};
+
+void protos_l4_init(void)
+{
+   proto_header_register(_hdr);
+}
diff --git a/trafgen_l4.h b/trafgen_l4.h
new file mode 100644
index 000..1a60ea5
--- /dev/null
+++ b/trafgen_l4.h
@@ -0,0 +1,14 @@
+#ifndef TRAFGEN_L4_I_H
+#define TRAFGEN_L4_I_H
+
+enum udp_field {
+   UDP_SPORT,
+   UDP_DPORT,
+   UDP_LEN,
+   UDP_CSUM,
+};
+
+extern void protos_l4_init(void);
+
+#endif /* TRAFGEN_L4_I_H */
+
diff --git a/trafgen_proto.c b/trafgen_proto.c
index e803f27..a36c0af 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -13,6 +13,7 @@
 #include "trafgen_conf.h"
 #include "trafgen_l2.h"
 #include "trafgen_l3.h"
+#include "trafgen_l4.h"
 #include "trafgen_proto.h"
 
 #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
@@ -367,6 +368,7 @@ void protos_init(char *dev)
 
protos_l2_init();
protos_l3_init();
+   protos_l4_init();
 
for (p = registered; p; p = p->next)
p->ctx = 
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 02/16] trafgen: Add helper to get current packet

2016-01-25 Thread Vadim Kochan
Add current_packet() helper for getting current
used packet and make it public to other modules.

It will be used by proto generation logic.

Signed-off-by: Vadim Kochan 
---
 trafgen_conf.h   | 2 ++
 trafgen_parser.y | 5 +
 2 files changed, 7 insertions(+)

diff --git a/trafgen_conf.h b/trafgen_conf.h
index 887fa3d..50b437b 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -62,4 +62,6 @@ extern void cleanup_packets(void);
 
 extern void set_fill(uint8_t val, size_t len);
 
+extern struct packet *current_packet(void);
+
 #endif /* TRAFGEN_CONF */
diff --git a/trafgen_parser.y b/trafgen_parser.y
index 49ee577..4725f7c 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -137,6 +137,11 @@ static void realloc_packet(void)
__init_new_csum_slot(_dyn[packetd_last]);
 }
 
+struct packet *current_packet(void)
+{
+   return [packet_last];
+}
+
 static void set_byte(uint8_t val)
 {
struct packet *pkt = [packet_last];
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 03/16] trafgen: Add basic proto generation logic

2016-01-25 Thread Vadim Kochan
Add new trafgen_proto.c module with basic proto
header fields generation logic.

Each proto must implement proto_hdr struct and register it
to the global proto list.

Proto header consist from set of fields, and each field must be
described via proto_field struct by specifying unique id, len,
offset (relative to the header). Small fields ( < 8 bits) can be
described via left shift & mask.

Few callbacks are invoked to perform special actions to build
the header:

1) header_init - required fields must be added to the packet and
initialized with default values.

2) header_finish - it is invoked when header is specified, all user
specified fields are set.

3) packet_finish - callback is invoked from upper to lower header
to calculate such things like total len, checksum.

Proto generation API provides easy proto field setters/getters to easy
craft the packet via parser.

Signed-off-by: Vadim Kochan 
---
 trafgen.c|   3 +
 trafgen/Makefile |   1 +
 trafgen_proto.c  | 331 +++
 trafgen_proto.h  |  96 
 4 files changed, 431 insertions(+)
 create mode 100644 trafgen_proto.c
 create mode 100644 trafgen_proto.h

diff --git a/trafgen.c b/trafgen.c
index c74a973..949f909 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -54,6 +54,7 @@
 #include "timer.h"
 #include "ring_tx.h"
 #include "csum.h"
+#include "trafgen_proto.h"
 
 #ifndef timeval_to_timespec
 #define timeval_to_timespec(tv, ts) { \
@@ -1215,6 +1216,8 @@ int main(int argc, char **argv)
register_signal(SIGTERM, signal_handler);
register_signal(SIGHUP, signal_handler);
 
+   protos_init(ctx.device);
+
if (prio_high) {
set_proc_prio(-20);
set_sched_status(SCHED_FIFO, 
sched_get_priority_max(SCHED_FIFO));
diff --git a/trafgen/Makefile b/trafgen/Makefile
index bc256b2..2ea684f 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -19,6 +19,7 @@ trafgen-objs =xmalloc.o \
timer.o \
sysctl.o \
cpp.o \
+   trafgen_proto.o \
trafgen_lexer.yy.o \
trafgen_parser.tab.o \
trafgen.o
diff --git a/trafgen_proto.c b/trafgen_proto.c
new file mode 100644
index 000..787da7a
--- /dev/null
+++ b/trafgen_proto.c
@@ -0,0 +1,331 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include 
+#include 
+
+#include "xmalloc.h"
+#include "trafgen_conf.h"
+#include "trafgen_proto.h"
+
+#define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
+   ((f)->mask ? (f)->mask : (0x)))
+
+#define field_unmask_and_unshift(f, v) (((v) & \
+   ((f)->mask ? (f)->mask : (0x))) >> (f)->shift)
+
+static struct proto_ctx ctx;
+
+#define PROTO_MAX_LAYERS   16
+
+static struct proto_hdr *headers[PROTO_MAX_LAYERS];
+static uint32_t headers_count;
+
+static struct proto_hdr *registered;
+
+struct proto_hdr *proto_current_header(void)
+{
+   if (headers_count > 0)
+   return headers[headers_count - 1];
+
+   panic("No header was added\n");
+}
+
+struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
+{
+   struct proto_hdr *lower = NULL;
+   uint32_t i;
+
+   if (headers_count == 0)
+   return NULL;
+
+   for (i = 1, lower = headers[0]; i < headers_count; i++) {
+   if (headers[i] == hdr)
+   return headers[i - 1];
+   }
+
+   return lower;
+}
+
+uint8_t *proto_header_ptr(struct proto_hdr *hdr)
+{
+   return _packet()->payload[hdr->pkt_offset];
+}
+
+static struct proto_hdr *proto_header_by_id(enum proto_id id)
+{
+   struct proto_hdr *p = registered;
+
+   for (; p; p = p->next)
+   if (p->id == id)
+   return p;
+
+   panic("Can't lookup proto by id %u\n", id);
+}
+
+void proto_header_register(struct proto_hdr *hdr)
+{
+   hdr->next = registered;
+   registered = hdr;
+
+   hdr->fields = NULL;
+   hdr->fields_count = 0;
+}
+
+static void proto_fields_realloc(struct proto_hdr *hdr, size_t count)
+{
+   hdr->fields = xrealloc(hdr->fields, count * sizeof(*hdr->fields));
+   hdr->fields_count = count;
+}
+
+void proto_header_fields_add(struct proto_hdr *hdr, struct proto_field *fields,
+size_t count)
+{
+   struct packet *pkt = current_packet();
+   struct proto_field *f;
+   int i;
+
+   if (!hdr->fields)
+   hdr->pkt_offset = pkt->len;
+
+   proto_fields_realloc(hdr, hdr->fields_count + count);
+
+   for (i = 0; count >= 1; count--, i++) {
+   f = >fields[hdr->fields_count - count];
+
+   f->id = fields[i].id;
+   f->len = fields[i].len;
+   f->is_set = false;
+   f->shift = fields[i].shift;
+   f->mask = 

[netsniff-ng] [PATCH v2 01/16] trafgen: Export set_fill func

2016-01-25 Thread Vadim Kochan
Make public set_fill func to be used by proto generation code.

Signed-off-by: Vadim Kochan 
---
 trafgen_conf.h   | 2 ++
 trafgen_parser.y | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/trafgen_conf.h b/trafgen_conf.h
index b171798..887fa3d 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -60,4 +60,6 @@ extern void compile_packets(char *file, bool verbose, 
unsigned int cpu,
bool invoke_cpp, char *const cpp_argv[]);
 extern void cleanup_packets(void);
 
+extern void set_fill(uint8_t val, size_t len);
+
 #endif /* TRAFGEN_CONF */
diff --git a/trafgen_parser.y b/trafgen_parser.y
index 79a8439..49ee577 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -157,7 +157,7 @@ static void set_multi_byte(uint8_t *s, size_t len)
set_byte(s[i]);
 }
 
-static void set_fill(uint8_t val, size_t len)
+void set_fill(uint8_t val, size_t len)
 {
size_t i;
struct packet *pkt = [packet_last];
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 11/16] trafgen: parser: Add syntax to generate ARP header fields

2016-01-25 Thread Vadim Kochan
Add syntax to generate ARP header fields:

{ arp(op=req, sip=1.1.1.1, smac=11:22:33:44:55:66) }
{ arp() }

Signed-off-by: Vadim Kochan 
---
 trafgen_lexer.l  | 15 +++
 trafgen_parser.y | 38 +-
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index ac4fec1..e89d8c8 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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,16 @@ 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"  { return K_REQ; }
+"resp"|"reply" { return K_RESP; }
+"op"   { return K_OPER; }
+
 "eth"  { return K_ETH; }
+"arp"  { return K_ARP; }
 
 [ ]*"-"[ ]*{ return '-'; }
 [ ]*"+"[ ]*{ return '+'; }
@@ -161,6 +172,10 @@ mac
({mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex})
panic("Failed to parse MAC addres %s\n", yytext);
  return mac; }
 
+{ip_addr}  { if (inet_pton(AF_INET, yytext, _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..5c9dcd9 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -17,6 +17,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #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_REQ K_RESP
+
 %token K_ETH
+%token K_ARP
 
 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
 
-%token number string mac
+%token number string mac ip_addr
 
 %type  number expression
 %type  string
 %type  mac
+%type  ip_addr
 
 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
 
@@ -566,6 +573,7 @@ ddec
 
 proto
: eth_proto { }
+   | arp_proto { }
;
 
 eth_proto
@@ -591,6 +599,34 @@ 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_REQ
+   { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
+   | K_OPER  skip_white '=' skip_white K_RESP
+   { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
+   | 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)
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 15/16] trafgen: parser: Add syntax to build UDP header

2016-01-25 Thread Vadim Kochan
Added trafgen syntax to set UDP header fields:

{ udp(sport=111, dport=222) }

Signed-off-by: Vadim Kochan 
---
 trafgen_lexer.l  |  4 
 trafgen_parser.y | 29 +
 2 files changed, 33 insertions(+)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index 26876b4..98afc91 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -131,9 +131,13 @@ ip_addr([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)
 "df"   { return K_DF; }
 "mf"   { return K_MF; }
 
+"sp"|"sport"   { return K_SPORT; }
+"dp"|"dport"   { return K_DPORT; }
+
 "eth"  { return K_ETH; }
 "arp"  { return K_ARP; }
 "ip4"|"ipv4"   { return K_IP4; }
+"udp"  { return K_UDP; }
 
 [ ]*"-"[ ]*{ return '-'; }
 [ ]*"+"[ ]*{ return '+'; }
diff --git a/trafgen_parser.y b/trafgen_parser.y
index 7ca8ef2..4838a8b 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -26,6 +26,7 @@
 #include "trafgen_proto.h"
 #include "trafgen_l2.h"
 #include "trafgen_l3.h"
+#include "trafgen_l4.h"
 #include "built_in.h"
 #include "die.h"
 #include "str.h"
@@ -352,10 +353,12 @@ static void proto_add(enum proto_id pid)
 %token K_DADDR K_SADDR K_PROT
 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQ K_RESP
 %token 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
+%token K_SPORT K_DPORT
 
 %token K_ETH
 %token K_ARP
 %token K_IP4
+%token K_UDP
 
 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
 
@@ -578,6 +581,7 @@ proto
: eth_proto { }
| arp_proto { }
| ip4_proto { }
+   | udp_proto { }
;
 
 eth_proto
@@ -678,6 +682,31 @@ ip4
: K_IP4 { proto_add(PROTO_IP4); }
;
 
+udp_proto
+   : udp '(' udp_param_list ')' { }
+   ;
+
+udp_param_list
+   : { }
+   | udp_field { }
+   | udp_field delimiter udp_param_list { }
+   ;
+
+udp_field
+   : K_SPORT  skip_white '=' skip_white number
+   { proto_field_set_be16(hdr, UDP_SPORT, $5); }
+   | K_DPORT  skip_white '=' skip_white number
+   { proto_field_set_be16(hdr, UDP_DPORT, $5); }
+   | K_LEN skip_white '=' skip_white number
+   { proto_field_set_be16(hdr, UDP_LEN, $5); }
+   | K_CSUM skip_white '=' skip_white number
+   { proto_field_set_be16(hdr, UDP_CSUM, $5); }
+   ;
+
+udp
+   : K_UDP { proto_add(PROTO_UDP); }
+   ;
+
 %%
 
 static void finalize_packet(void)
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] [PATCH v2 12/16] trafgen: l3: Add IPv4 header generation backend

2016-01-25 Thread Vadim Kochan
Add L3 module for implement L3 layer protos generation.

Implemented generating of IPv4 header with all fields except options.
By default IPv4 address of output device is used as src ip address.
On finish (after packet is specified) - total len & checksum is calculated.

Meanwhile Ethernet proto is initialized as default underlying proto.

Signed-off-by: Vadim Kochan 
---
 trafgen/Makefile |  1 +
 trafgen_l3.c | 82 
 trafgen_l3.h | 26 ++
 trafgen_proto.c  |  2 ++
 4 files changed, 111 insertions(+)
 create mode 100644 trafgen_l3.c
 create mode 100644 trafgen_l3.h

diff --git a/trafgen/Makefile b/trafgen/Makefile
index 1c95118..4f342ca 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -21,6 +21,7 @@ trafgen-objs =xmalloc.o \
cpp.o \
trafgen_proto.o \
trafgen_l2.o \
+   trafgen_l3.o \
trafgen_lexer.yy.o \
trafgen_parser.tab.o \
trafgen.o
diff --git a/trafgen_l3.c b/trafgen_l3.c
new file mode 100644
index 000..dd45395
--- /dev/null
+++ b/trafgen_l3.c
@@ -0,0 +1,82 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include 
+
+#include "csum.h"
+#include "built_in.h"
+#include "trafgen_l2.h"
+#include "trafgen_l3.h"
+#include "trafgen_proto.h"
+#include "trafgen_conf.h"
+
+static struct proto_field ipv4_fields[] = {
+   { .id = IP4_VER,   .len = 1, .offset = 0, .shift = 4, .mask = 0xf0 
},
+   { .id = IP4_IHL,   .len = 1, .offset = 0, .shift = 0, .mask = 0x0f 
},
+   { .id = IP4_DSCP,  .len = 1, .offset = 1, .shift = 2, .mask = 0xfc 
},
+   { .id = IP4_ECN,   .len = 1, .offset = 1, .shift = 0, .mask = 0x03 
},
+   { .id = IP4_TOS,   .len = 1, .offset = 1 },
+   { .id = IP4_LEN,   .len = 2, .offset = 2 },
+   { .id = IP4_ID,.len = 2, .offset = 4 },
+   { .id = IP4_FLAGS, .len = 2, .offset = 6, .shift = 13, .mask = 
0xe000 },
+   { .id = IP4_MF,.len = 2, .offset = 6, .shift = 13, .mask = 
0x2000 },
+   { .id = IP4_DF,.len = 2, .offset = 6, .shift = 14, .mask = 
0x4000 },
+   { .id = IP4_FRAG_OFFS, .len = 2, .offset = 6, .shift = 0,  .mask = 
0x1fff },
+   { .id = IP4_TTL,   .len = 1, .offset = 8 },
+   { .id = IP4_PROTO, .len = 1, .offset = 9 },
+   { .id = IP4_CSUM,  .len = 2, .offset = 10 },
+   { .id = IP4_SADDR, .len = 4, .offset = 12 },
+   { .id = IP4_DADDR, .len = 4, .offset = 16 },
+};
+
+static void ipv4_header_init(struct proto_hdr *hdr)
+{
+   struct proto_hdr *lower;
+
+   proto_lower_default_add(PROTO_ETH);
+
+   lower = proto_current_header();
+
+   if (lower->id == PROTO_ETH)
+   proto_field_set_default_be16(lower, ETH_PROTO_ID, ETH_P_IP);
+   else if (lower->id == PROTO_IP4)
+   proto_field_set_default_u8(lower, IP4_PROTO, IPPROTO_IPIP);
+
+   proto_header_fields_add(hdr, ipv4_fields, array_size(ipv4_fields));
+
+   proto_field_set_default_u8(hdr, IP4_VER, 4);
+   proto_field_set_default_u8(hdr, IP4_IHL, 5);
+   proto_field_set_default_dev_ipv4(hdr, IP4_SADDR);
+}
+
+static void ipv4_packet_finish(struct proto_hdr *hdr)
+{
+   struct packet *pkt = current_packet();
+   uint16_t total_len;
+
+   total_len = pkt->len - hdr->pkt_offset;
+   proto_field_set_default_be16(hdr, IP4_LEN, total_len);
+
+   if (!proto_field_is_set(hdr, IP4_CSUM)) {
+   uint16_t csum;
+   uint8_t ihl;
+
+   ihl = proto_field_get_u8(hdr, IP4_IHL);
+   csum = htons(calc_csum(>payload[hdr->pkt_offset], ihl * 
4));
+   proto_field_set_u16(hdr, IP4_CSUM, bswap_16(csum));
+   }
+}
+
+static struct proto_hdr ipv4_hdr = {
+   .id = PROTO_IP4,
+   .layer  = PROTO_L3,
+   .header_init= ipv4_header_init,
+   .packet_finish  = ipv4_packet_finish,
+};
+
+void protos_l3_init(void)
+{
+   proto_header_register(_hdr);
+}
diff --git a/trafgen_l3.h b/trafgen_l3.h
new file mode 100644
index 000..d215d09
--- /dev/null
+++ b/trafgen_l3.h
@@ -0,0 +1,26 @@
+#ifndef TRAFGEN_L3_I_H
+#define TRAFGEN_L3_I_H
+
+enum ip4_field {
+   IP4_VER,
+   IP4_IHL,
+   IP4_DSCP,
+   IP4_ECN,
+   IP4_TOS,
+   IP4_LEN,
+   IP4_ID,
+   IP4_FLAGS,
+   IP4_FRAG_OFFS,
+   IP4_TTL,
+   IP4_PROTO,
+   IP4_CSUM,
+   IP4_SADDR,
+   IP4_DADDR,
+   IP4_DF,
+   IP4_MF,
+};
+
+extern void protos_l3_init(void);
+
+#endif /* TRAFGEN_L2_I_H */
+
diff --git a/trafgen_proto.c b/trafgen_proto.c
index dac806e..e803f27 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -12,6 +12,7 @@
 #include "xmalloc.h"
 #include "trafgen_conf.h"
 #include "trafgen_l2.h"
+#include "trafgen_l3.h"
 #include "trafgen_proto.h"
 
 #define 

[netsniff-ng] [PATCH v2 06/16] trafgen: l2: Add Ethernet proto header generation

2016-01-25 Thread Vadim Kochan
Add trafgen_l2.c module for generating L2 related headers.

Add Ethernet header generating. By default source MAC address
is used from the specified output device.

Signed-off-by: Vadim Kochan 
---
 trafgen/Makefile |  1 +
 trafgen_l2.c | 32 
 trafgen_l2.h | 12 
 trafgen_proto.c  |  3 +++
 4 files changed, 48 insertions(+)
 create mode 100644 trafgen_l2.c
 create mode 100644 trafgen_l2.h

diff --git a/trafgen/Makefile b/trafgen/Makefile
index 2ea684f..1c95118 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -20,6 +20,7 @@ trafgen-objs =xmalloc.o \
sysctl.o \
cpp.o \
trafgen_proto.o \
+   trafgen_l2.o \
trafgen_lexer.yy.o \
trafgen_parser.tab.o \
trafgen.o
diff --git a/trafgen_l2.c b/trafgen_l2.c
new file mode 100644
index 000..1082049
--- /dev/null
+++ b/trafgen_l2.c
@@ -0,0 +1,32 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include "built_in.h"
+#include "trafgen_l2.h"
+#include "trafgen_proto.h"
+
+struct proto_field eth_fields[] = {
+   { .id = ETH_DST_ADDR, .len = 6, },
+   { .id = ETH_SRC_ADDR, .len = 6, .offset = 6 },
+   { .id = ETH_PROTO_ID, .len = 2, .offset = 12 },
+};
+
+static void eth_header_init(struct proto_hdr *hdr)
+{
+   proto_header_fields_add(hdr, eth_fields, array_size(eth_fields));
+
+   proto_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
+}
+
+static struct proto_hdr eth_hdr = {
+   .id = PROTO_ETH,
+   .layer  = PROTO_L2,
+   .header_init= eth_header_init,
+};
+
+void protos_l2_init(void)
+{
+   proto_header_register(_hdr);
+}
diff --git a/trafgen_l2.h b/trafgen_l2.h
new file mode 100644
index 000..75d3d33
--- /dev/null
+++ b/trafgen_l2.h
@@ -0,0 +1,12 @@
+#ifndef TRAFGEN_L2_I_H
+#define TRAFGEN_L2_I_H
+
+enum eth_field {
+   ETH_DST_ADDR,
+   ETH_SRC_ADDR,
+   ETH_PROTO_ID,
+};
+
+extern void protos_l2_init(void);
+
+#endif /* TRAFGEN_L2_I_H */
diff --git a/trafgen_proto.c b/trafgen_proto.c
index 69579fa..efa6803 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -10,6 +10,7 @@
 #include "dev.h"
 #include "xmalloc.h"
 #include "trafgen_conf.h"
+#include "trafgen_l2.h"
 #include "trafgen_proto.h"
 
 #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
@@ -331,6 +332,8 @@ void protos_init(char *dev)
 
ctx.dev = dev;
 
+   protos_l2_init();
+
for (p = registered; p; p = p->next)
p->ctx = 
 }
-- 
2.6.3

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] Re: [PATCH 10/13] trafgen: l2: Add ARP header generation logic

2016-01-25 Thread Tobias Klauser
On 2016-01-21 at 00:19:58 +0100, Vadim Kochan  wrote:
> Add ARP proto header fields generation via src mac, src ip,
> dst mac, dst ip & operaion.
> 
> By default Ethernet proto will be initialized, and ARP probe
> request is filled.
> 
> Signed-off-by: Vadim Kochan 
> ---
>  trafgen_l2.c | 45 +
>  trafgen_l2.h | 12 
>  2 files changed, 57 insertions(+)
> 
> diff --git a/trafgen_l2.c b/trafgen_l2.c
> index 5d245b8..adee113 100644
> --- a/trafgen_l2.c
> +++ b/trafgen_l2.c
> @@ -3,10 +3,15 @@
>   * Subject to the GPL, version 2.
>   */
>  
> +#include 
> +#include 
> +
>  #include "built_in.h"
>  #include "trafgen_l2.h"
>  #include "trafgen_proto.h"
>  
> +#define ETH_BCAST { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
> +
>  struct proto_field eth_fields[] = {
>   { .id = ETH_DST_ADDR, .len = 6, },
>   { .id = ETH_SRC_ADDR, .len = 6, .offset = 6 },
> @@ -25,7 +30,47 @@ static struct proto_gen eth_prot = {
>   .header_init= eth_header_init,
>  };
>  
> +static struct proto_field arp_fields[] = {
> + { .id = ARP_HTYPE, .len = 2 },
> + { .id = ARP_PTYPE, .len = 2, .offset = 2 },
> + { .id = ARP_HLEN,  .len = 1, .offset = 4 },
> + { .id = ARP_PLEN,  .len = 1, .offset = 5 },
> + { .id = ARP_OPER,  .len = 2, .offset = 6 },
> + { .id = ARP_SHA,   .len = 6, .offset = 8 },
> + { .id = ARP_SPA,   .len = 4, .offset = 14 },
> + { .id = ARP_THA,   .len = 6, .offset = 18 },
> + { .id = ARP_TPA,   .len = 4, .offset = 24 },
> +};
> +
> +static void arp_header_init(struct proto_gen *prot)
> +{
> + uint8_t mac[6] = ETH_BCAST;
> +
> + proto_header_init(PROTO_ETH);
> +
> + proto_field_set_default_bytes(PROTO_ETH, ETH_DST_ADDR, mac);
> + proto_field_set_default_be16(PROTO_ETH, ETH_PROTO_ID, ETH_P_ARP);
> +
> + proto_fields_add(prot->id, arp_fields, array_size(arp_fields));
> +
> + /* Generate probe request by default */
> + proto_field_set_default_be16(prot->id, ARP_HTYPE, ARPHRD_ETHER);
> + proto_field_set_default_be16(prot->id, ARP_PTYPE, ETH_P_IP);
> + proto_field_set_default_u8(prot->id, ARP_HLEN, 6);
> + proto_field_set_default_u8(prot->id, ARP_PLEN, 4);
> + proto_field_set_default_be16(prot->id, ARP_OPER, ARPOP_REQUEST);
> +proto_field_set_default_dev_mac(prot->id, ARP_SHA);

Please use tab to indent here as well.

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] Re: [PATCH 00/13] trafgen: Add proto header generation

2016-01-25 Thread Vadim Kochan
On Mon, Jan 25, 2016 at 09:56:37AM +0100, Tobias Klauser wrote:
> On 2016-01-21 at 00:19:48 +0100, Vadim Kochan  wrote:
> > Add new trafgen proto generation framework which allows to describe
> > proto header fields and easy build the proto header by set/get proto
> > header fields value.
> 
> This is great, thanks a lot for doing this! I only had the chance to
> have a quick look at the series and couldn't find any major problems,
> except for one thing: Please add a patch for trafgen.8, adding a section
> which shortly describes the keywords, supported protocols, default
> values for fields not specified etc. Having the user dig through git
> commit messages or parser grammars to figure out how to use these
> features is not very nice :)
> 
> Once you add that I think we can safely apply the series and fix any
> remaining issues in follow-up patches. I'll also reply to some of the
> patches with some minor comments which you might want to consider for v2
> along with the changes you already announced.
> 
> Thanks!

BTW, I reworked to make possible to specify headers in any order and
multiple times (which was not possible in previous version), so it
allows to make such constructions like:

{ ip(), ip(proto=0x1) }

which builds ip-in-ip header (including Ethernet). And now user
responsible to specify the order of headers, but lower layers still will
be added automatically if they were not specified by user.

Regarding man changes, well I did not include it because I am not good
in English so to do not block this series in case of English issues I
decided to work on it separately, but OK - I will try to document it.

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] Re: [PATCH 13/13] trafgen: parser: Add syntax for IPv4 proto

2016-01-25 Thread Tobias Klauser
On 2016-01-21 at 00:20:01 +0100, Vadim Kochan  wrote:
> Add syntax to specify IPv4 header fields:
> 
> { ip(df, mf, frag=100, prot=0x1, ecn=2, dscp=20) }
> 
> Signed-off-by: Vadim Kochan 
> ---
>  trafgen_lexer.l  | 15 +++
>  trafgen_parser.y | 51 +++
>  2 files changed, 66 insertions(+)
> 
> diff --git a/trafgen_lexer.l b/trafgen_lexer.l
> index 9bbd982..b9bcd10 100644
> --- a/trafgen_lexer.l
> +++ b/trafgen_lexer.l
> @@ -117,8 +117,23 @@ ip_addr  ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)
>  "resp"|"reply"   { return F_RESP; }
>  "op" { return F_OPER; }
>  
> +"ihl"{ return F_IHL; }
> +"ver"{ return F_VER; }

Maybe add "version" here as well?

> +"ttl"{ return F_TTL; }
> +"dscp"   { return F_DSCP; }
> +"ecn"{ return F_ECN; }
> +"tos"{ return F_TOS; }
> +"len"{ return F_LEN; }

"length"?

> +"id" { return F_ID; }
> +"flags"  { return F_FLAGS; }
> +"frag"   { return F_FRAG; }
> +"csum"   { return F_CSUM; }
> +"df" { return F_DF; }
> +"mf" { return F_MF; }
> +
>  "eth"{ return P_ETH; }
>  "arp"{ return P_ARP; }
> +"ip" { return P_IP4; }

I think this should be "ip4" or "ipv4" (or both), in order to be
consistent with a possible future extension to support IPv6.

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[netsniff-ng] Re: [PATCH 04/13] trafgen: Add basic proto generation logic

2016-01-25 Thread Vadim Kochan
On Mon, Jan 25, 2016 at 10:15:24AM +0100, Tobias Klauser wrote:
> On 2016-01-21 at 00:19:52 +0100, Vadim Kochan  wrote:
> > Add new trafgen_proto.c module with basic proto
> > header fields generation logic.
> > 
> > Each proto must implement proto_gen struct and register it
> > to the global proto list.
> > 
> > Proto header consist from set of fields, and each field must be
> > described via proto_field struct by specifying unique id, len,
> > offset (relative to the header). Small fields ( < 8 bits) can be
> > described via left shift & mask.
> > 
> > On header_init required fields must be added to the packet and
> > initialized with default values.
> > 
> > header_finish callback is invoked from upper to lower proto
> > and some final calculations might be performed (total len, checksum).
> > 
> > Proto generation API provides easy proto field setters/getters to easy
> > craft the packet via parser.
> > 
> > Signed-off-by: Vadim Kochan 
> > ---
> >  trafgen.c|   3 +
> >  trafgen/Makefile |   1 +
> >  trafgen_proto.c  | 288 
> > +++
> >  trafgen_proto.h  |  82 
> >  4 files changed, 374 insertions(+)
> >  create mode 100644 trafgen_proto.c
> >  create mode 100644 trafgen_proto.h
> > 
> > diff --git a/trafgen.c b/trafgen.c
> > index c74a973..949f909 100644
> > --- a/trafgen.c
> > +++ b/trafgen.c
> > @@ -54,6 +54,7 @@
> >  #include "timer.h"
> >  #include "ring_tx.h"
> >  #include "csum.h"
> > +#include "trafgen_proto.h"
> >  
> >  #ifndef timeval_to_timespec
> >  #define timeval_to_timespec(tv, ts) { \
> > @@ -1215,6 +1216,8 @@ int main(int argc, char **argv)
> > register_signal(SIGTERM, signal_handler);
> > register_signal(SIGHUP, signal_handler);
> >  
> > +   protos_init(ctx.device);
> > +
> > if (prio_high) {
> > set_proc_prio(-20);
> > set_sched_status(SCHED_FIFO, 
> > sched_get_priority_max(SCHED_FIFO));
> > diff --git a/trafgen/Makefile b/trafgen/Makefile
> > index bc256b2..2ea684f 100644
> > --- a/trafgen/Makefile
> > +++ b/trafgen/Makefile
> > @@ -19,6 +19,7 @@ trafgen-objs =xmalloc.o \
> > timer.o \
> > sysctl.o \
> > cpp.o \
> > +   trafgen_proto.o \
> > trafgen_lexer.yy.o \
> > trafgen_parser.tab.o \
> > trafgen.o
> > diff --git a/trafgen_proto.c b/trafgen_proto.c
> > new file mode 100644
> > index 000..caf2685
> > --- /dev/null
> > +++ b/trafgen_proto.c
> > @@ -0,0 +1,288 @@
> > +/*
> > + * netsniff-ng - the packet sniffing beast
> > + * Subject to the GPL, version 2.
> > + */
> > +
> > +#include 
> > +#include 
> > +
> > +#include "xmalloc.h"
> > +#include "trafgen_conf.h"
> > +#include "trafgen_proto.h"
> > +
> > +#define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
> > +   ((f)->mask ? (f)->mask : (0x)))
> > +
> > +#define field_unmask_and_unshift(f, v) (((v) & \
> > +   ((f)->mask ? (f)->mask : (0x))) >> (f)->shift)
> > +
> > +static struct proto_ctx ctx;
> > +
> > +#define PROTO_MAX_LAYERS   8
> > +
> > +static struct proto_gen *headers[PROTO_MAX_LAYERS];
> > +static int headers_count;
> > +
> > +static struct proto_gen *protos;
> > +
> > +struct proto_gen *proto_get_by_id(enum proto_id id)
> > +{
> > +   struct proto_gen *p = protos;
> > +
> > +   for (; p; p = p->next)
> > +   if (p->id == id)
> > +   return p;
> > +
> > +   panic("Can't lookup proto by id %u\n", id);
> 
> Why do panic here? Wouldn't it be better to return NULL and let the
> callers handle it gracefully?

Well, just because it should not happen in normal case but only when
adding new proto syntax (parser strictly specifies the proto id).

> 
> > +}
> > +
> > +void proto_register(struct proto_gen *prot)
> > +{
> > +   prot->next = protos;
> > +   protos = prot;
> > +
> > +   prot->fields = NULL;
> > +   prot->fields_count = 0;
> > +}
> > +
> > +static void proto_fields_realloc(struct proto_gen *prot, int count)
> > +{
> > +   prot->fields = xrealloc(prot->fields, count * sizeof(*prot->fields));
> > +   prot->fields_count = count;
> > +}
> > +
> > +void proto_fields_add(enum proto_id pid, struct proto_field *fields, int 
> > count)
> > +{
> > +   struct proto_gen *prot = proto_get_by_id(pid);
> > +   struct packet *pkt = current_packet();
> > +   struct proto_field *f;
> > +   int i;
> > +
> > +   if (!prot->fields)
> > +   prot->pkt_offset = pkt->len;
> > +
> > +   proto_fields_realloc(prot, prot->fields_count + count);
> > +
> > +   for (i = 0; count >= 1; count--, i++) {
> > +   f = >fields[prot->fields_count - count];
> > +
> > +   f->id = fields[i].id;
> > +   f->len = fields[i].len;
> > +   f->is_set = false;
> > +   f->shift = fields[i].shift;
> > +   f->mask = fields[i].mask;
> > +   f->pkt_offset = prot->pkt_offset + fields[i].offset;
> > +
> >