Skip to content

Commit

Permalink
Bug #703 fix IP header lengths before checksum
Browse files Browse the repository at this point in the history
  • Loading branch information
fklassen committed Feb 12, 2022
1 parent 7248ddb commit b63f169
Show file tree
Hide file tree
Showing 64 changed files with 65 additions and 43 deletions.
17 changes: 4 additions & 13 deletions src/tcpedit/checksum.c
Expand Up @@ -154,24 +154,15 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
icmp6->icmp_sum = CHECKSUM_CARRY(sum);
break;

case IPPROTO_IP:
default:
if (ipv4) {
ipv4->ip_sum = 0;
sum = do_checksum_math((uint16_t *)data, ip_hl);
ipv4->ip_sum = CHECKSUM_CARRY(sum);
} else {
tcpedit_setwarn(tcpedit, "Unsupported protocol for checksum: 0x%x", proto);
return TCPEDIT_WARN;
}
break;

case IPPROTO_IGMP:
case IPPROTO_GRE:
case IPPROTO_OSPF:
case IPPROTO_OSPF_LSA:
case IPPROTO_VRRP:
case TCPR_PROTO_CDP:
case TCPR_PROTO_ISL:
default:
tcpedit_setwarn(tcpedit, "Unsupported protocol for checksum: 0x%x", proto);
return TCPEDIT_WARN;
}

return TCPEDIT_OK;
Expand Down
75 changes: 48 additions & 27 deletions src/tcpedit/edit_packet.c
Expand Up @@ -65,13 +65,14 @@ fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
assert(ip_hdr);

if (pkthdr->caplen < (sizeof(*ip_hdr) + l2len)) {
tcpedit_setwarn(tcpedit, "caplen too small to read IPv4 header: %u",
pkthdr->caplen);
tcpedit_setwarn(tcpedit, "caplen too small to read IPv4 header: caplen=%u: pkt=" COUNTER_SPEC,
pkthdr->caplen, tcpedit->runtime.packetnum);
return TCPEDIT_WARN;
}

if (ip_hdr->ip_v != 4) {
tcpedit_seterr(tcpedit, "Invalid packet: Expected IPv4 packet: got %u", ip_hdr->ip_v);
tcpedit_seterr(tcpedit, "Invalid packet: Expected IPv4 packet: got %u: pkt=" COUNTER_SPEC,
ip_hdr->ip_v, tcpedit->runtime.packetnum);
return TCPEDIT_ERROR;
}

Expand All @@ -81,9 +82,9 @@ fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
(htons(ip_hdr->ip_off) & (IP_MF | IP_OFFMASK)) == 0) {
if (ip_len != (int)(pkthdr->caplen - l2len)) {
tcpedit_seterr(tcpedit,
"caplen minus L2 length %u does IPv4 header length %u",
pkthdr->caplen - l2len,
ip_len);
"caplen minus L2 length %u does IPv4 header length %u: pkt=" COUNTER_SPEC,
pkthdr->caplen - l2len, ip_len,
tcpedit->runtime.packetnum);
return TCPEDIT_ERROR;
}
ret1 = do_checksum(tcpedit, (u_char*)ip_hdr, ip_hdr->ip_p,
Expand Down Expand Up @@ -144,8 +145,8 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
assert(ip6_hdr);

if (pkthdr->caplen < (sizeof(*ip6_hdr) + l2len)) {
tcpedit_setwarn(tcpedit, "caplen too small to read IPv6 header: %u",
pkthdr->caplen);
tcpedit_setwarn(tcpedit, "caplen too small to read IPv6 header: caplen=%u pkt=" COUNTER_SPEC,
pkthdr->caplen, tcpedit->runtime.packetnum);
return TCPEDIT_WARN;
}

Expand All @@ -159,9 +160,9 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
if (pkthdr->caplen == pkthdr->len) {
int ip6_len = ipv6_header_length(ip6_hdr, pkthdr->len, l2len);
if (ip6_hdr->ip_len < ip6_len) {
tcpedit_seterr(tcpedit, "Unable to checksum IPv6 packet with invalid length %u",
ip6_hdr->ip_len);
return TCPEDIT_ERROR;
tcpedit_setwarn(tcpedit, "Unable to checksum IPv6 packet with invalid: pkt=" COUNTER_SPEC " IP length=%u caplen=" COUNTER_SPEC,
tcpedit->runtime.packetnum, ip6_hdr->ip_len);
return TCPEDIT_WARN;
}
ret = do_checksum(tcpedit, (u_char *)ip6_hdr, ip6_hdr->ip_nh,
htons(ip6_hdr->ip_len));
Expand All @@ -176,20 +177,6 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
return TCPEDIT_OK;
}

/*
* #406 fix IP headers which may be not be set properly due to TCP segmentation
*/
void fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr)
{
if (!ip_hdr->ip_len)
ip_hdr->ip_len = htons((uint16_t)pkthdr->len);
}

void fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr)
{
if (!ip6_hdr->ip_len)
ip6_hdr->ip_len = htons((uint16_t)pkthdr->len);
}

static void ipv4_l34_csum_replace(uint8_t *data, uint8_t protocol,
uint32_t old, uint32_t new)
Expand Down Expand Up @@ -378,6 +365,40 @@ randomize_ipv6_addr(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr)
}
}

int fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr,
const size_t l2len)
{
int ip_len = (int)ntohs(ip_hdr->ip_len);
int ip_len_want = (int)(pkthdr->len - l2len);

if (pkthdr->caplen < l2len + sizeof(*ip_hdr))
return -1;

if ((htons(ip_hdr->ip_off) & (IP_MF | IP_OFFMASK)) == 0 &&
ip_len != ip_len_want) {
ip_hdr->ip_len = htons(ip_len_want);
return 1;
}

return 0;
}

int fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr,
const size_t l2len)
{
int ip_len = ntohs((uint16_t)ip6_hdr->ip_len);
int ip_len_want = (int)(pkthdr->len - l2len - sizeof(*ip6_hdr));

if (pkthdr->caplen < l2len + sizeof(*ip6_hdr))
return -1;

if (ip_len != ip_len_want) {
ip6_hdr->ip_len = htons((uint16_t)ip_len_want);
return 1;
}

return 0;
}

/**
* randomizes the source and destination IP addresses based on a
Expand Down Expand Up @@ -455,8 +476,8 @@ randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
/* randomize IP addresses based on the value of random */
dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
if (l3len < (int)sizeof(ipv6_hdr_t)) {
tcpedit_seterr(tcpedit, "Unable to randomize IPv6 header due to packet capture snap length %u",
pkthdr->caplen);
tcpedit_seterr(tcpedit, "Unable to randomize IPv6 header due to packet capture snap length %u: pkt=" COUNTER_SPEC,
pkthdr->caplen, tcpedit->runtime.packetnum);
return TCPEDIT_ERROR;
}

Expand Down
6 changes: 4 additions & 2 deletions src/tcpedit/edit_packet.h
Expand Up @@ -42,9 +42,11 @@ int fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkdhdr,
int fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkdhdr,
ipv6_hdr_t *ip_hdr, const size_t l2len);

void fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr);
int fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr,
const size_t l2len);

void fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr);
int fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr,
const size_t l2len);

int extract_data(tcpedit_t *tcpedit, const u_char *pktdata,
int caplen, char *l7data[]);
Expand Down
10 changes: 9 additions & 1 deletion src/tcpedit/tcpedit.c
Expand Up @@ -356,8 +356,16 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr,
}
}

/* ensure IP header length is correct */
if (ip_hdr != NULL) {
needtorecalc |= fix_ipv4_length(*pkthdr, ip_hdr, l2len);
needtorecalc = 1;
} else if (ip6_hdr != NULL) {
needtorecalc |= fix_ipv6_length(*pkthdr, ip6_hdr, l2len);
}

