From abe9d9f67f2c2c696ef26690fa8518dfc4e28728 Mon Sep 17 00:00:00 2001 From: Ghanan Gowripalan Date: Wed, 6 Jan 2021 11:39:14 -0800 Subject: Support add/remove IPv6 multicast group sock opt IPv4 was always supported but UDP never supported joining/leaving IPv6 multicast groups via socket options. Add: IPPROTO_IPV6, IPV6_JOIN_GROUP/IPV6_ADD_MEMBERSHIP Remove: IPPROTO_IPV6, IPV6_LEAVE_GROUP/IPV6_DROP_MEMBERSHIP Test: integration_test.TestUDPAddRemoveMembershipSocketOption PiperOrigin-RevId: 350396072 --- pkg/sentry/socket/netstack/netstack.go | 37 +++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'pkg/sentry/socket') diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index 3f587638f..fe11fca9c 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -2091,9 +2091,29 @@ func setSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name ep.SocketOptions().SetV6Only(v != 0) return nil - case linux.IPV6_ADD_MEMBERSHIP, - linux.IPV6_DROP_MEMBERSHIP, - linux.IPV6_IPSEC_POLICY, + case linux.IPV6_ADD_MEMBERSHIP: + req, err := copyInMulticastV6Request(optVal) + if err != nil { + return err + } + + return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.AddMembershipOption{ + NIC: tcpip.NICID(req.InterfaceIndex), + MulticastAddr: tcpip.Address(req.MulticastAddr[:]), + })) + + case linux.IPV6_DROP_MEMBERSHIP: + req, err := copyInMulticastV6Request(optVal) + if err != nil { + return err + } + + return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.RemoveMembershipOption{ + NIC: tcpip.NICID(req.InterfaceIndex), + MulticastAddr: tcpip.Address(req.MulticastAddr[:]), + })) + + case linux.IPV6_IPSEC_POLICY, linux.IPV6_JOIN_ANYCAST, linux.IPV6_LEAVE_ANYCAST, // TODO(b/148887420): Add support for IPV6_PKTINFO. @@ -2181,6 +2201,7 @@ func setSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name var ( inetMulticastRequestSize = int(binary.Size(linux.InetMulticastRequest{})) inetMulticastRequestWithNICSize = int(binary.Size(linux.InetMulticastRequestWithNIC{})) + inet6MulticastRequestSize = int(binary.Size(linux.Inet6MulticastRequest{})) ) // copyInMulticastRequest copies in a variable-size multicast request. The @@ -2214,6 +2235,16 @@ func copyInMulticastRequest(optVal []byte, allowAddr bool) (linux.InetMulticastR return req, nil } +func copyInMulticastV6Request(optVal []byte) (linux.Inet6MulticastRequest, *syserr.Error) { + if len(optVal) < inet6MulticastRequestSize { + return linux.Inet6MulticastRequest{}, syserr.ErrInvalidArgument + } + + var req linux.Inet6MulticastRequest + binary.Unmarshal(optVal[:inet6MulticastRequestSize], usermem.ByteOrder, &req) + return req, nil +} + // parseIntOrChar copies either a 32-bit int or an 8-bit uint out of buf. // // net/ipv4/ip_sockglue.c:do_ip_setsockopt does this for its socket options. -- cgit v1.2.3