johnyburd / net-route

Rust crate providing a cross platform interface for interacting with the routing table
https://docs.rs/net-route/
21 stars 14 forks source link

The `Handle::add` returns an error on macOs when setting the route to `0.0.0.0/0` #15

Open xmh0511 opened 10 months ago

xmh0511 commented 10 months ago

The way of setting routes to make all traffic reach the specified tun interface is suggested to be:

 let if_name = CString::new("utun6")?;
let tun_ifindex = unsafe{
    libc::if_nametoindex(if_name.as_ptr())
};
let handle = Handle::new()?;
let route = Route::new("0.0.0.0".parse().unwrap(), 0).with_ifindex(tun_ifindex);
handle.add(&route).await  // #1

However, #1 just returns an error Err(Custom { kind: AlreadyExists, error: "rtm_errno 17" }). If set the routing with Route::new("20.0.0.0".parse().unwrap(), 24).with_ifindex(tun_ifindex); then it's OK.

In both case, there is a panic at

.cargo/registry/src/index.crates.io-6f17d22bba15001f/net-route-0.2.11/src/platform_impl/macos/macos.rs:254:25:
index out of bounds: the len is 12 but the index is 12
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
gelstudios commented 10 months ago

If you call Route::new() with the same arguments two times, do you get the same "rm_errno 17" ?

Route::new("20.0.0.0".parse().unwrap(), 24).with_ifindex(tun_ifindex); Route::new("20.0.0.0".parse().unwrap(), 24).with_ifindex(tun_ifindex);

xmh0511 commented 10 months ago

routing.tar.gz

This is the minimal reproduce project.

The table routing is:

test@192 ~ % netstat -rn
Routing tables

Internet:
Destination        Gateway            Flags           Netif Expire
default            192.168.2.1        UGScg             en0       
10.0.0.1           10.0.0.9           UH              utun6       
10.147.17/24       link#9             UC           feth1532      !
127                127.0.0.1          UCS               lo0       
127.0.0.1          127.0.0.1          UH                lo0       
169.254            link#5             UCS               en0      !
192.168.2          link#5             UCS               en0      !
192.168.2.1/32     link#5             UCS               en0      !
192.168.2.1        2c:a0:42:b9:39:72  UHLWIir           en0   1191
192.168.2.21/32    link#5             UCS               en0      !
224.0.0/4          link#5             UmCS              en0      !
224.0.0.251        1:0:5e:0:0:fb      UHmLWI            en0       
239.255.255.250    1:0:5e:7f:ff:fa    UHmLWI            en0       
255.255.255.255/32 link#5             UCS               en0      !

Internet6:
Destination                             Gateway                         Flags           Netif Expire
default                                 fe80::2ea0:42ff:feb9:3972%en0   UGcg              en0       
default                                 fe80::%utun0                    UGcIg           utun0       
default                                 fe80::%utun1                    UGcIg           utun1       
default                                 fe80::%utun2                    UGcIg           utun2       
::1                                     ::1                             UHL               lo0       
2409:8a20:a893:2011::/64                link#5                          UC                en0       
2409:8a20:a893:2011:10df:97e7:e8bc:85f2 a4:5e:60:be:a5:63               UHL               lo0       
2409:8a20:a893:2011:2ca0:42b9:3972:2    a4:5e:60:be:a5:63               UHL               lo0       
2409:8a20:a893:2011:aca2:6a28:c831:a35b a4:5e:60:be:a5:63               UHL               lo0       
fe80::%lo0/64                           fe80::1%lo0                     UcI               lo0       
fe80::1%lo0                             link#1                          UHLI              lo0       
fe80::%en0/64                           link#5                          UCI               en0       
fe80::4b5:39fc:c7c8:8592%en0            a4:5e:60:be:a5:63               UHLI              lo0       
fe80::2ea0:42ff:feb9:3972%en0           2c:a0:42:b9:39:72               UHLWIir           en0       
fe80::%awdl0/64                         link#12                         UCI             awdl0       
fe80::841f:85ff:fe51:e29e%awdl0         86:1f:85:51:e2:9e               UHLI              lo0       
fe80::%llw0/64                          link#13                         UCI              llw0       
fe80::841f:85ff:fe51:e29e%llw0          86:1f:85:51:e2:9e               UHLI              lo0       
fe80::%utun0/64                         fe80::105c:fc07:b5d1:c4%utun0   UcI             utun0       
fe80::105c:fc07:b5d1:c4%utun0           link#14                         UHLI              lo0       
fe80::%utun1/64                         fe80::6b1b:8cc1:643e:79e9%utun1 UcI             utun1       
fe80::6b1b:8cc1:643e:79e9%utun1         link#15                         UHLI              lo0       
fe80::%utun2/64                         fe80::ce81:b1c:bd2c:69e%utun2   UcI             utun2       
fe80::ce81:b1c:bd2c:69e%utun2           link#16                         UHLI              lo0       
ff00::/8                                ::1                             UmCI              lo0       
ff00::/8                                link#5                          UmCI              en0       
ff00::/8                                link#12                         UmCI            awdl0       
ff00::/8                                link#13                         UmCI             llw0       
ff00::/8                                fe80::105c:fc07:b5d1:c4%utun0   UmCI            utun0       
ff00::/8                                fe80::6b1b:8cc1:643e:79e9%utun1 UmCI            utun1       
ff00::/8                                fe80::ce81:b1c:bd2c:69e%utun2   UmCI            utun2       
ff01::%lo0/32                           ::1                             UmCI              lo0       
ff01::%en0/32                           link#5                          UmCI              en0       
ff01::%awdl0/32                         link#12                         UmCI            awdl0       
ff01::%llw0/32                          link#13                         UmCI             llw0       
ff01::%utun0/32                         fe80::105c:fc07:b5d1:c4%utun0   UmCI            utun0       
ff01::%utun1/32                         fe80::6b1b:8cc1:643e:79e9%utun1 UmCI            utun1       
ff01::%utun2/32                         fe80::ce81:b1c:bd2c:69e%utun2   UmCI            utun2       
ff02::%lo0/32                           ::1                             UmCI              lo0       
ff02::%en0/32                           link#5                          UmCI              en0       
ff02::%awdl0/32                         link#12                         UmCI            awdl0       
ff02::%llw0/32                          link#13                         UmCI             llw0       
ff02::%utun0/32                         fe80::105c:fc07:b5d1:c4%utun0   UmCI            utun0       
ff02::%utun1/32                         fe80::6b1b:8cc1:643e:79e9%utun1 UmCI            utun1       
ff02::%utun2/32                         fe80::ce81:b1c:bd2c:69e%utun2   UmCI            utun2 