/* do we need to fix checksums? -- must always do this last! */
if ((tcpedit->fixcsum || needtorecalc)) {
if ((tcpedit->fixcsum || needtorecalc > 0)) {
if (ip_hdr != NULL) {
dbgx(3, "doing IPv4 checksum: needtorecalc=%d", needtorecalc);
retval = fix_ipv4_checksums(tcpedit, *pkthdr, ip_hdr, l2len);
Expand Down
Binary file modified test/test.rewrite_1ttl
Binary file not shown.
Binary file modified test/test.rewrite_2ttl
Binary file not shown.
Binary file modified test/test.rewrite_3ttl
Binary file not shown.
Binary file modified test/test.rewrite_config
Binary file not shown.
Binary file modified test/test.rewrite_dlthdlc
Binary file not shown.
Binary file modified test/test.rewrite_dltuser
Binary file not shown.
Binary file modified test/test.rewrite_efcs
Binary file not shown.
Binary file modified test/test.rewrite_endpoint
Binary file not shown.
Binary file modified test/test.rewrite_enet_subsmac
Binary file not shown.
Binary file modified test/test.rewrite_fixcsum
Binary file not shown.
Binary file modified test/test.rewrite_fixlen_del
Binary file not shown.
Binary file modified test/test.rewrite_fixlen_pad
Binary file not shown.
Binary file modified test/test.rewrite_fixlen_trunc
Binary file not shown.
Binary file modified test/test.rewrite_l7fuzzing
Binary file not shown.
Binary file modified test/test.rewrite_layer2
Binary file not shown.
Binary file modified test/test.rewrite_mac
Binary file not shown.
Binary file modified test/test.rewrite_mac_seed
Binary file not shown.
Binary file modified test/test.rewrite_mac_seed_keep
Binary file not shown.
Binary file modified test/test.rewrite_mtutrunc
Binary file not shown.
Binary file modified test/test.rewrite_pad
Binary file not shown.
Binary file modified test/test.rewrite_pnat
Binary file not shown.
Binary file modified test/test.rewrite_portmap
Binary file not shown.
Binary file modified test/test.rewrite_range_portmap
Binary file not shown.
Binary file modified test/test.rewrite_seed
Binary file not shown.
Binary file modified test/test.rewrite_sequence
Binary file not shown.
Binary file modified test/test.rewrite_skip
Binary file not shown.
Binary file modified test/test.rewrite_tos
Binary file not shown.
Binary file modified test/test.rewrite_trunc
Binary file not shown.
Binary file modified test/test.rewrite_vlan802.1ad
Binary file not shown.
Binary file modified test/test.rewrite_vlandel
Binary file not shown.
Binary file modified test/test2.rewrite_1ttl
Binary file not shown.
Binary file modified test/test2.rewrite_2ttl
Binary file not shown.
Binary file modified test/test2.rewrite_3ttl
Binary file not shown.
Binary file modified test/test2.rewrite_config
Binary file not shown.
Binary file modified test/test2.rewrite_dlthdlc
Binary file not shown.
Binary file modified test/test2.rewrite_dltuser
Binary file not shown.
Binary file modified test/test2.rewrite_efcs
Binary file not shown.
Binary file modified test/test2.rewrite_endpoint
Binary file not shown.
Binary file modified test/test2.rewrite_enet_subsmac
Binary file not shown.
Binary file modified test/test2.rewrite_fixcsum
Binary file not shown.
Binary file modified test/test2.rewrite_fixlen_del
Binary file not shown.
Binary file modified test/test2.rewrite_fixlen_pad
Binary file not shown.
Binary file modified test/test2.rewrite_fixlen_trunc
Binary file not shown.
Binary file modified test/test2.rewrite_l7fuzzing
Binary file not shown.
Binary file modified test/test2.rewrite_layer2
Binary file not shown.
Binary file modified test/test2.rewrite_mac
Binary file not shown.
Binary file modified test/test2.rewrite_mac_seed
Binary file not shown.
Binary file modified test/test2.rewrite_mac_seed_keep
Binary file not shown.
Binary file modified test/test2.rewrite_mtutrunc
Binary file not shown.
Binary file modified test/test2.rewrite_pad
Binary file not shown.
Binary file modified test/test2.rewrite_pnat
Binary file not shown.
Binary file modified test/test2.rewrite_portmap
Binary file not shown.
Binary file modified test/test2.rewrite_range_portmap
Binary file not shown.
Binary file modified test/test2.rewrite_seed
Binary file not shown.
Binary file modified test/test2.rewrite_sequence
Binary file not shown.
Binary file modified test/test2.rewrite_skip
Binary file not shown.
Binary file modified test/test2.rewrite_tos
Binary file not shown.
Binary file modified test/test2.rewrite_trunc
Binary file not shown.
Binary file modified test/test2.rewrite_vlan802.1ad
Binary file not shown.
Binary file modified test/test2.rewrite_vlandel
Binary file not shown.

0 comments on commit b63f169

Please sign in to comment.