Closed SajjadPourali closed 3 months ago
you mean, just simplely add a tag target_os = "freebsd"
, tun2
will support freebsd fine? like this
#[cfg(target_os = "linux", target_os = "freebsd")]
pub mod linux;
#[cfg(target_os = "linux", target_os = "freebsd")]
pub use self::linux::{create, Configuration, Device, Queue};
it appears that the provided patch is not sufficient. Let's keep it open for the future improvement.
root@free:~/rust-tun # uname -a
FreeBSD free 14.0-RELEASE FreeBSD 14.0-RELEASE #0 releng/14.0-n265380-f9716eee8ab4: Fri Nov 10 05:54:07 UTC 2023 root@releng1.nyi.freebsd.org:/usr/obj/usr/src/arm64.aarch64/sys/GENERIC arm64
root@free:~/rust-tun # cargo check
Checking tun2 v0.6.2 (/root/rust-tun)
error[E0433]: failed to resolve: could not find `linux` in `platform`
--> src/platform/freebsd/device.rs:34:15
|
34 | platform::linux::sys::*,
| ^^^^^ could not find `linux` in `platform`
error[E0432]: unresolved imports `libc::IFF_MULTI_QUEUE`, `libc::IFF_NO_PI`, `libc::IFF_TAP`, `libc::IFF_TUN`
--> src/platform/freebsd/device.rs:16:44
|
16 | self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_RUNNING, IFF_TAP,
| ^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^ no `IFF_TAP` in the root
| | |
| | no `IFF_NO_PI` in the root
| no `IFF_MULTI_QUEUE` in the root
17 | IFF_TUN, IFF_UP, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
| ^^^^^^^ no `IFF_TUN` in the root
|
help: a similar name exists in the module
|
16 | self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NOARP, IFF_RUNNING, IFF_TAP,
| ~~~~~~~~~
help: a similar name exists in the module
|
16 | self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_RUNNING, IFF_UP,
| ~~~~~~
help: a similar name exists in the module
|
17 | IFF_UP, IFF_UP, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
| ~~~~~~
error[E0432]: unresolved import `ioctl`
--> src/platform/freebsd/sys.rs:17:5
|
17 | use ioctl::*;
| ^^^^^ use of undeclared crate or module `ioctl`
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:20:1
|
20 | ioctl!(bad read siocgifflags with 0x8913; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:21:1
|
21 | ioctl!(bad write siocsifflags with 0x8914; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:22:1
|
22 | ioctl!(bad read siocgifaddr with 0x8915; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:23:1
|
23 | ioctl!(bad write siocsifaddr with 0x8916; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:24:1
|
24 | ioctl!(bad read siocgifdstaddr with 0x8917; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:25:1
|
25 | ioctl!(bad write siocsifdstaddr with 0x8918; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:26:1
|
26 | ioctl!(bad read siocgifbrdaddr with 0x8919; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:27:1
|
27 | ioctl!(bad write siocsifbrdaddr with 0x891a; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:28:1
|
28 | ioctl!(bad read siocgifnetmask with 0x891b; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:29:1
|
29 | ioctl!(bad write siocsifnetmask with 0x891c; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:30:1
|
30 | ioctl!(bad read siocgifmtu with 0x8921; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:31:1
|
31 | ioctl!(bad write siocsifmtu with 0x8922; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:32:1
|
32 | ioctl!(bad write siocsifname with 0x8923; ifreq);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:34:1
|
34 | ioctl!(write tunsetiff with b'T', 202; c_int);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:35:1
|
35 | ioctl!(write tunsetpersist with b'T', 203; c_int);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:36:1
|
36 | ioctl!(write tunsetowner with b'T', 204; c_int);
| ^^^^^
error: cannot find macro `ioctl` in this scope
--> src/platform/freebsd/sys.rs:37:1
|
37 | ioctl!(write tunsetgroup with b'T', 206; c_int);
| ^^^^^
warning: unused imports: `c_int`, `ifreq`
--> src/platform/freebsd/sys.rs:18:12
|
18 | use libc::{c_int, ifreq};
| ^^^^^ ^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0308]: mismatched types
--> src/platform/freebsd/device.rs:85:39
|
85 | req.ifr_ifru.ifru_flags = device_type
| _____________-----------------------___^
| | |
| | expected due to the type of this binding
86 | | | if packet_information { 0 } else { iff_no_pi }
87 | | | if queues_num > 1 { iff_multi_queue } else { 0 };
| |__________________________________________________________________^ expected `[i16; 2]`, found `i16`
error[E0425]: cannot find function `tunsetiff` in this scope
--> src/platform/freebsd/device.rs:93:20
|
93 | if tunsetiff(tun.0, &mut req as *mut _ as *mut _) < 0 {
| ^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `tunsetpersist` in this scope
--> src/platform/freebsd/device.rs:133:16
|
133 | if tunsetpersist(self.as_raw_fd(), &1) < 0 {
| ^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `tunsetowner` in this scope
--> src/platform/freebsd/device.rs:144:16
|
144 | if tunsetowner(self.as_raw_fd(), &value) < 0 {
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `tunsetgroup` in this scope
--> src/platform/freebsd/device.rs:155:16
|
155 | if tunsetgroup(self.as_raw_fd(), &value) < 0 {
| ^^^^^^^^^^^ not found in this scope
error[E0609]: no field `ifru_newname` on type `__c_anonymous_ifr_ifru`
--> src/platform/freebsd/device.rs:222:30
|
222 | req.ifr_ifru.ifru_newname.as_mut_ptr(),
| ^^^^^^^^^^^^ unknown field
|
= note: available fields are: `ifru_addr`, `ifru_dstaddr`, `ifru_broadaddr`, `ifru_buffer`, `ifru_flags` ... and 10 others
error[E0425]: cannot find function `siocsifname` in this scope
--> src/platform/freebsd/device.rs:226:16
|
226 | if siocsifname(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocgifflags` in this scope
--> src/platform/freebsd/device.rs:240:16
|
240 | if siocgifflags(self.ctl.as_raw_fd(), &mut req) < 0 {
| ^^^^^^^^^^^^ not found in this scope
error[E0368]: binary assignment operation `|=` cannot be applied to type `[i16; 2]`
--> src/platform/freebsd/device.rs:245:17
|
245 | req.ifr_ifru.ifru_flags |= (IFF_UP | IFF_RUNNING) as c_short;
| -----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| cannot use `|=` on type `[i16; 2]`
error[E0368]: binary assignment operation `&=` cannot be applied to type `[i16; 2]`
--> src/platform/freebsd/device.rs:247:17
|
247 | req.ifr_ifru.ifru_flags &= !(IFF_UP as c_short);
| -----------------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| cannot use `&=` on type `[i16; 2]`
error[E0425]: cannot find function `siocsifflags` in this scope
--> src/platform/freebsd/device.rs:250:16
|
250 | if siocsifflags(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocgifaddr` in this scope
--> src/platform/freebsd/device.rs:262:16
|
262 | if siocgifaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocsifaddr` in this scope
--> src/platform/freebsd/device.rs:275:16
|
275 | if siocsifaddr(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocgifdstaddr` in this scope
--> src/platform/freebsd/device.rs:287:16
|
287 | if siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
| ^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocsifdstaddr` in this scope
--> src/platform/freebsd/device.rs:300:16
|
300 | if siocsifdstaddr(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocgifbrdaddr` in this scope
--> src/platform/freebsd/device.rs:312:16
|
312 | if siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
| ^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocsifbrdaddr` in this scope
--> src/platform/freebsd/device.rs:325:16
|
325 | if siocsifbrdaddr(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocgifnetmask` in this scope
--> src/platform/freebsd/device.rs:337:16
|
337 | if siocgifnetmask(self.ctl.as_raw_fd(), &mut req) < 0 {
| ^^^^^^^^^^^^^^ not found in this scope
error[E0609]: no field `ifru_netmask` on type `__c_anonymous_ifr_ifru`
--> src/platform/freebsd/device.rs:341:41
|
341 | SockAddr::new(&req.ifr_ifru.ifru_netmask).map(Into::into)
| ^^^^^^^^^^^^ unknown field
|
= note: available fields are: `ifru_addr`, `ifru_dstaddr`, `ifru_broadaddr`, `ifru_buffer`, `ifru_flags` ... and 10 others
error[E0609]: no field `ifru_netmask` on type `__c_anonymous_ifr_ifru`
--> src/platform/freebsd/device.rs:348:26
|
348 | req.ifr_ifru.ifru_netmask = SockAddr::from(value).into();
| ^^^^^^^^^^^^ unknown field
|
= note: available fields are: `ifru_addr`, `ifru_dstaddr`, `ifru_broadaddr`, `ifru_buffer`, `ifru_flags` ... and 10 others
error[E0425]: cannot find function `siocsifnetmask` in this scope
--> src/platform/freebsd/device.rs:350:16
|
350 | if siocsifnetmask(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocgifmtu` in this scope
--> src/platform/freebsd/device.rs:362:16
|
362 | if siocgifmtu(self.ctl.as_raw_fd(), &mut req) < 0 {
| ^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `siocsifmtu` in this scope
--> src/platform/freebsd/device.rs:375:16
|
375 | if siocsifmtu(self.ctl.as_raw_fd(), &req) < 0 {
| ^^^^^^^^^^ not found in this scope
Some errors have detailed explanations: E0308, E0368, E0425, E0432, E0433, E0609.
For more information about an error, try `rustc --explain E0308`.
warning: `tun2` (lib) generated 1 warning
error: could not compile `tun2` (lib) due to 43 previous errors; 1 warning emitted
root@free:~/rust-tun #
This patch is sufficient to build narrowlink. But maybe it isn't sufficient in general.
I think there are multiple minor changes that are required to get this working:
platform/mod.rs
:
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub mod linux;
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub use self::linux::{create, Configuration, Device, Queue};
Cargo.toml
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos", target_os = "android"))'.dependencies]
ioctl = { version = "0.8", package = "ioctl-sys" }
In the initial comment by @ssrlive, the any
specifier was missing in the platform/mod.rs
file. Many of the errors were also due to missing ioctl
, which should be fixed by the second change I proposed.
Could you try this again with the suggested changes? I do not have a FreeBSD VM available to me at the moment.
ioctl-sys
support openbsb
and not support freebsd
.
Since we have replaced ioctl-sys
with nix
, nix
supports freebsd
, this platform can be achieved after doing minor changes, I think. People having FreeBSD
, OpenBSD
environments can have a try to test whether the change works
platform/mod.rs
:
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub mod linux;
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub use self::linux::{create, Device, PlatformConfig};
Cargo.toml
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos", target_os = "android"))'.dependencies]
nix = { version = "0.27", features = ["ioctl"] }
If it works, I think changing the name of the module linux
to unix_like
to cover these platforms is reasonable.
emm. sounds good.
@xmh0511: FreeBSD uses slightly different APIs. I believe https://github.com/LaKabane/libtuntap/blob/master/tuntap-unix-freebsd.c could be inspiring for implementation.
root@freebsd:/home/test/rust-tun # git diff
diff --git a/Cargo.toml b/Cargo.toml
index be374c1..79eb3c8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,7 @@ tokio = { version = "1", features = [
], optional = true }
tokio-util = { version = "0.7", features = ["codec"], optional = true }
-[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))'.dependencies]
+[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos", target_os = "android"))'.dependencies]
nix = { version = "0.27", features = ["ioctl"] }
[target.'cfg(target_os = "windows")'.dependencies]
diff --git a/src/platform/mod.rs b/src/platform/mod.rs
index 7bb628d..ac175ab 100644
--- a/src/platform/mod.rs
+++ b/src/platform/mod.rs
@@ -17,9 +17,9 @@
#[cfg(unix)]
pub mod posix;
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub mod linux;
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub use self::linux::{create, Device, PlatformConfig};
#[cfg(target_os = "macos")]
root@freebsd:/home/test/rust-tun # cargo check
Checking tun2 v1.1.1 (/home/test/rust-tun)
error[E0432]: unresolved imports `libc::IFF_MULTI_QUEUE`, `libc::IFF_NO_PI`, `libc::IFF_TAP`, `libc::IFF_TUN`
--> src/platform/linux/device.rs:16:44
|
16 | self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_RUNNING, IFF_TAP,
| ^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^ no `IFF_TAP` in the root
| | |
| | no `IFF_NO_PI` in the root
| no `IFF_MULTI_QUEUE` in the root
17 | IFF_TUN, IFF_UP, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
| ^^^^^^^ no `IFF_TUN` in the root
|
help: a similar name exists in the module
|
16 | self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NOARP, IFF_RUNNING, IFF_TAP,
| ~~~~~~~~~
help: a similar name exists in the module
|
16 | self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_RUNNING, IFF_UP,
| ~~~~~~
help: a similar name exists in the module
|
17 | IFF_UP, IFF_UP, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
| ~~~~~~
error[E0425]: cannot find value `TUN_PROTO_IP6` in this scope
--> src/platform/posix/split.rs:52:25
|
52 | return Some(TUN_PROTO_IP6);
| ^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find value `TUN_PROTO_IP4` in this scope
--> src/platform/posix/split.rs:54:25
|
54 | return Some(TUN_PROTO_IP4);
| ^^^^^^^^^^^^^ not found in this scope
error[E0308]: mismatched types
--> src/platform/linux/device.rs:94:39
|
94 | req.ifr_ifru.ifru_flags = device_type
| _____________-----------------------___^
| | |
| | expected due to the type of this binding
95 | | | if packet_information { 0 } else { iff_no_pi }
96 | | | if queues_num > 1 { iff_multi_queue } else { 0 };
| |__________________________________________________________________^ expected `[i16; 2]`, found `i16`
error[E0609]: no field `ifru_newname` on type `__c_anonymous_ifr_ifru`
--> src/platform/linux/device.rs:227:30
|
227 | req.ifr_ifru.ifru_newname.as_mut_ptr(),
| ^^^^^^^^^^^^ unknown field
|
= note: available fields are: `ifru_addr`, `ifru_dstaddr`, `ifru_broadaddr`, `ifru_buffer`, `ifru_flags` ... and 10 others
error[E0368]: binary assignment operation `|=` cannot be applied to type `[i16; 2]`
--> src/platform/linux/device.rs:250:17
|
250 | req.ifr_ifru.ifru_flags |= (IFF_UP | IFF_RUNNING) as c_short;
| -----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| cannot use `|=` on type `[i16; 2]`
error[E0368]: binary assignment operation `&=` cannot be applied to type `[i16; 2]`
--> src/platform/linux/device.rs:252:17
|
252 | req.ifr_ifru.ifru_flags &= !(IFF_UP as c_short);
| -----------------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| cannot use `&=` on type `[i16; 2]`
error[E0609]: no field `ifru_netmask` on type `__c_anonymous_ifr_ifru`
--> src/platform/linux/device.rs:362:45
|
362 | SockAddr::new(&req.ifr_ifru.ifru_netmask).map(Into::into)?,
| ^^^^^^^^^^^^ unknown field
|
= note: available fields are: `ifru_addr`, `ifru_dstaddr`, `ifru_broadaddr`, `ifru_buffer`, `ifru_flags` ... and 10 others
error[E0609]: no field `ifru_netmask` on type `__c_anonymous_ifr_ifru`
--> src/platform/linux/device.rs:373:26
|
373 | req.ifr_ifru.ifru_netmask = SockAddr::from(value).into();
| ^^^^^^^^^^^^ unknown field
|
= note: available fields are: `ifru_addr`, `ifru_dstaddr`, `ifru_broadaddr`, `ifru_buffer`, `ifru_flags` ... and 10 others
Some errors have detailed explanations: E0308, E0368, E0425, E0432, E0609.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `tun2` (lib) due to 9 previous errors
I am a bit busy with the investigation, but I have some plans to execute.
For Freebsd
, certain places need to be adjusted. In https://github.com/ssrlive/rust-tun/blob/v2/src/platform/posix/split.rs#L35, we should add some support, then write the specialized modules for Freebsd
since it more or less has different APIs from Linux
. Out of I don't have a Freebsd
environment in hand, I couldn't implement it now.
@SajjadPourali I searched the imported names in libc
module that were reported as unresolved in your quote, I found that the libc
for FreeBSD
had at least IFF_UP
, IFF_NOARP
, and IFF_MULTI_QUEUE
, see https://docs.rs/libc/0.2.153/x86_64-unknown-freebsd/libc/index.html?search=IFF_MULTI_QUEUE.
Do you try to update the dependencies and test them?
@SajjadPourali @yurivict @M0dEx @ssrlive
This PR https://github.com/ssrlive/rust-tun/pull/51 prepares to fix this issue, which has made tun2
successfully compiled on FreeBSD. However, it cannot work due to Inappropriate ioctl for device
, I still didn't find any resolution here. So, some help is needed to complete the patch.
The generated ioctl
is by looking up https://github.com/lattera/freebsd/blob/master/sys/sys/sockio.h
Reference: https://github.com/osmocom/openggsn/blob/master/lib/tun.c
@xmh0511 I think in freebsd we should call SIOCAIFADDR
to set an ip address, but in the code SIOCSIFADDR
is used.
http://dostf.blogspot.com/2010/10/programmatic-interface-alias-creation.html
@xmh0511 I think in freebsd we should call
SIOCAIFADDR
to set an ip address, but in the codeSIOCSIFADDR
is used.http://dostf.blogspot.com/2010/10/programmatic-interface-alias-creation.html
I tried this scheme. However, it still cannot work
Error: Io(Os { code: 22, kind: InvalidInput, message: "Invalid argument" })
Seems a relevant issue https://wiki.strongswan.org/issues/566
The relevant resolution is http://fxr.watson.org/fxr/source/netinet/in_var.h?v=FREEBSD-13-STABLE;im=bigexc, and using SIOCAIFADDR
https://svnweb.freebsd.org/base/head/sbin/ifconfig/ifconfig.c?revision=281143&view=markup#l1012
Now, tun2
has been available on FreeBSD. This issue can be closed as completed. Feel free to open new issue if there is some issue when using tun2
on FreeBSD.
I found that the created tun interface remains in the resulting list of running the command ifconfig -a
after the program exits on FreeBSD. The relevant is https://stackoverflow.com/questions/25600708/how-to-use-siocifdestroy-in-freebsd. However, it seems not to cause problems in my test.
Any enhancement to this "issue" is appreciated.
Running:
Exit:
Based on the patch provided by @yurivict for 'tun', it appears that FreeBSD and Linux APIs are the same. We just need to add FreeBSD to the target lists in the platform module. For more information, refer to this link