summaryrefslogtreecommitdiff
path: root/trafgen_l4.c
diff options
context:
space:
mode:
authorVadim Kochan <vadim4j@gmail.com>2016-07-13 01:01:53 +0300
committerTobias Klauser <tklauser@distanz.ch>2016-07-13 09:32:07 +0200
commit423bb070d372341aa178849a9479099b95c7d352 (patch)
treece5a939c07d84d05ea29be0458f51b2ed02af282 /trafgen_l4.c
parente6fcf1f0f2c58cf38fad98d1d8b00a3b7ebd3070 (diff)
trafgen: proto: Add ICMPv4 header generation
Support for generating ICMPv4 headers using the 'icmp4()/icmpv4()' trafgen generation functions. Fields supported: type Set type field (default 0: Echo reply) Supported keywords: echorequest, echoreply code Set code field (default 0) csum Set checksum field (calculated by default) mtu Set mtu field for destination unreachable (default 0) seq Set sequence field (default 0) id Set identifier field (default 0) addr Set redirect address (default 0.0.0.0) Example (send ping request): { icmpv4(echorequest, seq=1, id=1326) } Signed-off-by: Vadim Kochan <vadim4j@gmail.com> [tk: squash commits, consistency between functionality and docu] Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'trafgen_l4.c')
-rw-r--r--trafgen_l4.c42
1 files changed, 42 insertions, 0 deletions
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);
}