Compare commits

..

4 commits

7 changed files with 267 additions and 215 deletions

View file

@ -52,6 +52,32 @@ This repo contains an example configuration at `config.toml` that allows a few b
desktop apps to function. It also demonstrates the use of `ask_cmd` and `notify_cmd` by defining filters on clipboard-related
requests. Detailed explanation of the configuration format is also contained in the example.
To launch a program under `wl-mitm`, set its `WAYLAND_DISPLAY` env variable to whatever `listen` is under `[socket]` in `config.toml`.
Note that you may want to use another container and pass _only_ the `wl-mitm`'d socket through for proper isolation.
A Word on Filtering
---
`wl-mitm` gives you a ton of flexibility on filtering. In particular, you are allowed to filter _any_ request on _any_ object
in `config.toml`.
However, please keep in mind that while most requests can be filtered, Wayland (and most of its protocols) is not designed to handle
this type of filtering. While a lot of requests can be filtered without consequences, there are a significant number of them that
will result in irrecoverable de-sync between the client and the server. For example, _any_ message that creates a new object ID
(of the type `new_id`) _will_ result in undefined behavior if filtered.
`wl-mitm` does provide the ability to _reject_ a request with an explicit error. Unfortunately, errors in Wayland are usually
fatal, and clients are not designed to recover from them.
The most reliable (and the only protocol-compliant) way to prevent a client from using certain features is to block the
entire global object where that feature resides. These are usually "manager" objects that live in the global registry,
and can be blocked in `allowed_globals` inside `config.toml`. Each extension protocol has to expose _some_ manager object
in order for clients to access their functionalities, and thus blocking them there will prevent clients from even knowing
their existence. However, globals can't be selectively blocked using `ask_cmd`, because clients usually bind to them as soon
as they start.
Since `notify_cmd` never blocks a request, it is safe to use on _any_ request filter.
XWayland
---

View file

