diff options
author | Ian Gudger <igudger@google.com> | 2019-03-08 15:48:16 -0800 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-03-08 15:49:17 -0800 |
commit | 56a61282953b46c8f8b707d5948a2d3958dced0c (patch) | |
tree | 2336f9f92e227d5f43bbad81cee80c527573a6a2 /pkg/tcpip/transport/udp/endpoint.go | |
parent | 832589cb076a638ca53076ebb66afb9fac4597d1 (diff) |
Implement IP_MULTICAST_LOOP.
IP_MULTICAST_LOOP controls whether or not multicast packets sent on the default
route are looped back. In order to implement this switch, support for sending
and looping back multicast packets on the default route had to be implemented.
For now we only support IPv4 multicast.
PiperOrigin-RevId: 237534603
Change-Id: I490ac7ff8e8ebef417c7eb049a919c29d156ac1c
Diffstat (limited to 'pkg/tcpip/transport/udp/endpoint.go')
-rw-r--r-- | pkg/tcpip/transport/udp/endpoint.go | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 4108cb09c..3693abae5 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -81,6 +81,7 @@ type endpoint struct { multicastTTL uint8 multicastAddr tcpip.Address multicastNICID tcpip.NICID + multicastLoop bool reusePort bool broadcast bool @@ -124,6 +125,7 @@ func newEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waite // // Linux defaults to TTL=1. multicastTTL: 1, + multicastLoop: true, rcvBufSizeMax: 32 * 1024, sndBufSize: 32 * 1024, } @@ -274,7 +276,7 @@ func (e *endpoint) connectRoute(nicid tcpip.NICID, addr tcpip.FullAddress) (stac } // Find a route to the desired destination. - r, err := e.stack.FindRoute(nicid, localAddr, addr.Addr, netProto) + r, err := e.stack.FindRoute(nicid, localAddr, addr.Addr, netProto, e.multicastLoop) if err != nil { return stack.Route{}, 0, 0, err } @@ -458,13 +460,19 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error { case tcpip.AddMembershipOption: nicID := v.NIC - if v.InterfaceAddr != header.IPv4Any { + if v.InterfaceAddr == header.IPv4Any { + if nicID == 0 { + r, err := e.stack.FindRoute(0, "", v.MulticastAddr, header.IPv4ProtocolNumber, false /* multicastLoop */) + if err == nil { + nicID = r.NICID() + r.Release() + } + } + } else { nicID = e.stack.CheckLocalAddress(nicID, e.netProto, v.InterfaceAddr) } if nicID == 0 { - // TODO: Allow adding memberships without - // specifing an interface. - return tcpip.ErrNoRoute + return tcpip.ErrUnknownDevice } // TODO: check that v.MulticastAddr is a multicast address. @@ -479,11 +487,19 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error { case tcpip.RemoveMembershipOption: nicID := v.NIC - if v.InterfaceAddr != header.IPv4Any { + if v.InterfaceAddr == header.IPv4Any { + if nicID == 0 { + r, err := e.stack.FindRoute(0, "", v.MulticastAddr, header.IPv4ProtocolNumber, false /* multicastLoop */) + if err == nil { + nicID = r.NICID() + r.Release() + } + } + } else { nicID = e.stack.CheckLocalAddress(nicID, e.netProto, v.InterfaceAddr) } if nicID == 0 { - return tcpip.ErrNoRoute + return tcpip.ErrUnknownDevice } // TODO: check that v.MulticastAddr is a multicast address. @@ -503,6 +519,11 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error { } } + case tcpip.MulticastLoopOption: + e.mu.Lock() + e.multicastLoop = bool(v) + e.mu.Unlock() + case tcpip.ReusePortOption: e.mu.Lock() e.reusePort = v != 0 @@ -578,6 +599,14 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error { e.mu.Unlock() return nil + case *tcpip.MulticastLoopOption: + e.mu.RLock() + v := e.multicastLoop + e.mu.RUnlock() + + *o = tcpip.MulticastLoopOption(v) + return nil + case *tcpip.ReusePortOption: e.mu.RLock() v := e.reusePort |