Skip to content
  • Daniel Borkmann's avatar
    ipv6: mld: answer mldv2 queries with mldv1 reports in mldv1 fallback · 35f7aa53
    Daniel Borkmann authored
    
    
    RFC2710 (MLDv1), section 3.7. says:
    
      The length of a received MLD message is computed by taking the
      IPv6 Payload Length value and subtracting the length of any IPv6
      extension headers present between the IPv6 header and the MLD
      message. If that length is greater than 24 octets, that indicates
      that there are other fields present *beyond* the fields described
      above, perhaps belonging to a *future backwards-compatible* version
      of MLD. An implementation of the version of MLD specified in this
      document *MUST NOT* send an MLD message longer than 24 octets and
      MUST ignore anything past the first 24 octets of a received MLD
      message.
    
    RFC3810 (MLDv2), section 8.2.1. states for *listeners* regarding
    presence of MLDv1 routers:
    
      In order to be compatible with MLDv1 routers, MLDv2 hosts MUST
      operate in version 1 compatibility mode. [...] When Host
      Compatibility Mode is MLDv2, a host acts using the MLDv2 protocol
      on that interface. When Host Compatibility Mode is MLDv1, a host
      acts in MLDv1 compatibility mode, using *only* the MLDv1 protocol,
      on that interface. [...]
    
    While section 8.3.1. specifies *router* behaviour regarding presence
    of MLDv1 routers:
    
      MLDv2 routers may be placed on a network where there is at least
      one MLDv1 router. The following requirements apply:
    
      If an MLDv1 router is present on the link, the Querier MUST use
      the *lowest* version of MLD present on the network. This must be
      administratively assured. Routers that desire to be compatible
      with MLDv1 MUST have a configuration option to act in MLDv1 mode;
      if an MLDv1 router is present on the link, the system administrator
      must explicitly configure all MLDv2 routers to act in MLDv1 mode.
      When in MLDv1 mode, the Querier MUST send periodic General Queries
      truncated at the Multicast Address field (i.e., 24 bytes long),
      and SHOULD also warn about receiving an MLDv2 Query (such warnings
      must be rate-limited). The Querier MUST also fill in the Maximum
      Response Delay in the Maximum Response Code field, i.e., the
      exponential algorithm described in section 5.1.3. is not used. [...]
    
    That means that we should not get queries from different versions of
    MLD. When there's a MLDv1 router present, MLDv2 enforces truncation
    and MRC == MRD (both fields are overlapping within the 24 octet range).
    
    Section 8.3.2. specifies behaviour in the presence of MLDv1 multicast
    address *listeners*:
    
      MLDv2 routers may be placed on a network where there are hosts
      that have not yet been upgraded to MLDv2. In order to be compatible
      with MLDv1 hosts, MLDv2 routers MUST operate in version 1 compatibility
      mode. MLDv2 routers keep a compatibility mode per multicast address
      record. The compatibility mode of a multicast address is determined
      from the Multicast Address Compatibility Mode variable, which can be
      in one of the two following states: MLDv1 or MLDv2.
    
      The Multicast Address Compatibility Mode of a multicast address
      record is set to MLDv1 whenever an MLDv1 Multicast Listener Report is
      *received* for that multicast address. At the same time, the Older
      Version Host Present timer for the multicast address is set to Older
      Version Host Present Timeout seconds. The timer is re-set whenever a
      new MLDv1 Report is received for that multicast address. If the Older
      Version Host Present timer expires, the router switches back to
      Multicast Address Compatibility Mode of MLDv2 for that multicast
      address. [...]
    
    That means, what can happen is the following scenario, that hosts can
    act in MLDv1 compatibility mode when they previously have received an
    MLDv1 query (or, simply operate in MLDv1 mode-only); and at the same
    time, an MLDv2 router could start up and transmits MLDv2 startup query
    messages while being unaware of the current operational mode.
    
    Given RFC2710, section 3.7 we would need to answer to that with an MLDv1
    listener report, so that the router according to RFC3810, section 8.3.2.
    would receive that and internally switch to MLDv1 compatibility as well.
    
    Right now, I believe since the initial implementation of MLDv2, Linux
    hosts would just silently drop such MLDv2 queries instead of replying
    with an MLDv1 listener report, which would prevent a MLDv2 router going
    into fallback mode (until it receives other MLDv1 queries).
    
    Since the mapping of MRC to MRD in exactly such cases can make use of
    the exponential algorithm from 5.1.3, we cannot [strictly speaking] be
    aware in MLDv1 of the encoding in MRC, it seems also not mentioned by
    the RFC. Since encodings are the same up to 32767, assume in such a
    situation this value as a hard upper limit we would clamp. We have asked
    one of the RFC authors on that regard, and he mentioned that there seem
    not to be any implementations that make use of that exponential algorithm
    on startup messages. In any case, this patch fixes this MLD
    interoperability issue.
    
    Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
    Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    35f7aa53