diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2016-04-25 17:56:51 +0200 |
---|---|---|
committer | Tobias Klauser <tklauser@distanz.ch> | 2016-04-25 18:06:08 +0200 |
commit | 77d5cae4d45d1def8f41d4e89b705d2953858643 (patch) | |
tree | fb07be4ac5a8459808887b7447c0572cbceb7272 /trafgen_l4.c | |
parent | c09e06a6efaa94768660636a9c58ce9666e29d05 (diff) |
trafgen: proto: Add ICMPv6 header generation
Support for generating simple ICMPv6 headers using the 'icmp6()/icmpv6()'
trafgen generation function.
Fields supported:
mtype Message type (default: 0)
Supported keywords: echorequest, echoreply
code Code (default: 0)
csum Message checksum (calculated by default)
Examples:
{ eth(), ipv6(daddr=::1), icmpv6(echorequest), 42, 42, 0, 0 }'
If not explicitely specified, the lower header is initialized as Ethernet.
Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'trafgen_l4.c')
-rw-r--r-- | trafgen_l4.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/trafgen_l4.c b/trafgen_l4.c index a5981c4..886e2b2 100644 --- a/trafgen_l4.c +++ b/trafgen_l4.c @@ -138,8 +138,57 @@ static struct proto_hdr tcp_hdr = { .packet_finish = tcp_packet_finish, }; +static struct proto_field icmpv6_fields[] = { + { .id = ICMPV6_TYPE, .len = 1, .offset = 0 }, + { .id = ICMPV6_CODE, .len = 1, .offset = 1 }, + { .id = ICMPV6_CSUM, .len = 2, .offset = 2 } +}; + +static void icmpv6_header_init(struct proto_hdr *hdr) +{ + proto_lower_default_add(hdr, PROTO_IP6); + + proto_header_fields_add(hdr, icmpv6_fields, array_size(icmpv6_fields)); +} + +static void icmpv6_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; + + if (proto_field_is_set(hdr, ICMPV6_CSUM)) + return; + + if (!lower) + return; + + total_len = pkt->len - hdr->pkt_offset; + + switch (lower->id) { + case PROTO_IP6: + csum = p6_csum((void *) proto_header_ptr(lower), proto_header_ptr(hdr), + total_len, IPPROTO_ICMPV6); + break; + default: + csum = 0; + break; + } + + proto_field_set_be16(hdr, ICMPV6_CSUM, bswap_16(csum)); +} + +static struct proto_hdr icmpv6_hdr = { + .id = PROTO_ICMP6, + .layer = PROTO_L4, + .header_init = icmpv6_header_init, + .packet_finish = icmpv6_packet_finish, +}; + void protos_l4_init(void) { proto_header_register(&udp_hdr); proto_header_register(&tcp_hdr); + proto_header_register(&icmpv6_hdr); } |