meta: switch from ipnetwork to ipnet (#193)

pull/195/head
Jake McGinty 2022-02-01 14:01:21 +09:00 committed by GitHub
parent b6ce16bc00
commit a77cbb4f49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 116 additions and 77 deletions

13
Cargo.lock generated
View File

@ -137,7 +137,7 @@ dependencies = [
"dialoguer", "dialoguer",
"hostsfile", "hostsfile",
"indoc", "indoc",
"ipnetwork", "ipnet",
"lazy_static", "lazy_static",
"log", "log",
"regex", "regex",
@ -470,9 +470,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "ipnetwork" name = "ipnet"
version = "0.17.0" version = "2.3.1"
source = "git+https://github.com/mcginty/ipnetwork?rev=393f2d89e41ac6c1c0d80a31fc0997c387a7f7ba#393f2d89e41ac6c1c0d80a31fc0997c387a7f7ba" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -933,7 +934,7 @@ dependencies = [
"dialoguer", "dialoguer",
"hyper", "hyper",
"indoc", "indoc",
"ipnetwork", "ipnet",
"lazy_static", "lazy_static",
"libc", "libc",
"libsqlite3-sys", "libsqlite3-sys",
@ -966,7 +967,7 @@ dependencies = [
"colored", "colored",
"dialoguer", "dialoguer",
"indoc", "indoc",
"ipnetwork", "ipnet",
"lazy_static", "lazy_static",
"libc", "libc",
"log", "log",

View File

@ -21,7 +21,7 @@ clap_complete = "3"
dialoguer = { version = "0.9", default-features = false } dialoguer = { version = "0.9", default-features = false }
hostsfile = { path = "../hostsfile" } hostsfile = { path = "../hostsfile" }
indoc = "1" indoc = "1"
ipnetwork = { git = "https://github.com/mcginty/ipnetwork", rev = "393f2d89e41ac6c1c0d80a31fc0997c387a7f7ba" } ipnet = { version = "2", features = ["serde"] }
lazy_static = "1" lazy_static = "1"
log = "0.4" log = "0.4"
regex = { version = "1", default-features = false, features = ["std"] } regex = { version = "1", default-features = false, features = ["std"] }

View File

@ -24,7 +24,7 @@ colored = "2"
dialoguer = { version = "0.9", default-features = false } dialoguer = { version = "0.9", default-features = false }
hyper = { version = "0.14", default-features = false, features = ["http1", "server", "runtime", "stream"] } hyper = { version = "0.14", default-features = false, features = ["http1", "server", "runtime", "stream"] }
indoc = "1" indoc = "1"
ipnetwork = { git = "https://github.com/mcginty/ipnetwork", rev = "393f2d89e41ac6c1c0d80a31fc0997c387a7f7ba" } ipnet = { version = "2", features = ["serde"] }
lazy_static = "1" lazy_static = "1"
libc = "0.2" libc = "0.2"
libsqlite3-sys = "0.23" libsqlite3-sys = "0.23"

View File

@ -1,7 +1,7 @@
use crate::ServerError; use crate::ServerError;
use ipnetwork::IpNetwork; use ipnet::IpNet;
use rusqlite::{params, Connection}; use rusqlite::{params, Connection};
use shared::{Cidr, CidrContents}; use shared::{Cidr, CidrContents, IpNetExt};
use std::ops::Deref; use std::ops::Deref;
pub static CREATE_TABLE_SQL: &str = "CREATE TABLE cidrs ( pub static CREATE_TABLE_SQL: &str = "CREATE TABLE cidrs (
@ -56,8 +56,8 @@ impl DatabaseCidr {
let closest_parent = cidrs let closest_parent = cidrs
.iter() .iter()
.filter(|current| cidr.is_subnet_of(current.cidr)) .filter(|current| current.cidr.contains(cidr))
.max_by_key(|current| current.cidr.prefix()); .max_by_key(|current| current.cidr.prefix_len());
if let Some(closest_parent) = closest_parent { if let Some(closest_parent) = closest_parent {
if closest_parent.id != *parent_id { if closest_parent.id != *parent_id {
@ -70,7 +70,7 @@ impl DatabaseCidr {
} }
let parent_cidr = Self::get(conn, *parent_id)?.cidr; let parent_cidr = Self::get(conn, *parent_id)?.cidr;
if !parent_cidr.contains(cidr.network()) || !parent_cidr.contains(cidr.broadcast()) { if !parent_cidr.contains(&cidr.network()) || !parent_cidr.contains(&cidr.broadcast()) {
log::warn!("tried to add a CIDR with a network range outside of its parent."); log::warn!("tried to add a CIDR with a network range outside of its parent.");
return Err(ServerError::InvalidQuery); return Err(ServerError::InvalidQuery);
} }
@ -81,10 +81,10 @@ impl DatabaseCidr {
.filter(|current| current.parent == *parent) .filter(|current| current.parent == *parent)
.map(|sibling| sibling.cidr) .map(|sibling| sibling.cidr)
.any(|sibling| { .any(|sibling| {
cidr.contains(sibling.network()) cidr.contains(&sibling.network())
|| cidr.contains(sibling.broadcast()) || cidr.contains(&sibling.broadcast())
|| sibling.contains(cidr.network()) || sibling.contains(&cidr.network())
|| sibling.contains(cidr.broadcast()) || sibling.contains(&cidr.broadcast())
}); });
if overlapping_sibling { if overlapping_sibling {
@ -95,7 +95,12 @@ impl DatabaseCidr {
conn.execute( conn.execute(
"INSERT INTO cidrs (name, ip, prefix, parent) "INSERT INTO cidrs (name, ip, prefix, parent)
VALUES (?1, ?2, ?3, ?4)", VALUES (?1, ?2, ?3, ?4)",
params![name, cidr.ip().to_string(), cidr.prefix() as i32, parent], params![
name,
cidr.addr().to_string(),
cidr.prefix_len() as i32,
parent
],
)?; )?;
let id = conn.last_insert_rowid(); let id = conn.last_insert_rowid();
Ok(Cidr { id, contents }) Ok(Cidr { id, contents })
@ -109,14 +114,12 @@ impl DatabaseCidr {
fn from_row(row: &rusqlite::Row) -> Result<Cidr, rusqlite::Error> { fn from_row(row: &rusqlite::Row) -> Result<Cidr, rusqlite::Error> {
let id = row.get(0)?; let id = row.get(0)?;
let name = row.get(1)?; let name = row.get(1)?;
let ip: String = row.get(2)?; let ip_str: String = row.get(2)?;
let prefix = row.get(3)?; let prefix = row.get(3)?;
let cidr = IpNetwork::new( let ip = ip_str
ip.parse() .parse()
.map_err(|_| rusqlite::Error::ExecuteReturnedResults)?,
prefix,
)
.map_err(|_| rusqlite::Error::ExecuteReturnedResults)?; .map_err(|_| rusqlite::Error::ExecuteReturnedResults)?;
let cidr = IpNet::new(ip, prefix).map_err(|_| rusqlite::Error::ExecuteReturnedResults)?;
let parent = row.get(4)?; let parent = row.get(4)?;
Ok(Cidr { Ok(Cidr {
id, id,

View File

@ -3,7 +3,7 @@ use crate::ServerError;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use rusqlite::{params, types::Type, Connection}; use rusqlite::{params, types::Type, Connection};
use shared::{Peer, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS}; use shared::{IpNetExt, Peer, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS};
use std::{ use std::{
net::IpAddr, net::IpAddr,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
@ -96,12 +96,12 @@ impl DatabasePeer {
} }
let cidr = DatabaseCidr::get(conn, *cidr_id)?; let cidr = DatabaseCidr::get(conn, *cidr_id)?;
if !cidr.cidr.contains(*ip) { if !cidr.cidr.contains(ip) {
log::warn!("tried to add peer with IP outside of parent CIDR range."); log::warn!("tried to add peer with IP outside of parent CIDR range.");
return Err(ServerError::InvalidQuery); return Err(ServerError::InvalidQuery);
} }
if !cidr.cidr.is_assignable(*ip) { if !cidr.cidr.is_assignable(ip) {
println!( println!(
"Peer IP {} is not unicast assignable in CIDR {}", "Peer IP {} is not unicast assignable in CIDR {}",
ip, cidr.cidr ip, cidr.cidr

View File

@ -4,9 +4,12 @@ use clap::Parser;
use db::DatabaseCidr; use db::DatabaseCidr;
use dialoguer::{theme::ColorfulTheme, Input}; use dialoguer::{theme::ColorfulTheme, Input};
use indoc::printdoc; use indoc::printdoc;
use ipnet::IpNet;
use publicip::Preference; use publicip::Preference;
use rusqlite::{params, Connection}; use rusqlite::{params, Connection};
use shared::{prompts, CidrContents, Endpoint, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS}; use shared::{
prompts, CidrContents, Endpoint, IpNetExt, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
};
use wireguard_control::KeyPair; use wireguard_control::KeyPair;
fn create_database<P: AsRef<Path>>( fn create_database<P: AsRef<Path>>(
@ -31,7 +34,7 @@ pub struct InitializeOpts {
/// The network CIDR (ex: 10.42.0.0/16) /// The network CIDR (ex: 10.42.0.0/16)
#[clap(long)] #[clap(long)]
pub network_cidr: Option<IpNetwork>, pub network_cidr: Option<IpNet>,
/// This server's external endpoint (ex: 100.100.100.100:51820) /// This server's external endpoint (ex: 100.100.100.100:51820)
#[clap(long, conflicts_with = "auto-external-endpoint")] #[clap(long, conflicts_with = "auto-external-endpoint")]
@ -48,8 +51,8 @@ pub struct InitializeOpts {
struct DbInitData { struct DbInitData {
network_name: String, network_name: String,
network_cidr: IpNetwork, network_cidr: IpNet,
server_cidr: IpNetwork, server_cidr: IpNet,
our_ip: IpAddr, our_ip: IpAddr,
public_key_base64: String, public_key_base64: String,
endpoint: Endpoint, endpoint: Endpoint,
@ -131,7 +134,7 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
.interact()? .interact()?
}; };
let root_cidr: IpNetwork = if let Some(cidr) = opts.network_cidr { let root_cidr: IpNet = if let Some(cidr) = opts.network_cidr {
cidr cidr
} else { } else {
Input::with_theme(&theme) Input::with_theme(&theme)
@ -163,10 +166,9 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
}; };
let our_ip = root_cidr let our_ip = root_cidr
.iter() .hosts()
.find(|ip| root_cidr.is_assignable(*ip)) .find(|ip| root_cidr.is_assignable(ip))
.unwrap(); .unwrap();
let server_cidr = IpNetwork::new(our_ip, root_cidr.max_prefix())?;
let config_path = conf.config_path(&name); let config_path = conf.config_path(&name);
let our_keypair = KeyPair::generate(); let our_keypair = KeyPair::generate();
@ -174,14 +176,14 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
private_key: our_keypair.private.to_base64(), private_key: our_keypair.private.to_base64(),
listen_port, listen_port,
address: our_ip, address: our_ip,
network_cidr_prefix: root_cidr.prefix(), network_cidr_prefix: root_cidr.prefix_len(),
}; };
config.write_to_path(&config_path)?; config.write_to_path(&config_path)?;
let db_init_data = DbInitData { let db_init_data = DbInitData {
network_name: name.to_string(), network_name: name.to_string(),
network_cidr: root_cidr, network_cidr: root_cidr,
server_cidr, server_cidr: IpNet::new(our_ip, root_cidr.max_prefix_len())?,
our_ip, our_ip,
public_key_base64: our_keypair.public.to_base64(), public_key_base64: our_keypair.public.to_base64(),
endpoint, endpoint,

View File

@ -4,12 +4,12 @@ use colored::*;
use dialoguer::Confirm; use dialoguer::Confirm;
use hyper::{http, server::conn::AddrStream, Body, Request, Response}; use hyper::{http, server::conn::AddrStream, Body, Request, Response};
use indoc::printdoc; use indoc::printdoc;
use ipnetwork::IpNetwork; use ipnet::IpNet;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use rusqlite::Connection; use rusqlite::Connection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use shared::{ use shared::{
get_local_addrs, AddCidrOpts, AddPeerOpts, DeleteCidrOpts, Endpoint, IoErrorContext, get_local_addrs, AddCidrOpts, AddPeerOpts, DeleteCidrOpts, Endpoint, IoErrorContext, IpNetExt,
NetworkOpts, PeerContents, RenamePeerOpts, INNERNET_PUBKEY_HEADER, NetworkOpts, PeerContents, RenamePeerOpts, INNERNET_PUBKEY_HEADER,
}; };
use std::{ use std::{
@ -502,7 +502,7 @@ async fn serve(
wg::up( wg::up(
&interface, &interface,
&config.private_key, &config.private_key,
IpNetwork::new(config.address, config.network_cidr_prefix)?, IpNet::new(config.address, config.network_cidr_prefix)?,
Some(config.listen_port), Some(config.listen_port),
None, None,
network, network,

View File

@ -13,7 +13,7 @@ clap = { version = "3", features = ["derive"] }
colored = "2.0" colored = "2.0"
dialoguer = { version = "0.9", default-features = false } dialoguer = { version = "0.9", default-features = false }
indoc = "1" indoc = "1"
ipnetwork = { git = "https://github.com/mcginty/ipnetwork", rev ="393f2d89e41ac6c1c0d80a31fc0997c387a7f7ba" } ipnet = { version = "2", features = ["serde"] }
lazy_static = "1" lazy_static = "1"
libc = "0.2" libc = "0.2"
log = "0.4" log = "0.4"

View File

@ -1,6 +1,6 @@
use crate::{chmod, ensure_dirs_exist, Endpoint, Error, IoErrorContext, WrappedIoError}; use crate::{chmod, ensure_dirs_exist, Endpoint, Error, IoErrorContext, WrappedIoError};
use indoc::writedoc; use indoc::writedoc;
use ipnetwork::IpNetwork; use ipnet::IpNet;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
fs::{File, OpenOptions}, fs::{File, OpenOptions},
@ -28,7 +28,7 @@ pub struct InterfaceInfo {
/// The invited peer's internal IP address that's been allocated to it, inside /// The invited peer's internal IP address that's been allocated to it, inside
/// the entire network's CIDR prefix. /// the entire network's CIDR prefix.
pub address: IpNetwork, pub address: IpNet,
/// WireGuard private key (base64) /// WireGuard private key (base64)
pub private_key: String, pub private_key: String,

View File

@ -1,4 +1,5 @@
pub use anyhow::Error; pub use anyhow::Error;
use ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError};
use std::{ use std::{
fs::{self, File, Permissions}, fs::{self, File, Permissions},
io, io,
@ -116,3 +117,29 @@ pub fn get_local_addrs() -> Result<impl Iterator<Item = std::net::IpAddr>, io::E
}) })
.take(10)) .take(10))
} }
pub trait IpNetExt {
fn is_assignable(&self, ip: &IpAddr) -> bool;
#[allow(clippy::new_ret_no_self)]
fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError>;
}
impl IpNetExt for IpNet {
fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError> {
Ok(match ip {
IpAddr::V4(a) => Ipv4Net::new(a, prefix_len)?.into(),
IpAddr::V6(a) => Ipv6Net::new(a, prefix_len)?.into(),
})
}
fn is_assignable(&self, ip: &IpAddr) -> bool {
self.contains(ip)
&& match self {
IpNet::V4(_) => {
self.prefix_len() >= 31 || (ip != &self.network() && ip != &self.broadcast())
},
IpNet::V6(_) => self.prefix_len() >= 127 || ip != &self.network(),
}
}
}

View File

@ -1,4 +1,4 @@
use ipnetwork::IpNetwork; use ipnet::IpNet;
use netlink_packet_core::{NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_CREATE, NLM_F_REQUEST}; use netlink_packet_core::{NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_CREATE, NLM_F_REQUEST};
use netlink_packet_route::{ use netlink_packet_route::{
address, address,
@ -36,11 +36,11 @@ pub fn set_up(interface: &InterfaceName, mtu: u32) -> Result<(), io::Error> {
Ok(()) Ok(())
} }
pub fn set_addr(interface: &InterfaceName, addr: IpNetwork) -> Result<(), io::Error> { pub fn set_addr(interface: &InterfaceName, addr: IpNet) -> Result<(), io::Error> {
let index = if_nametoindex(interface)?; let index = if_nametoindex(interface)?;
let (family, nlas) = match addr { let (family, nlas) = match addr {
IpNetwork::V4(network) => { IpNet::V4(network) => {
let addr_bytes = network.ip().octets().to_vec(); let addr_bytes = network.addr().octets().to_vec();
( (
AF_INET as u8, AF_INET as u8,
vec![ vec![
@ -49,16 +49,16 @@ pub fn set_addr(interface: &InterfaceName, addr: IpNetwork) -> Result<(), io::Er
], ],
) )
}, },
IpNetwork::V6(network) => ( IpNet::V6(network) => (
AF_INET6 as u8, AF_INET6 as u8,
vec![address::Nla::Address(network.ip().octets().to_vec())], vec![address::Nla::Address(network.addr().octets().to_vec())],
), ),
}; };
let message = AddressMessage { let message = AddressMessage {
header: AddressHeader { header: AddressHeader {
index, index,
family, family,
prefix_len: addr.prefix(), prefix_len: addr.prefix_len(),
scope: RT_SCOPE_UNIVERSE, scope: RT_SCOPE_UNIVERSE,
..Default::default() ..Default::default()
}, },
@ -72,11 +72,11 @@ pub fn set_addr(interface: &InterfaceName, addr: IpNetwork) -> Result<(), io::Er
Ok(()) Ok(())
} }
pub fn add_route(interface: &InterfaceName, cidr: IpNetwork) -> Result<bool, io::Error> { pub fn add_route(interface: &InterfaceName, cidr: IpNet) -> Result<bool, io::Error> {
let if_index = if_nametoindex(interface)?; let if_index = if_nametoindex(interface)?;
let (address_family, dst) = match cidr { let (address_family, dst) = match cidr {
IpNetwork::V4(network) => (AF_INET as u8, network.network().octets().to_vec()), IpNet::V4(network) => (AF_INET as u8, network.network().octets().to_vec()),
IpNetwork::V6(network) => (AF_INET6 as u8, network.network().octets().to_vec()), IpNet::V6(network) => (AF_INET6 as u8, network.network().octets().to_vec()),
}; };
let message = RouteMessage { let message = RouteMessage {
header: RouteHeader { header: RouteHeader {
@ -84,7 +84,7 @@ pub fn add_route(interface: &InterfaceName, cidr: IpNetwork) -> Result<bool, io:
protocol: RTPROT_BOOT, protocol: RTPROT_BOOT,
scope: RT_SCOPE_LINK, scope: RT_SCOPE_LINK,
kind: RTN_UNICAST, kind: RTN_UNICAST,
destination_prefix_length: cidr.prefix(), destination_prefix_length: cidr.prefix_len(),
address_family, address_family,
..Default::default() ..Default::default()
}, },

View File

@ -1,13 +1,13 @@
use crate::{ use crate::{
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo}, interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree,
DeleteCidrOpts, Endpoint, Error, Hostname, ListenPortOpts, OverrideEndpointOpts, Peer, DeleteCidrOpts, Endpoint, Error, Hostname, IpNetExt, ListenPortOpts, OverrideEndpointOpts,
PeerContents, RenamePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS, Peer, PeerContents, RenamePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
}; };
use anyhow::anyhow; use anyhow::anyhow;
use colored::*; use colored::*;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select}; use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
use ipnetwork::IpNetwork; use ipnet::IpNet;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use publicip::Preference; use publicip::Preference;
use std::{ use std::{
@ -267,7 +267,7 @@ pub fn add_peer(
}; };
let mut available_ip = None; let mut available_ip = None;
let candidate_ips = cidr.iter().filter(|ip| cidr.is_assignable(*ip)); let candidate_ips = cidr.hosts().filter(|ip| cidr.is_assignable(ip));
for ip in candidate_ips { for ip in candidate_ips {
if !peers.iter().any(|peer| peer.ip == ip) { if !peers.iter().any(|peer| peer.ip == ip) {
available_ip = Some(ip); available_ip = Some(ip);
@ -439,7 +439,7 @@ pub fn write_peer_invitation(
interface: InterfaceInfo { interface: InterfaceInfo {
network_name: network_name.to_string(), network_name: network_name.to_string(),
private_key: keypair.private.to_base64(), private_key: keypair.private.to_base64(),
address: IpNetwork::new(peer.ip, root_cidr.prefix())?, address: IpNet::new(peer.ip, root_cidr.prefix_len())?,
listen_port: None, listen_port: None,
}, },
server: ServerInfo { server: ServerInfo {

View File

@ -1,6 +1,6 @@
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use clap::Args; use clap::Args;
use ipnetwork::IpNetwork; use ipnet::IpNet;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -195,12 +195,12 @@ impl Deref for Association {
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Eq, Ord)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Eq, Ord)]
pub struct CidrContents { pub struct CidrContents {
pub name: String, pub name: String,
pub cidr: IpNetwork, pub cidr: IpNet,
pub parent: Option<i64>, pub parent: Option<i64>,
} }
impl Deref for CidrContents { impl Deref for CidrContents {
type Target = IpNetwork; type Target = IpNet;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.cidr &self.cidr
@ -247,7 +247,7 @@ impl<'a> CidrTree<'a> {
pub fn new(cidrs: &'a [Cidr]) -> Self { pub fn new(cidrs: &'a [Cidr]) -> Self {
let root = cidrs let root = cidrs
.iter() .iter()
.min_by_key(|c| c.cidr.prefix()) .min_by_key(|c| c.cidr.prefix_len())
.expect("failed to find root CIDR"); .expect("failed to find root CIDR");
Self::with_root(cidrs, root) Self::with_root(cidrs, root)
} }
@ -356,7 +356,7 @@ pub struct AddCidrOpts {
/// The CIDR network (eg. '10.42.5.0/24') /// The CIDR network (eg. '10.42.5.0/24')
#[clap(long)] #[clap(long)]
pub cidr: Option<IpNetwork>, pub cidr: Option<IpNet>,
/// The CIDR parent name /// The CIDR parent name
#[clap(long)] #[clap(long)]
@ -431,7 +431,7 @@ pub struct NatOpts {
#[clap(long)] #[clap(long)]
/// Exclude one or more CIDRs from NAT candidate reporting. /// Exclude one or more CIDRs from NAT candidate reporting.
/// ex. --exclude-nat-candidates '0.0.0.0/0' would report no candidates. /// ex. --exclude-nat-candidates '0.0.0.0/0' would report no candidates.
pub exclude_nat_candidates: Vec<IpNetwork>, pub exclude_nat_candidates: Vec<IpNet>,
#[clap(long, conflicts_with = "exclude-nat-candidates")] #[clap(long, conflicts_with = "exclude-nat-candidates")]
/// Don't report any candidates to coordinating server. /// Don't report any candidates to coordinating server.
@ -454,7 +454,7 @@ impl NatOpts {
|| self || self
.exclude_nat_candidates .exclude_nat_candidates
.iter() .iter()
.any(|network| network.contains(ip)) .any(|network| network.contains(&ip))
} }
} }

View File

@ -1,5 +1,5 @@
use crate::{Error, IoErrorContext, NetworkOpts, Peer, PeerDiff}; use crate::{Error, IoErrorContext, NetworkOpts, Peer, PeerDiff};
use ipnetwork::IpNetwork; use ipnet::IpNet;
use std::{ use std::{
io, io,
net::{IpAddr, SocketAddr}, net::{IpAddr, SocketAddr},
@ -32,17 +32,17 @@ fn cmd(bin: &str, args: &[&str]) -> Result<std::process::Output, io::Error> {
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn set_addr(interface: &InterfaceName, addr: IpNetwork) -> Result<(), io::Error> { pub fn set_addr(interface: &InterfaceName, addr: IpNet) -> Result<(), io::Error> {
let real_interface = wireguard_control::backends::userspace::resolve_tun(interface)?; let real_interface = wireguard_control::backends::userspace::resolve_tun(interface)?;
if addr.is_ipv4() { if matches!(addr, IpNet::V4(_)) {
cmd( cmd(
"ifconfig", "ifconfig",
&[ &[
&real_interface, &real_interface,
"inet", "inet",
&addr.to_string(), &addr.to_string(),
&addr.ip().to_string(), &addr.addr().to_string(),
"alias", "alias",
], ],
) )
@ -72,7 +72,7 @@ pub use super::netlink::set_up;
pub fn up( pub fn up(
interface: &InterfaceName, interface: &InterfaceName,
private_key: &str, private_key: &str,
address: IpNetwork, address: IpNet,
listen_port: Option<u16>, listen_port: Option<u16>,
peer: Option<(&str, IpAddr, SocketAddr)>, peer: Option<(&str, IpAddr, SocketAddr)>,
network: NetworkOpts, network: NetworkOpts,
@ -102,9 +102,11 @@ pub fn up(
set_addr(interface, address)?; set_addr(interface, address)?;
set_up( set_up(
interface, interface,
network network.mtu.unwrap_or(if matches!(address, IpNet::V4(_)) {
.mtu 1420
.unwrap_or_else(|| if address.is_ipv4() { 1420 } else { 1400 }), } else {
1400
}),
)?; )?;
if !network.no_routing { if !network.no_routing {
add_route(interface, address)?; add_route(interface, address)?;
@ -139,14 +141,18 @@ pub fn down(interface: &InterfaceName, backend: Backend) -> Result<(), Error> {
/// Returns an error if the process doesn't exit successfully, otherwise returns /// Returns an error if the process doesn't exit successfully, otherwise returns
/// true if the route was changed, false if the route already exists. /// true if the route was changed, false if the route already exists.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn add_route(interface: &InterfaceName, cidr: IpNetwork) -> Result<bool, io::Error> { pub fn add_route(interface: &InterfaceName, cidr: IpNet) -> Result<bool, io::Error> {
let real_interface = wireguard_control::backends::userspace::resolve_tun(interface)?; let real_interface = wireguard_control::backends::userspace::resolve_tun(interface)?;
let output = cmd( let output = cmd(
"route", "route",
&[ &[
"-n", "-n",
"add", "add",
if cidr.is_ipv4() { "-inet" } else { "-inet6" }, if matches!(cidr, IpNet::V4(_)) {
"-inet"
} else {
"-inet6"
},
&cidr.to_string(), &cidr.to_string(),
"-interface", "-interface",
&real_interface, &real_interface,