Closed leonaves closed 4 years ago
I think this is might be related to SIP, which is on by default. See https://apple.stackexchange.com/questions/208478/how-do-i-disable-system-integrity-protection-sip-aka-rootless-on-macos-os-x
It seems to be picking an unused/inactive interface by default. You can directly tell it which interface to use with the -i parameter. However, when doing this in my attempts so far, it displays no traffic use despite there definitely being traffic.
To be clear, it does show the UI and there is no longer the mentioned error if, for example, I run sudo what en0
on my system where en0 is the name of the interface that is my top priority default ethernet port. The app just claims 0 bytes traffic and has empty boxes.
I am seeing same issue on Mojave Version 10.14.5
I am also seeing no traffic displayed. (Mojave Version 10.14.6)
Same
chances are there's a tool called what
already installed on osx. use sudo ~/.cargo/bin/what -i en0
to be sure to use the right tool
Same problem here. I tried all network interfaces with the "-i" argument, all of them show no traffic, except en5 which still outputs the "device not configured" error
Mojave 10.14.6, doesn't run without sudo. With sudo, it starts but does not display any data.
Same empty screen for me on High Sierra. Using sudo or not same empty screen. I am on hackintosh so no SIP for me at all. Listening for en0 does not improve. :(
I think I found why an error occurs without specifying an interface. We get all the interfaces and loop around them. If some interface does not active, then we return an error. Therefore, even one non-working interface breaks everything.
https://github.com/imsnif/what/blob/c9b9025577d0e1f831c9ebb054a5ac00b7a89796/src/os/shared.rs#L94-L97 And... https://github.com/imsnif/what/blob/b150bf3ef49d38b8839c19cd711fb91cbdc20f38/src/os/shared.rs#L33-L43
In get_datalink_channel
we get an error.
Please check me out, I started learning Rust a couple of days ago :-)
@Grishy - this looks like the issue and you describe it perfectly. :) Would you be interested in working on a PR to fix it? I'd be happy to provide guidance.
The no-traffic issue could, as @hobofan mentioned, be related to not being able to run lsof
properly (which is how we get process information on MacOS). We can discuss that issue further here: https://github.com/imsnif/what/issues/34 - would be happy to hear input for all who experience it.
@imsnif That would be great! But I'm afraid you will be a little disappointed ๐ I have not done PR yet and have not programmed in Rust (just debug your code 3 min). But I will try. I have little experience with the network (from Golang) and I have a macOS :)
@Grishy - I promise not to be disappointed, and since there is a workaround for this issue (using the -i flag), there is no urgency. Take as much time as you need, and ping me here or privately through email for any help whatsoever.
@Grishy, just some hint in case it helps :)
Something that would work would be to make get_datalink_channel
return
Result<Option<Box<dyn DataLinkReceiver>>, failure::Error>
(note the Box
being wrapped in Option
) and returning a None
in case there is an error listening. Then in the first snippet you linked you can filter the None
s. Take a look into filter_map
and flatten
.
EDIT: Thinking a bit more about it, maybe we can even get rid of the Result
if we don't want to fail here. We should also check at some point that the vector of interfaces is not empty.
I have now set up the development environment and was able to start the project normally in debug mode ๐
At the moment I do not understand what the word dyn
is responsible for...
Do I understand correctly that we need an additional Option
because we need to return something with error. We cannot return something like:
return nil, failure::bail!("Unknown interface type");
because we do not have in Rust null pointers. It's just that I'm looking at examples now and everything is much simpler here) https://doc.rust-lang.org/stable/rust-by-example/error/iter_result.html
Also, the compiler itself can recognize
match datalink::channel(interface, config) {
Ok(Ethernet(_tx, rx)) => Ok(rx),
// ...
like
Result<Box<dyn DataLinkReceiver>, failure::Error>
Or are we somehow helping him?
I'm having the same issue on Mojave 10.14.6.
Neither sudo what
nor sudo what -i en0
show any network activity.
@rtulip You have no error as in the issue header when starting without specifying an interface?
@Grishy dyn
is a way to make explicit that DataLinkReceiver
is a trait object. This would be similar to an interface in golang. As you say the compiler understands Ok(rx)
as the Ok
variant of the Result
, and rx
is the aforementioned trait object; because the size of the trait object is not known (it could be any type implementing DataLinkReceiver
) we need a way to refer to it indirectly, a pointer, and in this case the actual object implementing DataLinkReceiver
is in the heap (this is the box).
About a possible solution, we want to avoid bail
ing out because that would turn the Result
into the Err
variant, and when we hit this question mark:
https://github.com/imsnif/what/blob/a935397e66c96d989e7b81157ee603b0a58664d2/src/os/shared.rs#L97
we will return early if we find an error (collect
is turning a Vec<Result<T, U>>
into a Result<Vec<T>, U>
under the hood).
So one think we can do would be to make get_datalink_channel
return an Option<Box<dyn DataLinkReceiver>>
(without the result) so we can end up with a Vec<Option<T>>
and turn that into a Vec<T>
, checking at some point that the vector is not empty. Maybe @imsnif has another idea but I think we could check that in try_main
(main.rs).
Let me know if this helps!
@ebroto Thanks! I got to the point where the code after my changes at least compiles ๐ x2
let network_frames = network_interfaces
.iter()
.map(|iface| get_datalink_channel(iface))
.filter_map(Result::ok)
.collect::<Vec<_>>();
Itโs bad that we drown out the errors, although it is not clear what to do with them (output to the console?)
Maybe use partition()
and display?
With Option
, we also lose errors.
Cool!
IMO it's OK in this case to ignore the errors as it means that the interfaces are not usable for us. We should error out though in case there are no available interfaces.
@ebroto ok, add check on len == 0 and create PR? I just started looking for how to get connections in macOS.
Sure, open the PR and we can discuss it there :)
+1 On macOS 10.15.2:
> bandwhich -i en0
Error: Failed to listen on network interface: No such file or directory (os error 2)
> sudo bandwhich -i en0
Does run but doesnโt display any data.
The interface error has been fixed in 0.7.0
. The no-traffic error has been partially fixed (we have a workaround that should work in most cases), and are working on a permanent fix for all cases - it's dependent on an external dependency.
To follow the progress of that other issue, see: https://github.com/imsnif/bandwhich/issues/51
EDIT: Almost forgot to mention - thanks @Grishy for the fix!!
I can't confirm. I run bandwhich 0.7.0
on Catalina 10.15.2 and the symptoms are exactly the same as before.
Without sudo
I get the Failed to find any network interface to listen on.
error. With sudo
I get an empty interface (no traffic displayed).
Hey @virtualritz, you can follow the progress of the empty interface issue here: https://github.com/imsnif/bandwhich/issues/51
@imsnif: ok, re. the empty interface. But what about the Failed to find any network interface to listen on.
error? Is bandwhich
meant to only work with root privileges?
I have the version just released on homebrew. It needs sudo to run, doesn't seem to need you to specify the interface either, but sudo is definitely needed to prevent the Failed to find any network interface to listen on
error.
Yeah, I'm afraid sudo is definitely required in order to run. OSes don't like giving permissions to sniff network packets without it (and rightfully so :) ).
On the other hand, we just put an error that should tell you to use sudo if you did not. I'm sorry it didn't show in your case! Maybe it doesn't work on a mac?
Would one of you be willing to open an issue for this? You should be told to use 'sudo'.
I did some digging and indeed the code in os/shared.rs
that deals with this doesn't trigger on macOS because the ErrorKind
returned when ran w/o sudo
on Catalina is actually ErrorKind::NotFound
, not ErrorKind::PermissionDenied
.
This quick fix in os/shared.rs
works for me on Catalina to get the Try running with sudo.
error:
if (ErrorKind::PermissionDenied == iface_error.kind())
|| (cfg!(target_os = "macos") && (ErrorKind::NotFound == iface_error.kind()))
Thanks @virtualritz - I'm opening a new issue for this. Feel free to pick it up!
On Catalina (10.15.2):