Do not store full IPv6 packet in common forwarding case.
Forwarding IPv6 packets is slower than IPv4. Reason is that m_copym()
is done for every packet. Just in case we may have to send an ICMP6
packet, ip6_forward() creates a mbuf copy. After that mbuf cluster
is read only, so for the ethernet header another mbuf is allocated.
pf NAT and RDR ignores readonly clusters, so it also modifies the
potential ICMP6 packet.
IPv4 ip_forward() avoids all these problems by copying the leading
68 bytes of the original packets onto the stack. More is not need
for ICMP. IPv6 RFC 4443 2.4. (c) requires up to 1232 bytes in the
ICMP6 packet. This cannot be copied to the stack.
The reason for the difference in the standard seems to be that the
ICMP6 packet has to contain the full header chain. If we have a
simple TCP, UDP or ESP packet without chain, do a shortcut and just
preserve the header for the ICMP6 packet.
Small packets already use stack memory, large packets need extra
mbuf allocation. Now truncate ICMP6 packet to a reasonable length
if the original packets has a final protocol header directly after
the IPv6 header. List of suitable protocols contains TCP, UDP, ESP
as they cover the common cases and anything behind the header should
not be needed for path MTU discovery.
OK deraadt@ florian@ mvs@