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 <vadi...@gmail.com>
---
 trafgen/Makefile |  1 +
 trafgen_l3.c     | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 trafgen_l3.h     | 26 +++++++++++++++++++++
 trafgen_proto.c  |  2 ++
 4 files changed, 100 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 0000000..1b393e9
--- /dev/null
+++ b/trafgen_l3.c
@@ -0,0 +1,71 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include <linux/if_ether.h>
+
+#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_gen *prot)
+{
+       proto_header_init(PROTO_ETH);
+
+       proto_field_set_default_be16(PROTO_ETH, ETH_PROTO_ID, ETH_P_IP);
+
+       proto_fields_add(prot->id, ipv4_fields, array_size(ipv4_fields));
+
+       proto_field_set_default_u8(prot->id, IP4_VER, 4);
+       proto_field_set_default_u8(prot->id, IP4_IHL, 5);
+       proto_field_set_default_dev_ipv4(prot->id, IP4_SADDR);
+}
+
+static void ipv4_header_finish(struct proto_gen *prot)
+{
+       struct packet *pkt = current_packet();
+       uint16_t total_len;
+       uint16_t csum;
+       uint8_t ihl;
+
+       total_len = pkt->len - prot->pkt_offset;
+       proto_field_set_default_be16(prot->id, IP4_LEN, total_len);
+
+       ihl = proto_field_get_u8(prot->id, IP4_IHL);
+       csum = htons(calc_csum(&pkt->payload[prot->pkt_offset], ihl * 4));
+       proto_field_set_default_u16(prot->id, IP4_CSUM, bswap_16(csum));
+}
+
+static struct proto_gen ipv4_prot = {
+       .id             = PROTO_IP4,
+       .header_init    = ipv4_header_init,
+       .header_finish  = ipv4_header_finish,
+};
+
+void protos_l3_init(void)
+{
+       proto_register(&ipv4_prot);
+}
diff --git a/trafgen_l3.h b/trafgen_l3.h
new file mode 100644
index 0000000..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 4c30116..ae18092 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 field_shift_and_mask(f, v) (((v) << (f)->shift) & \
@@ -326,6 +327,7 @@ void protos_init(char *dev)
        ctx.dev = dev;
 
        protos_l2_init();
+       protos_l3_init();
 
        for (p = protos; p; p = p->next)
                p->ctx = &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.

Reply via email to