Add ICMPv4 protocol header creating with minimum
field set: type, code, checksum & unused field.

Checksum is calculated by default if the 'csum' field
is not set.

It is allowed to specify such fields like:

    type, code, checksum, unused, sequence, identifier, mtu, redirect
    address

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_l3.c    |  3 +++
 trafgen_l4.c    | 42 ++++++++++++++++++++++++++++++++++++++++++
 trafgen_l4.h    | 10 ++++++++++
 trafgen_proto.h |  1 +
 4 files changed, 56 insertions(+)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index cbdbe6c..ae3f136 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -69,6 +69,9 @@ static void ipv4_set_next_proto(struct proto_hdr *hdr, enum 
proto_id pid)
        case PROTO_IP4:
                ip_proto = IPPROTO_IPIP;
                break;
+       case PROTO_ICMP4:
+               ip_proto = IPPROTO_ICMP;
+               break;
        case PROTO_UDP:
                ip_proto = IPPROTO_UDP;
                break;
diff --git a/trafgen_l4.c b/trafgen_l4.c
index 886e2b2..c109675 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -138,6 +138,47 @@ static struct proto_hdr tcp_hdr = {
        .packet_finish  = tcp_packet_finish,
 };
 
+static struct proto_field icmpv4_fields[] = {
+       { .id = ICMPV4_TYPE,       .len = 1, .offset = 0 },
+       { .id = ICMPV4_CODE,       .len = 1, .offset = 1 },
+       { .id = ICMPV4_CSUM,       .len = 2, .offset = 2 },
+       /* Echo/Ping fields */
+       { .id = ICMPV4_ID,         .len = 2, .offset = 4 },
+       { .id = ICMPV4_SEQ,        .len = 2, .offset = 6 },
+       /* Redirect field */
+       { .id = ICMPV4_REDIR_ADDR, .len = 4, .offset = 4 },
+       /* Next-hop MTU */
+       { .id = ICMPV4_MTU,        .len = 2, .offset = 6 },
+};
+
+static void icmpv4_header_init(struct proto_hdr *hdr)
+{
+       proto_lower_default_add(hdr, PROTO_IP4);
+
+       proto_header_fields_add(hdr, icmpv4_fields, array_size(icmpv4_fields));
+}
+
+static void icmpv4_packet_finish(struct proto_hdr *hdr)
+{
+       struct packet *pkt;
+       uint16_t csum;
+
+       if (proto_field_is_set(hdr, ICMPV4_CSUM))
+               return;
+
+       pkt = current_packet();
+
+       csum = htons(calc_csum(proto_header_ptr(hdr), pkt->len - 
hdr->pkt_offset));
+       proto_field_set_u16(hdr, ICMPV4_CSUM, bswap_16(csum));
+}
+
+static struct proto_hdr icmpv4_hdr = {
+       .id             = PROTO_ICMP4,
+       .layer          = PROTO_L4,
+       .header_init    = icmpv4_header_init,
+       .packet_finish  = icmpv4_packet_finish,
+};
+
 static struct proto_field icmpv6_fields[] = {
        { .id = ICMPV6_TYPE, .len = 1, .offset = 0 },
        { .id = ICMPV6_CODE, .len = 1, .offset = 1 },
@@ -190,5 +231,6 @@ void protos_l4_init(void)
 {
        proto_header_register(&udp_hdr);
        proto_header_register(&tcp_hdr);
+       proto_header_register(&icmpv4_hdr);
        proto_header_register(&icmpv6_hdr);
 }
diff --git a/trafgen_l4.h b/trafgen_l4.h
index e94ff23..9537cbf 100644
--- a/trafgen_l4.h
+++ b/trafgen_l4.h
@@ -27,6 +27,16 @@ enum tcp_field {
        TCP_URG_PTR,
 };
 
+enum icmpv4_field {
+       ICMPV4_TYPE,
+       ICMPV4_CODE,
+       ICMPV4_CSUM,
+       ICMPV4_ID,
+       ICMPV4_SEQ,
+       ICMPV4_REDIR_ADDR,
+       ICMPV4_MTU,
+};
+
 enum icmpv6_field {
        ICMPV6_TYPE,
        ICMPV6_CODE,
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 5528704..822d841 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -16,6 +16,7 @@ enum proto_id {
        PROTO_ARP,
        PROTO_MPLS,
        PROTO_IP4,
+       PROTO_ICMP4,
        PROTO_IP6,
        PROTO_ICMP6,
        PROTO_UDP,
-- 
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