Skip to content

Commit

Permalink
unify and fix checksum calculation
Browse files Browse the repository at this point in the history
Co-authored-by: M.Koch <49749154+mkoch-fub@users.noreply.github.com>
  • Loading branch information
zirngibl and mkoch-tud committed Apr 25, 2023
1 parent 6d6c5d7 commit b55da2b
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 133 deletions.
8 changes: 2 additions & 6 deletions src/probe_modules/module_icmp6_echoscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,8 @@ static int icmp6_echo_make_packet(void *buf, size_t *buf_len, UNUSED ipaddr_n_t

icmp6_header->icmp6_id= icmp_idnum;
icmp6_header->icmp6_cksum = 0;
icmp6_header->icmp6_cksum= (uint16_t) icmp6_checksum(
&ip6_header->ip6_src,
&ip6_header->ip6_dst,
icmp6_header,
2*sizeof(uint32_t)
);

icmp6_header->icmp6_cksum = ipv6_payload_checksum(sizeof(struct icmp6_hdr) + 2*sizeof(uint32_t), &ip6_header->ip6_src, &ip6_header->ip6_dst, (unsigned short *) icmp6_header, IPPROTO_ICMPV6);

// 8 bytes of data are used in ICMPv6 for validation
*buf_len = sizeof(struct ether_header) + sizeof(struct ip6_hdr) + ICMP_MINLEN + 2*sizeof(uint32_t);
Expand Down
4 changes: 3 additions & 1 deletion src/probe_modules/module_ipv6_quic_initial.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ int ipv6_quic_initial_make_packet(void *buf, size_t *buf_len,
htons(sizeof(struct udphdr) + payload_len);
udp_header->uh_ulen = ntohs(sizeof(struct udphdr) + payload_len);

udp_header->uh_sum = ipv6_udp_checksum(&ip6_header->ip6_src, &ip6_header->ip6_dst, udp_header);
udp_header->uh_sum = 0;
udp_header->uh_sum = ipv6_payload_checksum(ntohs(udp_header->uh_ulen), &ip6_header->ip6_src, &ip6_header->ip6_dst, (unsigned short *) udp_header, IPPROTO_UDP);

size_t headers_len = sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct udphdr);
*buf_len = headers_len + payload_len;

Expand Down
6 changes: 4 additions & 2 deletions src/probe_modules/module_ipv6_tcp_synopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@ int ipv6_tcp_synopt_make_packet(void *buf, size_t *buf_len, __attribute__((unuse


tcp_header->th_sum = 0;
tcp_header->th_sum = tcp6_checksum(ZMAPV6_TCP_SYNOPT_TCP_HEADER_LEN+tcp_send_opts_len,
&ip6_header->ip6_src, &ip6_header->ip6_dst, tcp_header);

unsigned short len_tcp = ZMAPV6_TCP_SYNOPT_TCP_HEADER_LEN+tcp_send_opts_len;

tcp_header->th_sum = ipv6_payload_checksum(len_tcp, &ip6_header->ip6_src, &ip6_header->ip6_dst, (unsigned short *) tcp_header, IPPROTO_TCP);

*buf_len = ZMAPV6_TCP_SYNOPT_PACKET_LEN+tcp_send_opts_len;

Expand Down
4 changes: 2 additions & 2 deletions src/probe_modules/module_ipv6_tcp_synscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ int ipv6_synscan_make_packet(void *buf, size_t *buf_len, UNUSED ipaddr_n_t src_i
probe_num, validation));
tcp_header->th_seq = tcp_seq;
tcp_header->th_sum = 0;
tcp_header->th_sum = tcp6_checksum(ZMAPV6_TCP_SYNSCAN_TCP_HEADER_LEN,
&ip6_header->ip6_src, &ip6_header->ip6_dst, tcp_header);

tcp_header->th_sum = ipv6_payload_checksum(ZMAPV6_TCP_SYNSCAN_TCP_HEADER_LEN, &ip6_header->ip6_src, &ip6_header->ip6_dst, (unsigned short *) tcp_header, IPPROTO_TCP);

*buf_len = ZMAPV6_TCP_SYNSCAN_PACKET_LEN;

Expand Down
3 changes: 2 additions & 1 deletion src/probe_modules/module_ipv6_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ int ipv6_udp_make_packet(void *buf, size_t *buf_len, __attribute__((unused)) ipa
udp_header->uh_ulen = ntohs(sizeof(struct udphdr) + payload_len);
}
*/
udp_header->uh_sum = ipv6_udp_checksum(&ip6_header->ip6_src, &ip6_header->ip6_dst, udp_header);
udp_header->uh_sum = 0;
udp_header->uh_sum = ipv6_payload_checksum(ntohs(udp_header->uh_ulen), &ip6_header->ip6_src, &ip6_header->ip6_dst, (unsigned short *) udp_header, IPPROTO_UDP);

size_t headers_len = sizeof(struct ether_header) + sizeof(struct ip6_hdr) +
sizeof(struct udphdr);
Expand Down
4 changes: 2 additions & 2 deletions src/probe_modules/module_ipv6_udp_dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ int ipv6_udp_dns_make_packet(void *buf, size_t *buf_len, UNUSED ipaddr_n_t src_i
ip6_header->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
udp_header->uh_sport = htons(get_src_port(num_ports, probe_num,
validation));
udp_header->uh_sum = ipv6_udp_checksum(&ip6_header->ip6_src, &ip6_header->ip6_dst, udp_header);

udp_header->uh_sum = ipv6_udp_checksum(&ip6_header->ip6_src, &ip6_header->ip6_dst, udp_header);
udp_header->uh_sum = 0;
udp_header->uh_sum = ipv6_payload_checksum(ntohs(udp_header->uh_ulen), &ip6_header->ip6_src, &ip6_header->ip6_dst, (unsigned short *) udp_header, IPPROTO_UDP);

size_t headers_len = sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct udphdr);
*buf_len = headers_len + udp_send_msg_len;
Expand Down
134 changes: 15 additions & 119 deletions src/probe_modules/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,146 +112,42 @@ icmp_checksum(unsigned short *buf, size_t buflen)
return in_icmp_checksum(buf, buflen);
}

static inline uint16_t icmp6_checksum(
struct in6_addr *saddr,
struct in6_addr *daddr,
struct icmp6_hdr * icmp6_header,
size_t data_len
)
{
uint16_t *src_addr = (uint16_t *) saddr;
uint16_t *dest_addr = (uint16_t *) daddr;
unsigned short icmp6_len = sizeof(struct icmp6_hdr) + data_len;
unsigned long sum = 0;
int nleft = icmp6_len;
unsigned short *w;

w = (unsigned short *) icmp6_header;
// calculate the checksum for the tcp header and tcp data
while(nleft > 1) {
sum += *w++;
nleft -= 2;
}
// if nleft is 1 there ist still on byte left.
// We add a padding byte (0xFF) to build a 16bit word
if (nleft > 0) {
sum += *w & ntohs(0xFF00);
}

//return in_checksum(buf, (int) sizeof(struct icmp));
// add the pseudo header
sum += src_addr[0];
sum += src_addr[1];
sum += src_addr[2];
sum += src_addr[3];
sum += src_addr[4];
sum += src_addr[5];
sum += src_addr[6];
sum += src_addr[7];
sum += dest_addr[0];
sum += dest_addr[1];
sum += dest_addr[2];
sum += dest_addr[3];
sum += dest_addr[4];
sum += dest_addr[5];
sum += dest_addr[6];
sum += dest_addr[7];
sum += htons(icmp6_len);
sum += htons(IPPROTO_ICMPV6);
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
// Take the one's complement of sum
return (unsigned short) (~sum);
}

static inline uint16_t ipv6_udp_checksum(
struct in6_addr *saddr,
struct in6_addr *daddr,
struct udphdr *udp_header)
static inline uint16_t ipv6_payload_checksum(
unsigned short len,
struct in6_addr *saddr,
struct in6_addr *daddr,
unsigned short *w,
unsigned char proto)
{
unsigned long sum = 0;
uint16_t *src_addr = (uint16_t *) saddr;
uint16_t *dest_addr = (uint16_t *) daddr;

// Reset checksum value for calculation
udp_header->uh_sum = 0;

// Pseudo header for IPv6+UDP
for (int i = 0; i < 8; i++) {
sum += ntohs(src_addr[i]);
sum += src_addr[i];
}
for (int i = 0; i < 8; i++) {
sum += ntohs(dest_addr[i]);
sum += dest_addr[i];
}
sum += ntohs(udp_header->uh_ulen);
sum += IPPROTO_UDP;
sum += htons(len);
sum += htons(proto);

unsigned short *w = (unsigned short *) udp_header;
int bytes_left = ntohs(udp_header->uh_ulen);

// Add checksum of UDP header and data
while (bytes_left > 1) {
sum += ntohs(*w++);
bytes_left -= 2;
// Add checksum of header and data
while (len > 1) {
sum += *w++;
len -= 2;
}

// If 1 byte is left, we add a padding byte (0xFF) to build a 16bit word
if (bytes_left > 0) {
if (len > 0) {
sum += *w & ntohs(0xFF00);
}

// Account for carries
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);

// Take the one's complement of sum
return htons((unsigned short) (~sum));
}


static inline uint16_t tcp6_checksum(unsigned short len_tcp,
struct in6_addr *saddr, struct in6_addr *daddr, struct tcphdr *tcp_pkt)
{
uint16_t *src_addr = (uint16_t *) saddr;
uint16_t *dest_addr = (uint16_t *) daddr;

unsigned char prot_tcp = 6;
unsigned long sum = 0;
int nleft = len_tcp;
unsigned short *w;

w = (unsigned short *) tcp_pkt;
// calculate the checksum for the tcp header and tcp data
while(nleft > 1) {
sum += *w++;
nleft -= 2;
}
// if nleft is 1 there ist still on byte left.
// We add a padding byte (0xFF) to build a 16bit word
if (nleft > 0) {
sum += *w & ntohs(0xFF00);
}
// add the pseudo header
sum += src_addr[0];
sum += src_addr[1];
sum += src_addr[2];
sum += src_addr[3];
sum += src_addr[4];
sum += src_addr[5];
sum += src_addr[6];
sum += src_addr[7];
sum += dest_addr[0];
sum += dest_addr[1];
sum += dest_addr[2];
sum += dest_addr[3];
sum += dest_addr[4];
sum += dest_addr[5];
sum += dest_addr[6];
sum += dest_addr[7];
sum += htons(len_tcp);
sum += htons(prot_tcp);
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
// Take the one's complement of sum
return (unsigned short) (~sum);
}
Expand Down

0 comments on commit b55da2b

Please sign in to comment.