Fix refcounting leaks in IPv6 MLD code leading to loss of IPv6 connectivity.
Looking at past changes in this area like r337866, some refcounting bugs have been introduced, one by one. For example like calling in6m_disconnect() and in6m_rele_locked() in mld_v1_process_group_timer() where previously no disconnect nor refcount decrement was done. Calling in6m_disconnect() when it shouldn't causes IPv6 solitation to no longer work, because all the multicast addresses receiving the solitation messages are now deleted from the network interface. Due to a double increment when joining IPv6 multicast groups many of these issues have remained hidded.
This patch reverts some recent changes while improving the MLD refcounting and concurrency model after the MLD code was converted into using EPOCH(9).
List of important changes:
- All CK_STAILQ_FOREACH() macros are now properly enclosed into EPOCH(9) sections.
- Corrected bad use of in6m_disconnect() leading to loss of IPv6 connectivity for MLD v1.
- Added sysctl for sake of debugging to disable incoming MLD v2 messages similar to existing sysctl for MLD v1 messages.
- When joining multicast IPv6 groups bad refcounting was removed. This was observed by starting and stopping rpcbind, that the in6m_refcount was incrementing instead of remaining neutral.
- When detaching a network interface we need to drain the workqueue freeing the inm's because it will access the ifnet pointer which is about to be freed.
- Factored out checks for valid inm structure into in6m_ifmultiaddr_get_inm().
PR: 233535
MFC after: 1 week
Sponsored by: Mellanox Technologies