> Am 13.10.2016 um 13:06 schrieb Christian Weisgerber <na...@mips.inka.de>: > >> After the second m_makespace(): >> >> +------+-----+ +------+ +--------+-----+ >> | IPv6 | ESP | ---- | IPv6 | ---- | ICMPv6 | ESP | >> +------+-----+ +------+ +--------+-----+ >> >> With m_inject(), it would instead be something like this: >> >> +------+ +-----+ +------+ +-------- >> | IPv6 |----| ESP | ---- | IPv6 | ---- | ICMPv6 ... >> +------+ +-----+ +------+ +-------- > > Found it. It's this snippet of nd6_ns_output() that handles those > mbuf chains differently: > > 454 if (ln && ln->ln_hold) { > 455 hip6 = mtod(ln->ln_hold, struct ip6_hdr *); > 456 /* XXX pullup? */ > 457 if (sizeof(*hip6) < ln->ln_hold->m_len) > 458 saddr6 = &hip6->ip6_src; > 459 else > 460 saddr6 = NULL; > 461 } else > 462 saddr6 = NULL; > > Did this only ever work by accident?
ok, to get it right, the following is the difference: with m_inject() the first mbuf always contains the 40 byte ipv6 header while with m_makespace() it also contains the ESP header. so with m_inject() the ln_hold->m_len is 40 and since this is exactly the size of hip6, the code falls back to saddr6 = NULL. IMHO the code should use <= and not <: if (sizeof(*hip6) <= ln->ln_hold->m_len) but then your example will also fail with the old m_inject() code. If this intended address selection is indeed correct then we need to figure out if a bypass flow for NDP is necessary, or if NDP should always bypass IPsec (but what about bringing NDP over IPsec?) With IPv4 this problem does not exist, because ARP packet are not IP packets, so they are not matched by the IPsec flow. -m