Compare commits

...
Sign in to create a new pull request.

4 commits

5 changed files with 254 additions and 181 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 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. 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 XWayland
--- ---

View file

@ -206,10 +206,9 @@ fn handle_interface(
let mut event_opcode = 0; let mut event_opcode = 0;
let mut request_opcode = 0; let mut request_opcode = 0;
loop { let mut add_msg = |reader: &mut quick_xml::Reader<&[u8]>,
match reader.read_event().expect("Unable to parse XML file") { e: quick_xml::events::BytesStart<'_>,
Event::Eof => panic!("Unexpected EOF"), is_empty: bool| {
Event::Start(e) => {
let start_tag = let start_tag =
str::from_utf8(e.local_name().into_inner()).expect("Unable to parse start tag"); str::from_utf8(e.local_name().into_inner()).expect("Unable to parse start tag");
if start_tag == "event" { if start_tag == "event" {
@ -221,6 +220,7 @@ fn handle_interface(
WlMsgType::Event, WlMsgType::Event,
interface_name_snake, interface_name_snake,
e, e,
is_empty,
)); ));
} else if start_tag == "request" { } else if start_tag == "request" {
// A request! Increment our opcode tracker for it! // A request! Increment our opcode tracker for it!
@ -231,8 +231,19 @@ fn handle_interface(
WlMsgType::Request, WlMsgType::Request,
interface_name_snake, interface_name_snake,
e, e,
is_empty,
)); ));
}; };
};
loop {
match reader.read_event().expect("Unable to parse XML file") {
Event::Eof => panic!("Unexpected EOF"),
Event::Start(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, Event::End(e) if e.local_name() == start.local_name() => break,
_ => continue, _ => continue,
@ -251,6 +262,7 @@ fn handle_request_or_event(
msg_type: WlMsgType, msg_type: WlMsgType,
interface_name_snake: &str, interface_name_snake: &str,
start: quick_xml::events::BytesStart<'_>, start: quick_xml::events::BytesStart<'_>,
is_empty: bool,
) -> WlMsg { ) -> WlMsg {
let name_attr = start let name_attr = start
.attributes() .attributes()
@ -278,11 +290,13 @@ fn handle_request_or_event(
// Load arguments and their types from XML // Load arguments and their types from XML
let mut args: Vec<(String, WlArgType)> = Vec::new(); let mut args: Vec<(String, WlArgType)> = Vec::new();
if !is_empty {
loop { loop {
match reader.read_event().expect("Unable to parse XML file") { match reader.read_event().expect("Unable to parse XML file") {
Event::Eof => panic!("Unexpected EOF"), Event::Eof => panic!("Unexpected EOF"),
Event::Empty(e) Event::Empty(e)
if str::from_utf8(e.local_name().into_inner()).expect("utf8 encoding error") if str::from_utf8(e.local_name().into_inner())
.expect("utf8 encoding error")
== "arg" => == "arg" =>
{ {
let mut name: Option<String> = None; let mut name: Option<String> = None;
@ -351,6 +365,7 @@ fn handle_request_or_event(
_ => continue, _ => continue,
} }
} }
}
WlMsg { WlMsg {
interface_name_snake: interface_name_snake.to_string(), interface_name_snake: interface_name_snake.to_string(),

View file

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

View file

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

View file

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