summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/network/ipv4')
-rw-r--r--pkg/tcpip/network/ipv4/ipv4.go34
1 files changed, 28 insertions, 6 deletions
diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go
index be9c8e2f9..ce2087002 100644
--- a/pkg/tcpip/network/ipv4/ipv4.go
+++ b/pkg/tcpip/network/ipv4/ipv4.go
@@ -123,6 +123,15 @@ func (e *endpoint) Enable() *tcpip.Error {
// We have no need for the address endpoint.
ep.DecRef()
+ // Groups may have been joined while the endpoint was disabled, or the
+ // endpoint may have left groups from the perspective of IGMP when the
+ // endpoint was disabled. Either way, we need to let routers know to
+ // send us multicast traffic.
+ joinedGroups := e.mu.addressableEndpointState.JoinedGroups()
+ for _, group := range joinedGroups {
+ e.igmp.joinGroup(group)
+ }
+
// As per RFC 1122 section 3.3.7, all hosts should join the all-hosts
// multicast group. Note, the IANA calls the all-hosts multicast group the
// all-systems multicast group.
@@ -168,6 +177,13 @@ func (e *endpoint) disableLocked() {
panic(fmt.Sprintf("unexpected error when leaving group = %s: %s", header.IPv4AllSystems, err))
}
+ // Leave groups from the perspective of IGMP so that routers know that
+ // we are no longer interested in the group.
+ joinedGroups := e.mu.addressableEndpointState.JoinedGroups()
+ for _, group := range joinedGroups {
+ e.igmp.leaveGroup(group)
+ }
+
// The address may have already been removed.
if err := e.mu.addressableEndpointState.RemovePermanentAddress(ipv4BroadcastAddr.Address); err != nil && err != tcpip.ErrBadLocalAddress {
panic(fmt.Sprintf("unexpected error when removing address = %s: %s", ipv4BroadcastAddr.Address, err))
@@ -853,6 +869,15 @@ func (e *endpoint) joinGroupLocked(addr tcpip.Address) (bool, *tcpip.Error) {
return joined, err
}
+ // Only join the group from the perspective of IGMP when the endpoint is
+ // enabled.
+ //
+ // If we are not enabled right now, we will join the group from the
+ // perspective of IGMP when the endpoint is enabled.
+ if !e.Enabled() {
+ return true, nil
+ }
+
// joinGroup only returns an error if we try to join a group twice, but we
// checked above to make sure that the group was newly joined.
if err := e.igmp.joinGroup(addr); err != nil {
@@ -874,15 +899,12 @@ func (e *endpoint) LeaveGroup(addr tcpip.Address) (bool, *tcpip.Error) {
// Precondition: e.mu must be locked.
func (e *endpoint) leaveGroupLocked(addr tcpip.Address) (bool, *tcpip.Error) {
left, err := e.mu.addressableEndpointState.LeaveGroup(addr)
- if err != nil {
+ if err != nil || !left {
return left, err
}
- if left {
- e.igmp.leaveGroup(addr)
- }
-
- return left, nil
+ e.igmp.leaveGroup(addr)
+ return true, nil
}
// IsInGroup implements stack.GroupAddressableEndpoint.