diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b02f72..3ad1b61 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.55.0 + toolchain: 1.60.0 override: true components: rustfmt, clippy - name: Run rustfmt and fail if any warnings diff --git a/Cargo.toml b/Cargo.toml index 81c438d..ad56957 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ default = ["async", "logging"] [dependencies] flume = { version = "0.10", default-features = false } # channel between threads -if-addrs = "0.7" # get local IP addresses +if-addrs = "0.10" # get local IP addresses log = { version = "0.4.14", optional = true } # logging polling = "2.1" # select/poll sockets socket2 = { version = "0.4", features = ["all"] } # socket APIs diff --git a/README.md b/README.md index 2c0215f..38e7a4e 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Currently this library has the following limitations: ## Minimum Rust version -Tested against Rust 1.55.0 +Tested against Rust 1.60.0 ## License diff --git a/src/service_daemon.rs b/src/service_daemon.rs index ed90426..7464bbd 100644 --- a/src/service_daemon.rs +++ b/src/service_daemon.rs @@ -1672,20 +1672,36 @@ fn call_listener( /// Returns valid IPv4 interfaces in the host system. fn my_ipv4_interfaces() -> Vec { - if_addrs::get_if_addrs() + // Link local interfaces have the 169.254/16 prefix, + // see RFC 3927 for details. + let mut link_local_count = 0; + + let mut intf_vec: Vec = if_addrs::get_if_addrs() .unwrap_or_default() .into_iter() .filter_map(|i| { if i.is_loopback() { None } else { + if i.is_link_local() { + link_local_count += 1; + } match i.addr { IfAddr::V4(ifv4) => Some(ifv4), _ => None, } } }) - .collect() + .collect(); + + // If we have both routable interfaces and link-local interfaces, + // we only keep the routable interfaces. Otherwise, it can confuse + // the clients. + if link_local_count > 0 && intf_vec.len() > link_local_count { + intf_vec.retain(|i| !i.is_link_local()) + } + + intf_vec } /// Sends out `packet` to `addr` on the socket in `intf_sock`. diff --git a/tests/mdns_test.rs b/tests/mdns_test.rs index 3fb8431..d822d99 100644 --- a/tests/mdns_test.rs +++ b/tests/mdns_test.rs @@ -632,16 +632,22 @@ fn instance_name_two_dots() { } fn my_ipv4_interfaces() -> Vec { + let mut link_local_count = 0; + // Use a random port for binding test. let test_port = fastrand::u16(8000u16..9000u16); - if_addrs::get_if_addrs() + let mut intf_vec: Vec = if_addrs::get_if_addrs() .unwrap_or_default() .into_iter() .filter_map(|i| { if i.is_loopback() { None } else { + if i.is_link_local() { + link_local_count += 1; + } + match i.addr { IfAddr::V4(ifv4) => // Use a 'bind' to check if this is a valid IPv4 addr. @@ -658,7 +664,13 @@ fn my_ipv4_interfaces() -> Vec { } } }) - .collect() + .collect(); + + if link_local_count > 0 && intf_vec.len() > link_local_count { + intf_vec.retain(|i| !i.is_link_local()) + } + + intf_vec } /// Returns a made-up IPv4 address "net.1.1.1", where