The manpage divert(4) says this:
This is irrelevant with IPv6, since there is no IP header checksum.
But, as I am observing, the UDPv6/TCPv6 checkums are also wrong on the outgoing path (probably for the same reason: we dont yet know the interface, but might be able to offload calculation to hw).
This obviousely only applies to locally generated packets (there is no checksum change in IPv6 when gatewaying).
The problem with divert then is: when passing thru a divert socket and back from it, then on final transmit the checksums in the local packets do not get filled in, and the packets go out with wrong checksum and get then discarded at next hop.
As it seems, the fact that the packet was inserted locally (and does therefore not yet have calculated checksums) gets somehow lost when passing thru a divert socket and back.
I am not sure who is to blame for that, but could it be that divert(4) does not properly support IPv6? There is a mention of divert(4) here: https://wiki.freebsd.org/IPv6/ToDo - but that was there ten years ago already...
Code:
Packets are received and sent unchanged, except that packets read as out-
going have invalid IP header checksums, and packets written as outgoing
have their IP header checksums overwritten with the correct value. Pack-
ets written as incoming and having incorrect checksums will be dropped.
Otherwise, all header fields are unchanged (and therefore in network or-
der).
This is irrelevant with IPv6, since there is no IP header checksum.
But, as I am observing, the UDPv6/TCPv6 checkums are also wrong on the outgoing path (probably for the same reason: we dont yet know the interface, but might be able to offload calculation to hw).
This obviousely only applies to locally generated packets (there is no checksum change in IPv6 when gatewaying).
The problem with divert then is: when passing thru a divert socket and back from it, then on final transmit the checksums in the local packets do not get filled in, and the packets go out with wrong checksum and get then discarded at next hop.
As it seems, the fact that the packet was inserted locally (and does therefore not yet have calculated checksums) gets somehow lost when passing thru a divert socket and back.
I am not sure who is to blame for that, but could it be that divert(4) does not properly support IPv6? There is a mention of divert(4) here: https://wiki.freebsd.org/IPv6/ToDo - but that was there ten years ago already...