|
1 | 1 | use super::TunConfig;
|
2 |
| -#[cfg(target_os = "macos")] |
3 |
| -use std::io; |
4 | 2 | use std::{
|
5 | 3 | net::IpAddr,
|
6 | 4 | ops::Deref,
|
7 | 5 | os::unix::io::{AsRawFd, RawFd},
|
| 6 | + process::Command, |
8 | 7 | };
|
9 | 8 | use tun::{AbstractDevice, Configuration};
|
10 | 9 |
|
11 | 10 | /// Errors that can occur while setting up a tunnel device.
|
12 | 11 | #[derive(Debug, thiserror::Error)]
|
13 | 12 | pub enum Error {
|
14 |
| - /// Failed to set IP address on tunnel device |
15 |
| - #[cfg(target_os = "linux")] |
16 |
| - #[error("Failed to set IP address on tunnel device")] |
17 |
| - SetIp(#[source] tun::Error), |
18 |
| - |
19 | 13 | /// Failed to set IPv4 address on tunnel device
|
20 |
| - #[cfg(target_os = "macos")] |
21 | 14 | #[error("Failed to set IPv4 address")]
|
22 | 15 | SetIpv4(#[source] tun::Error),
|
23 | 16 |
|
24 | 17 | /// Failed to set IPv6 address on tunnel device
|
25 |
| - #[cfg(target_os = "macos")] |
26 | 18 | #[error("Failed to set IPv6 address")]
|
27 |
| - SetIpv6(#[source] io::Error), |
| 19 | + SetIpv6(#[source] std::io::Error), |
28 | 20 |
|
29 | 21 | /// Unable to open a tunnel device
|
30 | 22 | #[error("Unable to open a tunnel device")]
|
@@ -148,29 +140,37 @@ impl AsRawFd for TunnelDevice {
|
148 | 140 | }
|
149 | 141 |
|
150 | 142 | impl TunnelDevice {
|
151 |
| - #[cfg(target_os = "linux")] |
152 |
| - fn set_ip(&mut self, ip: IpAddr) -> Result<(), Error> { |
153 |
| - self.dev.set_address(ip).map_err(Error::SetIp)?; |
154 |
| - Ok(()) |
155 |
| - } |
156 |
| - |
157 |
| - #[cfg(target_os = "macos")] |
158 | 143 | fn set_ip(&mut self, ip: IpAddr) -> Result<(), Error> {
|
159 | 144 | match ip {
|
160 |
| - // NOTE: As of `tun 0.7`, `Device::set_address` accepts an `IpAddr` but |
161 |
| - // only supports the `IpAddr::V4` address kind and panics if you pass it an |
162 |
| - // `IpAddr::V6` value.. |
163 | 145 | IpAddr::V4(ipv4) => {
|
164 | 146 | self.dev.set_address(ipv4.into()).map_err(Error::SetIpv4)?;
|
165 | 147 | }
|
| 148 | + |
| 149 | + // NOTE: On MacOs, As of `tun 0.7`, `Device::set_address` accepts an `IpAddr` but |
| 150 | + // only supports the `IpAddr::V4` address kind and panics if you pass it an |
| 151 | + // `IpAddr::V6` value. |
| 152 | + #[cfg(target_os = "macos")] |
166 | 153 | IpAddr::V6(ipv6) => {
|
167 |
| - use std::process::Command; |
168 | 154 | // ifconfig <device> inet6 <ipv6 address> alias
|
169 |
| - let address = ipv6.to_string(); |
| 155 | + let ipv6 = ipv6.to_string(); |
| 156 | + let device = self.dev.tun_name().unwrap(); // TODO: Do not unwrap! |
| 157 | + Command::new("ifconfig") |
| 158 | + .args([&device, "inet6", &ipv6, "alias"]) |
| 159 | + .output() |
| 160 | + .map_err(Error::SetIpv6)?; |
| 161 | + } |
| 162 | + |
| 163 | + // NOTE: On Linux, As of `tun 0.7`, `Device::set_address` throws an I/O error if you |
| 164 | + // pass it an IPv6-address. |
| 165 | + #[cfg(target_os = "linux")] |
| 166 | + IpAddr::V6(ipv6) => { |
| 167 | + // ip -6 addr add <ipv6 address> dev <device> |
| 168 | + let ipv6 = ipv6.to_string(); |
170 | 169 | let device = self.dev.tun_name().unwrap(); // TODO: Do not unwrap!
|
171 |
| - let mut ifconfig = Command::new("ifconfig"); |
172 |
| - ifconfig.args([&device, "inet6", &address, "alias"]); |
173 |
| - ifconfig.output().map_err(Error::SetIpv6)?; |
| 170 | + Command::new("ip") |
| 171 | + .args(["-6", "addr", "add", &ipv6, "dev", &device]) |
| 172 | + .output() |
| 173 | + .map_err(Error::SetIpv6)?; |
174 | 174 | }
|
175 | 175 | }
|
176 | 176 | Ok(())
|
|
0 commit comments