diff options
Diffstat (limited to 'trafgen_l4.c')
-rw-r--r-- | trafgen_l4.c | 42 |
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); } |