@ -206,33 +206,44 @@ fn handle_interface(
let mut event_opcode = 0;
let mut request_opcode = 0;
let mut add_msg = |reader: &mut quick_xml::Reader<&[u8]>,
e: quick_xml::events::BytesStart<'_>,
is_empty: bool| {
let start_tag =
str::from_utf8(e.local_name().into_inner()).expect("Unable to parse start tag");
if start_tag == "event" {
// An event! Increment our opcode tracker for it!
event_opcode += 1;
msgs.push(handle_request_or_event(
reader,
event_opcode - 1,
WlMsgType::Event,
interface_name_snake,
e,
is_empty,
));
} else if start_tag == "request" {
// A request! Increment our opcode tracker for it!
request_opcode += 1;
msgs.push(handle_request_or_event(
reader,
request_opcode - 1,
WlMsgType::Request,
interface_name_snake,
e,
is_empty,
));
};
};
loop {
match reader.read_event().expect("Unable to parse XML file") {
Event::Eof => panic!("Unexpected EOF"),
Event::Start(e) => {
let start_tag =
str::from_utf8(e.local_name().into_inner()).expect("Unable to parse start tag");
if start_tag == "event" {
// An event! Increment our opcode tracker for it!
event_opcode += 1;
msgs.push(handle_request_or_event(
reader,
event_opcode - 1,
WlMsgType::Event,
interface_name_snake,
e,
));
} else if start_tag == "request" {
// A request! Increment our opcode tracker for it!
request_opcode += 1;
msgs.push(handle_request_or_event(
reader,
request_opcode - 1,
WlMsgType::Request,
interface_name_snake,
e,
));
};
add_msg(reader, e, false);
}
Event::Empty(e) => {
add_msg(reader, e, true);
}
Event::End(e) if e.local_name() == start.local_name() => break,
_ => continue,
@ -251,6 +262,7 @@ fn handle_request_or_event(
msg_type: WlMsgType,
interface_name_snake: &str,
start: quick_xml::events::BytesStart<'_>,
is_empty: bool,
) -> WlMsg {
let name_attr = start
.attributes()
@ -278,77 +290,80 @@ fn handle_request_or_event(
// Load arguments and their types from XML
let mut args: Vec<(String, WlArgType)> = Vec::new();
loop {
match reader.read_event().expect("Unable to parse XML file") {
Event::Eof => panic!("Unexpected EOF"),
Event::Empty(e)
if str::from_utf8(e.local_name().into_inner()).expect("utf8 encoding error")
== "arg" =>
{
let mut name: Option<String> = None;
let mut tt: Option<WlArgType> = None;
let mut interface_name: Option<String> = None;
if !is_empty {
loop {
match reader.read_event().expect("Unable to parse XML file") {
Event::Eof => panic!("Unexpected EOF"),
Event::Empty(e)
if str::from_utf8(e.local_name().into_inner())
.expect("utf8 encoding error")
== "arg" =>
{
let mut name: Option<String> = None;
let mut tt: Option<WlArgType> = None;
let mut interface_name: Option<String> = None;
for attr in e.attributes() {
let attr = attr.expect("attr parsing error");
let attr_name = str::from_utf8(attr.key.local_name().into_inner())
.expect("utf8 encoding error");
if attr_name == "name" {
name = Some(
str::from_utf8(&attr.value)
.expect("utf8 encoding error")
.to_string(),
);
} else if attr_name == "type" {
tt = Some(WlArgType::parse(
str::from_utf8(&attr.value).expect("utf8 encoding error"),
));
} else if attr_name == "interface" {
interface_name = Some(
str::from_utf8(&attr.value)
.expect("utf8 encoding error")
.to_string(),
);
for attr in e.attributes() {
let attr = attr.expect("attr parsing error");
let attr_name = str::from_utf8(attr.key.local_name().into_inner())
.expect("utf8 encoding error");
if attr_name == "name" {
name = Some(
str::from_utf8(&attr.value)
.expect("utf8 encoding error")
.to_string(),
);
} else if attr_name == "type" {
tt = Some(WlArgType::parse(
str::from_utf8(&attr.value).expect("utf8 encoding error"),
));
} else if attr_name == "interface" {
interface_name = Some(
str::from_utf8(&attr.value)
.expect("utf8 encoding error")
.to_string(),
);
}
}
}
if let Some(ref mut name) = name {
if name == "type" {
*name = "_type".to_string();
} else if name == "msg" {
*name = "_msg".to_string();
if let Some(ref mut name) = name {
if name == "type" {
*name = "_type".to_string();
} else if name == "msg" {
*name = "_msg".to_string();
}
}
}
if let Some(WlArgType::NewId(_)) = tt {
if let Some(interface_name) = interface_name {
tt.as_mut().unwrap().set_interface_name(interface_name);
} else {
// Unspecified interface for new_id; special serialization format!
args.push((
format!(
"{}_interface_name",
name.as_ref().expect("needs an arg name!")
),
WlArgType::String,
));
args.push((
format!(
"{}_interface_version",
name.as_ref().expect("needs an arg name!")
),
WlArgType::Uint,
))
if let Some(WlArgType::NewId(_)) = tt {
if let Some(interface_name) = interface_name {
tt.as_mut().unwrap().set_interface_name(interface_name);
} else {
// Unspecified interface for new_id; special serialization format!
args.push((
format!(
"{}_interface_name",
name.as_ref().expect("needs an arg name!")
),
WlArgType::String,
));
args.push((
format!(
"{}_interface_version",
name.as_ref().expect("needs an arg name!")
),
WlArgType::Uint,
))
}
}
}
args.push((
name.expect("args must have a name"),
tt.expect("args must have a type"),
));
args.push((
name.expect("args must have a name"),
tt.expect("args must have a type"),
));
}
Event::End(e) if e.local_name() == start.local_name() => break,
_ => continue,
}
Event::End(e) if e.local_name() == start.local_name() => break,
_ => continue,
}
}

View file

@ -192,28 +192,20 @@ impl WlMsg {
#opcode
}
fn self_opcode(&self) -> u16 {
#opcode
}
fn object_type() -> crate::objects::WlObjectType {
crate::proto::#interface_name_snake_upper
}
fn self_object_type(&self) -> crate::objects::WlObjectType {
crate::proto::#interface_name_snake_upper
}
fn self_msg_name(&self) -> &'static str {
fn msg_name() -> &'static str {
#msg_name_snake
}
fn static_type_id() -> std::any::TypeId {
std::any::TypeId::of::<#struct_name<'static>>()
fn is_destructor() -> bool {
#is_destructor
}
fn self_static_type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<#struct_name<'static>>()
fn num_consumed_fds() -> usize {
#num_consumed_fds
}
#[allow(unused, private_interfaces, non_snake_case)]
@ -231,28 +223,22 @@ impl WlMsg {
})
}
fn obj_id(&self) -> u32 {
fn _obj_id(&self) -> u32 {
self.obj_id
}
fn is_destructor(&self) -> bool {
#is_destructor
}
fn known_objects_created(&self) -> Option<Vec<(u32, crate::objects::WlObjectType)>> {
fn _known_objects_created(&self) -> Option<Vec<(u32, crate::objects::WlObjectType)>> {
#known_objects_created
}
fn to_json(&self) -> String {
fn _to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
fn num_consumed_fds(&self) -> usize {
#num_consumed_fds
}
}
unsafe impl<'a> crate::proto::AnyWlParsedMessage<'a> for #struct_name<'a> {}
unsafe impl<'a> crate::proto::DowncastableWlParsedMessage<'a> for #struct_name<'a> {
type Static = #struct_name<'static>;
}
pub struct #parser_fn_name;
@ -261,7 +247,7 @@ impl WlMsg {
&self,
objects: &'obj crate::proto::WlObjects,
msg: &'msg crate::codec::WlRawMsg,
) -> crate::proto::WaylandProtocolParsingOutcome<Box<dyn crate::proto::AnyWlParsedMessage<'msg> + 'msg>> {
) -> crate::proto::WaylandProtocolParsingOutcome<Box<dyn crate::proto::AnyWlParsedMessage + 'msg>> {
#struct_name::try_from_msg(objects, msg).map(|r| Box::new(r) as Box<_>)
}
}

View file

@ -145,28 +145,6 @@ impl<'a> WlMsgWriter<'a> {
self.write_queue.push(msg);
}
pub async fn write(&mut self, msg: WlRawMsg) -> io::Result<()> {
let (buf, fds) = msg.into_parts();
let mut written = 0usize;
while written < buf.len() {
self.egress.writable().await?;
let res = self
.egress
.send_with_fd(&buf[written..], unsafe { std::mem::transmute(fds.deref()) });
match res {
Ok(new_written) => written += new_written,
Err(e) if e.kind() == io::ErrorKind::WouldBlock => continue,
Err(e) => return Err(e),
}
}
Ok(())
}
/// Try to make progress by flushing some of the queued up messages into the stream.
/// When this resolves, note that we might have only partially written. In that
/// case the buffer is saved internally in this structure.

View file

@ -141,7 +141,7 @@ impl<'a> ConnDuplex<'a> {
match verdict {
WlMitmVerdict::Allowed => {
self.downstream_write.write(wl_raw_msg).await?;
self.downstream_write.queue_write(wl_raw_msg);
}
WlMitmVerdict::Terminate => {
return Err(io::Error::new(
@ -180,20 +180,18 @@ impl<'a> ConnDuplex<'a> {
match verdict {
WlMitmVerdict::Allowed => {
self.upstream_write.write(wl_raw_msg).await?;
self.upstream_write.queue_write(wl_raw_msg);
}
WlMitmVerdict::Rejected(error_code) => {
self.downstream_write
.write(
WlDisplayErrorEvent::new(
WL_DISPLAY_OBJECT_ID,
wl_raw_msg.obj_id,
error_code,
"Rejected by wl-mitm",
)
.build(),
self.downstream_write.queue_write(
WlDisplayErrorEvent::new(
WL_DISPLAY_OBJECT_ID,
wl_raw_msg.obj_id,
error_code,
"Rejected by wl-mitm",
)
.await?;
.build(),
);
}
WlMitmVerdict::Terminate => {
return Err(io::Error::new(
@ -217,6 +215,9 @@ impl<'a> ConnDuplex<'a> {
tokio::select! {
biased;
res = self.downstream_write.dequeue_write() => res?,
res = self.upstream_write.dequeue_write() => res?,
msg = self.upstream_read.read() => {
control_flow!(self.handle_s2c_event(msg?).await?);
}

View file

@ -35,27 +35,27 @@ impl<T> WaylandProtocolParsingOutcome<T> {
/// Internal module used to seal the [WlParsedMessage] trait
mod __private {
pub(super) trait WlParsedMessagePrivate: Send {}
pub(super) trait WlParsedMessagePrivate: Sized {}
pub(super) struct WlParsedMessagePrivateToken;
}
#[allow(private_bounds, private_interfaces)]
pub trait WlParsedMessage<'a>: __private::WlParsedMessagePrivate {
fn opcode() -> u16
where
Self: Sized;
fn object_type() -> WlObjectType
where
Self: Sized;
fn static_type_id() -> TypeId
where
Self: Sized;
fn opcode() -> u16;
fn object_type() -> WlObjectType;
fn msg_name() -> &'static str;
/// Is this request / event a destructor? That is, does it destroy [Self::obj_id()]?
fn is_destructor() -> bool;
/// How many fds have been consumed in parsing this message?
/// This is used to return any unused fds to the decoder.
fn num_consumed_fds() -> usize;
fn try_from_msg<'obj>(
objects: &'obj WlObjects,
msg: &'a WlRawMsg,
) -> WaylandProtocolParsingOutcome<Self>
where
Self: Sized + 'a,
Self: 'a,
{
// Verify object type and opcode
if objects.lookup_object(msg.obj_id) != Some(Self::object_type()) {
@ -74,19 +74,10 @@ pub trait WlParsedMessage<'a>: __private::WlParsedMessagePrivate {
_token: __private::WlParsedMessagePrivateToken,
) -> WaylandProtocolParsingOutcome<Self>
where
Self: Sized + 'a;
// dyn-available methods
fn self_opcode(&self) -> u16;
fn self_object_type(&self) -> WlObjectType;
fn self_msg_name(&self) -> &'static str;
fn self_static_type_id(&self) -> TypeId;
Self: 'a;
/// The object ID which this message acts upon
fn obj_id(&self) -> u32;
/// Is this request / event a destructor? That is, does it destroy [Self::obj_id()]?
fn is_destructor(&self) -> bool;
fn _obj_id(&self) -> u32;
/// List of (object id, object type) pairs created by this message
/// Note that this only includes objects created with a fixed, known interface
@ -94,43 +85,99 @@ pub trait WlParsedMessage<'a>: __private::WlParsedMessagePrivate {
/// serialized differently, and are not included here. However, the only
/// widely-used message with that capability is [WlRegistryBindRequest],
/// which is already handled separately on its own.
fn known_objects_created(&self) -> Option<Vec<(u32, WlObjectType)>>;
fn _known_objects_created(&self) -> Option<Vec<(u32, WlObjectType)>>;
/// Serialize this message into a JSON string, for use with ask scripts
fn to_json(&self) -> String;
/// How many fds have been consumed in parsing this message?
/// This is used to return any unused fds to the decoder.
fn num_consumed_fds(&self) -> usize;
fn _to_json(&self) -> String;
}
/// A version of [WlParsedMessage] that supports downcasting. By implementing this
/// trait, you assert that the [WlParsedMessage::static_type_id] and
/// [WlParsedMessage::self_static_type_id] implementations are sound: they MUST
/// return the [TypeId] of the implementing struct, assuming it had static lifetime.
/// trait, you assert that the [DowncastableWlParsedMessage::Static] MUST correspond
/// to a version of the implementor type with a static lifetime.
///
/// Any implementor also asserts that the type implementing this trait
/// does not contain any lifetime other than 'a, and that the implenetor struct is
/// _covariant_ with respect to lifetime 'a.
///
/// This is required for the soundness of the downcast_ref implementation.
pub unsafe trait AnyWlParsedMessage<'a>: WlParsedMessage<'a> {}
pub unsafe trait DowncastableWlParsedMessage<'a>: Send + WlParsedMessage<'a> {
type Static: 'static;
}
impl<'out, 'data: 'out> dyn AnyWlParsedMessage<'data> + 'data {
/// The implementation of dyn-available methods and downcasting for
/// [DowncastableWlParsedMessage]
pub trait AnyWlParsedMessage: Send {
fn static_type_id(&self) -> TypeId;
fn opcode(&self) -> u16;
fn object_type(&self) -> WlObjectType;
fn msg_name(&self) -> &'static str;
fn is_destructor(&self) -> bool;
fn obj_id(&self) -> u32;
fn known_objects_created(&self) -> Option<Vec<(u32, WlObjectType)>>;
fn to_json(&self) -> String;
fn num_consumed_fds(&self) -> usize;
}
impl<'a, T> AnyWlParsedMessage for T
where
T: DowncastableWlParsedMessage<'a> + 'a,
{
fn static_type_id(&self) -> TypeId {
TypeId::of::<T::Static>()
}
fn opcode(&self) -> u16 {
T::opcode()
}
fn object_type(&self) -> WlObjectType {
T::object_type()
}
fn msg_name(&self) -> &'static str {
T::msg_name()
}
fn is_destructor(&self) -> bool {
T::is_destructor()
}
fn obj_id(&self) -> u32 {
T::_obj_id(self)
}
fn known_objects_created(&self) -> Option<Vec<(u32, WlObjectType)>> {
T::_known_objects_created(self)
}
fn to_json(&self) -> String {
T::_to_json(self)
}
fn num_consumed_fds(&self) -> usize {
T::num_consumed_fds()
}
}
impl<'out, 'data: 'out> dyn AnyWlParsedMessage + 'data {
/// Downcast the type-erased, borrowed Wayland message to a concrete type. Note that the
/// safety of this relies on a few invariants:
///
/// 1. 'data outlives 'out (guaranteed by the trait bound above)
/// 2. The type implementing [AnyWlParsedMessage] does not contain any lifetime other than
/// 2. The type implementing [DowncastableWlParsedMessage] does not contain any lifetime other than
/// 'data (or 'a in the trait's definition).
pub fn downcast_ref<T: AnyWlParsedMessage<'data> + 'data>(&'out self) -> Option<&'out T> {
if self.self_static_type_id() != T::static_type_id() {
pub fn downcast_ref<
T: AnyWlParsedMessage + DowncastableWlParsedMessage<'data> + 'data,
>(
&'data self,
) -> Option<&'out T> {
if self.static_type_id() != TypeId::of::<T::Static>() {
return None;
}
// SAFETY: We have verified the type IDs match up.
//
// In addition, because [AnyWlParsedMessage]'s contract requires that no
// In addition, because [DowncastableWlParsedMessage]'s contract requires that no
// lifetime other than 'a ('data) is contained in the implemetor, the
// output type T cannot contain another lifetime that may be transmuted
// by this unsafe block.
@ -148,13 +195,13 @@ pub trait WlMsgParserFn: Send + Sync {
&self,
objects: &'obj WlObjects,
msg: &'msg WlRawMsg,
) -> WaylandProtocolParsingOutcome<Box<dyn AnyWlParsedMessage<'msg> + 'msg>>;
) -> WaylandProtocolParsingOutcome<Box<dyn AnyWlParsedMessage + 'msg>>;
}
/// Messages that can be converted back to [WlRawMsg]
pub trait WlConstructableMessage<'a>: Sized + WlParsedMessage<'a> {
fn build(&self) -> WlRawMsg {
WlRawMsg::build(self.obj_id(), Self::opcode(), |buf, fds| {
WlRawMsg::build(self._obj_id(), Self::opcode(), |buf, fds| {
self.build_inner(buf, fds)
})
}
@ -187,7 +234,7 @@ static WL_EVENT_REQUEST_PARSERS: LazyLock<(
pub fn decode_event<'obj, 'msg>(
objects: &'obj WlObjects,
msg: &'msg WlRawMsg,
) -> WaylandProtocolParsingOutcome<Box<dyn AnyWlParsedMessage<'msg> + 'msg>> {
) -> WaylandProtocolParsingOutcome<Box<dyn AnyWlParsedMessage + 'msg>> {
let Some(obj_type) = objects.lookup_object(msg.obj_id) else {
return WaylandProtocolParsingOutcome::Unknown;
};
@ -207,7 +254,7 @@ pub fn decode_event<'obj, 'msg>(
pub fn decode_request<'obj, 'msg>(
objects: &'obj WlObjects,
msg: &'msg WlRawMsg,
) -> WaylandProtocolParsingOutcome<Box<dyn AnyWlParsedMessage<'msg> + 'msg>> {
) -> WaylandProtocolParsingOutcome<Box<dyn AnyWlParsedMessage + 'msg>> {
let Some(obj_type) = objects.lookup_object(msg.obj_id) else {
return WaylandProtocolParsingOutcome::Unknown;
};

View file

@ -8,10 +8,9 @@ use crate::{
objects::WlObjects,
proto::{
AnyWlParsedMessage, WaylandProtocolParsingOutcome, WlDisplayDeleteIdEvent,
WlKeyboardEnterEvent, WlParsedMessage, WlPointerEnterEvent, WlRegistryBindRequest,
WlRegistryGlobalEvent, WlRegistryGlobalRemoveEvent, WlTouchDownEvent,
XdgSurfaceGetToplevelRequest, XdgToplevelSetAppIdRequest, XdgToplevelSetTitleRequest,
XdgWmBaseGetXdgSurfaceRequest,
WlKeyboardEnterEvent, WlPointerEnterEvent, WlRegistryBindRequest, WlRegistryGlobalEvent,
WlRegistryGlobalRemoveEvent, WlTouchDownEvent, XdgSurfaceGetToplevelRequest,
XdgToplevelSetAppIdRequest, XdgToplevelSetTitleRequest, XdgWmBaseGetXdgSurfaceRequest,
},
};
@ -118,7 +117,7 @@ impl WlMitmState {
/// is not handled here.
fn handle_created_or_destroyed_objects(
&mut self,
msg: &dyn AnyWlParsedMessage<'_>,
msg: &dyn AnyWlParsedMessage,
from_client: bool,
) -> bool {
if let Some(created_objects) = msg.known_objects_created() {
@ -133,7 +132,7 @@ impl WlMitmState {
is_half_destroyed = self.objects.is_half_destroyed(id),
"Trying to create object via message {}::{} but the object ID is already used!",
parent_obj.interface(),
msg.self_msg_name()
msg.msg_name()
);
return false;
@ -145,7 +144,7 @@ impl WlMitmState {
obj_id = id,
"Created object via message {}::{}",
parent_obj.interface(),
msg.self_msg_name()
msg.msg_name()
);
self.objects.record_object(tt, id);
}
@ -164,7 +163,7 @@ impl WlMitmState {
obj_id = msg.obj_id(),
"Object destructed via destructor {}::{}",
obj_type.interface(),
msg.self_msg_name()
msg.msg_name()
);
self.objects.remove_object(msg.obj_id(), from_client);
@ -179,13 +178,13 @@ impl WlMitmState {
fn prepare_command(
&self,
msg: &dyn AnyWlParsedMessage<'_>,
msg: &dyn AnyWlParsedMessage,
cmd_str: &str,
desc: &str,
) -> tokio::process::Command {
let mut cmd = tokio::process::Command::new(cmd_str);
cmd.arg(msg.self_object_type().interface());
cmd.arg(msg.self_msg_name());
cmd.arg(msg.object_type().interface());
cmd.arg(msg.msg_name());
cmd.arg(desc);
cmd.env("WL_MITM_MSG_JSON", msg.to_json());
@ -250,8 +249,8 @@ impl WlMitmState {
num_fds = raw_msg.fds.len(),
num_consumed_fds = msg.num_consumed_fds(),
"{}::{}",
msg.self_object_type().interface(),
msg.self_msg_name(),
msg.object_type().interface(),
msg.msg_name(),
)
}
@ -260,7 +259,7 @@ impl WlMitmState {
if self.objects.is_half_destroyed(msg.obj_id()) {
error!(
obj_id = msg.obj_id(),
opcode = msg.self_opcode(),
opcode = msg.opcode(),
"Client request detected on object already scheduled for destruction; aborting!"
);
return outcome.terminate();
@ -334,11 +333,11 @@ impl WlMitmState {
.config
.filter
.requests
.get(msg.self_object_type().interface())
.get(msg.object_type().interface())
{
if let Some(filtered) = filtered_requests
.iter()
.find(|f| f.requests.contains(msg.self_msg_name()))
.find(|f| f.requests.contains(msg.msg_name()))
{
match filtered.action {
WlFilterRequestAction::Ask => {
@ -346,8 +345,8 @@ impl WlMitmState {
info!(
ask_cmd = ask_cmd,
"Running ask command for {}::{}",
msg.self_object_type().interface(),
msg.self_msg_name()
msg.object_type().interface(),
msg.msg_name()
);
let mut cmd = self.prepare_command(
@ -360,8 +359,8 @@ impl WlMitmState {
if !status.success() {
warn!(
"Blocked {}::{} because of return status {}",
msg.self_object_type().interface(),
msg.self_msg_name(),
msg.object_type().interface(),
msg.msg_name(),
status
);
@ -379,8 +378,8 @@ impl WlMitmState {
warn!(
"Blocked {}::{} because of missing ask_cmd",
msg.self_object_type().interface(),
msg.self_msg_name()
msg.object_type().interface(),
msg.msg_name()
);
return match filtered.block_type {
WlFilterRequestBlockType::Ignore => outcome.filtered(),
@ -394,8 +393,8 @@ impl WlMitmState {
info!(
notify_cmd = notify_cmd,
"Running notify command for {}::{}",
msg.self_object_type().interface(),
msg.self_msg_name()
msg.object_type().interface(),
msg.msg_name()
);
let mut cmd = self.prepare_command(
@ -410,8 +409,8 @@ impl WlMitmState {
WlFilterRequestAction::Block => {
warn!(
"Blocked {}::{}",
msg.self_object_type().interface(),
msg.self_msg_name()
msg.object_type().interface(),
msg.msg_name()
);
return match filtered.block_type {
WlFilterRequestBlockType::Ignore => outcome.filtered(),
@ -458,8 +457,8 @@ impl WlMitmState {
num_fds = raw_msg.fds.len(),
num_consumed_fds = msg.num_consumed_fds(),
"{}::{}",
msg.self_object_type().interface(),
msg.self_msg_name(),
msg.object_type().interface(),
msg.msg_name(),
)
}