Skip to content

Commit

Permalink
ipv6 udp checksums like ipv4 but with ipv6 pseudoheader
Browse files Browse the repository at this point in the history
this fixes a problem where both source and destination port are supplied on the commandline,
this lead to packets not showing up any more due to checksum being different.
this was mentioned first on traviscross#351
  • Loading branch information
23hiro committed Nov 9, 2021
1 parent 3f80a21 commit d6171b8
Showing 1 changed file with 18 additions and 11 deletions.
29 changes: 18 additions & 11 deletions packet/construct_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,18 +306,25 @@ int construct_udp6_packet(
set_udp_ports(udp, probe, param);
udp->length = htons(udp_size);

if (net_state->platform.ip6_socket_raw) {
/*
Instruct the kernel to put the pseudoheader checksum into the
UDP header, this is only needed when using RAW socket.
*/
int chksum_offset = (char *) &udp->checksum - (char *) udp;
if (setsockopt(udp_socket, IPPROTO_IPV6,
IPV6_CHECKSUM, &chksum_offset, sizeof(int))) {
return -1;
}
}
struct IP6PseudoHeader udph = {
.zero = {0,0,0},
.protocol = 17,
.len = udp->length
};
memcpy(udph.saddr, sockaddr_addr_offset(&probe->local_addr), 16);
memcpy(udph.daddr, sockaddr_addr_offset(&probe->remote_addr), 16);

/* get position to write checksum */
uint16_t *checksum_off = &udp->checksum;

if (udp->checksum != 0)
{ /* checksum is sequence number - correct the payload to match the checksum
checksum_off is udp payload */
checksum_off = (uint16_t *)&packet_buffer[sizeof(struct UDPHeader)];
}
*checksum_off = htons(udp4_checksum(&udph, udp,
sizeof(struct IP6PseudoHeader),
udp_size, udp->checksum != 0));
return 0;
}

Expand Down

0 comments on commit d6171b8

Please sign in to comment.