> 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

Reply via email to