[netstack] add IPV6_{ADD,DROP}_MEMBERSHIP

This is not yet correctly implemented upstream.

NET-1901 #comment

Test: None
Change-Id: Ibb7b9359d6ac43b275ee4d344c024302bc678697
diff --git a/go/src/netstack/socket_conv.go b/go/src/netstack/socket_conv.go
index a494367..caf87ff 100644
--- a/go/src/netstack/socket_conv.go
+++ b/go/src/netstack/socket_conv.go
@@ -448,9 +448,26 @@
 		v := binary.LittleEndian.Uint32(optVal)
 		return ep.SetSockOpt(tcpip.V6OnlyOption(v))
 
+	case C.IPV6_ADD_MEMBERSHIP, C.IPV6_DROP_MEMBERSHIP:
+		var ipv6_mreq C.struct_ipv6_mreq
+		if err := ipv6_mreq.Unmarshal(optVal); err != nil {
+			return tcpip.ErrInvalidOptionValue
+		}
+
+		o := tcpip.MembershipOption{
+			NIC:           tcpip.NICID(ipv6_mreq.ipv6mr_interface),
+			MulticastAddr: tcpip.Address(ipv6_mreq.ipv6mr_multiaddr.Bytes()),
+		}
+		switch name {
+		case C.IPV6_ADD_MEMBERSHIP:
+			return ep.SetSockOpt(tcpip.AddMembershipOption(o))
+		case C.IPV6_DROP_MEMBERSHIP:
+			return ep.SetSockOpt(tcpip.RemoveMembershipOption(o))
+		default:
+			panic("unreachable")
+		}
+
 	case
-		C.IPV6_ADD_MEMBERSHIP,
-		C.IPV6_DROP_MEMBERSHIP,
 		C.IPV6_IPSEC_POLICY,
 		C.IPV6_JOIN_ANYCAST,
 		C.IPV6_LEAVE_ANYCAST,
diff --git a/go/src/netstack/socket_encode.go b/go/src/netstack/socket_encode.go
index 34b01da..e03543d 100644
--- a/go/src/netstack/socket_encode.go
+++ b/go/src/netstack/socket_encode.go
@@ -98,6 +98,15 @@
 	return nil
 }
 
+func (v *C.struct_ipv6_mreq) Unmarshal(data []byte) error {
+	const size = C.sizeof_struct_ipv6_mreq
+
+	if n := copy((*[size]byte)(unsafe.Pointer(v))[:], data); n < size {
+		return fmt.Errorf("short %T: %d/%d", v, n, size)
+	}
+	return nil
+}
+
 func (v *C.netc_if_info_t) MarshalTo(data []byte) (int, error) {
 	const size = C.sizeof_netc_if_info_t