If you call Route::new() with the same arguments two times, do you get the same "rm_errno 17" ?

just with a single let route = Route::new("0.0.0.0".parse().unwrap(), 0).with_ifindex(tun_ifindex);, the similar error can still exist:

[src/main.rs:76] tun_ifindex = 17
Err(Custom { kind: AlreadyExists, error: "rtm_errno 17" })
thread 'tokio-runtime-worker' panicked at /Users/test/.cargo/registry/src/index.crates.io-6f17d22bba15001f/net-route-0.2.11/src/platform_impl/macos/macos.rs:254:25:
index out of bounds: the len is 12 but the index is 12
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

This is the error when setting Route::new("20.0.0.0".parse().unwrap(), 24).with_ifindex(tun_ifindex); twice, the error will be prompted after approximately 5s, however, there is no rtm_errno 17 error.

[src/main.rs:76] tun_ifindex = 17
Ok(())
thread 'tokio-runtime-worker' panicked at /Users/test/.cargo/registry/src/index.crates.io-6f17d22bba15001f/net-route-0.2.11/src/platform_impl/macos/macos.rs:254:25:
index out of bounds: the len is 12 but the index is 12
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
johnyburd commented 8 months ago

can you check if this is fixed in 0.3.0

xmh0511 commented 8 months ago

I test the program with 0.3.0, and the first running will throw an error:

Err(Os { code: 17, kind: AlreadyExists, message: "File exists" })

Re-run the example is ok but terminating the program will never revert the original routing table even though I have deleted the routing by let r = handle.lock().await.delete(&route).await; before exiting main. This issue causes all my network access to be a failure, and I have to restart my system to revert the routing table.

BTW, there isn't the above error if I just set normal routing, for example, let route = Route::new("20.0.0.1".parse().unwrap(), 24).with_ifindex(tun_ifindex);.

johnyburd commented 8 months ago

What you're describing sounds like it may be expected behavior on macos. Do you already have a default route when you're trying to install another one? What if you try 0.0.0.0/1 and 128.0.0.0/1?

I can take a closer look if you upload a minimum reproduction I can test on my machine.

xmh0511 commented 8 months ago

What you're describing sounds like it may be expected behavior on macos. Do you already have a default route when you're trying to install another one? What if you try 0.0.0.0/1 and 128.0.0.0/1?

I can take a closer look if you upload a minimum reproduction I can test on my machine.

The minimum reproduction is here https://github.com/johnyburd/net-route/issues/15#issuecomment-1890300339, just update the dependency to 0.3.0

xmh0511 commented 8 months ago

Change the route setting to 0.0.0.0/1, then everything is right. There is no initial error as above and deleting routing when exiting the program works for me. The route setting 0.0.0.0/0, as written in https://github.com/johnyburd/net-route/issues/8#issuecomment-1886329528, has the problem.

I don't know why 0.0.0.0/1 is ok while 0.0.0.0/0 will have the issue. What's the difference here?