diff --git a/Cargo.lock b/Cargo.lock index 7bfb2b4..28932f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,17 +105,58 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", - "textwrap", + "strsim 0.8.0", + "textwrap 0.11.0", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1957aa4a5fb388f0a0a73ce7556c5b42025b874e5cdc2c670775e346e97adec0" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap 0.14.2", +] + +[[package]] +name = "clap_complete" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a394f7ec0715b42a4e52b294984c27c9a61f77c8d82f7774c5198350be143f19" +dependencies = [ + "clap 3.0.6", +] + +[[package]] +name = "clap_derive" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "client" version = "1.5.2" dependencies = [ "anyhow", + "clap 3.0.6", + "clap_complete", "colored", "dialoguer", "hostsfile", @@ -127,7 +168,6 @@ dependencies = [ "serde", "serde_json", "shared", - "structopt", "tempfile", "ureq", "wireguard-control", @@ -319,6 +359,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -415,6 +461,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "indoc" version = "1.0.3" @@ -660,6 +716,15 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -922,11 +987,14 @@ version = "1.5.2" dependencies = [ "anyhow", "bytes", + "clap 3.0.6", + "clap_complete", "colored", "dialoguer", "hyper", "indoc", "ipnetwork", + "lazy_static", "libc", "libsqlite3-sys", "log", @@ -939,7 +1007,6 @@ dependencies = [ "serde_json", "shared", "socket2", - "structopt", "subtle", "tempfile", "thiserror", @@ -955,6 +1022,7 @@ version = "1.5.2" dependencies = [ "anyhow", "atty", + "clap 3.0.6", "colored", "dialoguer", "indoc", @@ -998,13 +1066,19 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ - "clap", + "clap 2.34.0", "lazy_static", "structopt-derive", ] @@ -1015,7 +1089,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -1081,6 +1155,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + [[package]] name = "thiserror" version = "1.0.30" diff --git a/client/Cargo.toml b/client/Cargo.toml index 6e733aa..3041c11 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -16,6 +16,8 @@ path = "src/main.rs" [dependencies] anyhow = "1" colored = "2" +clap = { version = "3", features = ["derive"] } +clap_complete = "3" dialoguer = { version = "0.9", default-features = false } hostsfile = { path = "../hostsfile" } indoc = "1" @@ -26,7 +28,6 @@ regex = { version = "1", default-features = false, features = ["std"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" shared = { path = "../shared", default-features = false } -structopt = "0.3" ureq = { version = "2", default-features = false, features = ["json"] } wireguard-control = { path = "../wireguard-control" } diff --git a/client/src/main.rs b/client/src/main.rs index e1af1f9..e56f223 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -20,7 +20,7 @@ use std::{ thread, time::{Duration, Instant}, }; -use structopt::{clap::AppSettings, StructOpt}; +use clap::{AppSettings, IntoApp, Parser, Subcommand, Args}; use wireguard_control::{Device, DeviceUpdate, InterfaceName, PeerConfigBuilder, PeerInfo}; mod data_store; @@ -46,34 +46,35 @@ macro_rules! println_pad { } } -#[derive(Clone, Debug, StructOpt)] -#[structopt(name = "innernet", about, global_settings(&[AppSettings::ColoredHelp, AppSettings::DeriveDisplayOrder, AppSettings::VersionlessSubcommands, AppSettings::UnifiedHelpMessage]))] +#[derive(Clone, Debug, Parser)] +#[clap(name = "innernet", author, version, about)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] struct Opts { - #[structopt(subcommand)] + #[clap(subcommand)] command: Option, /// Verbose output, use -vv for even higher verbositude - #[structopt(short, long, parse(from_occurrences))] + #[clap(short, long, parse(from_occurrences))] verbose: u64, - #[structopt(short, long, default_value = "/etc/innernet")] + #[clap(short, long, default_value = "/etc/innernet")] config_dir: PathBuf, - #[structopt(short, long, default_value = "/var/lib/innernet")] + #[clap(short, long, default_value = "/var/lib/innernet")] data_dir: PathBuf, - #[structopt(flatten)] + #[clap(flatten)] network: NetworkOpts, } -#[derive(Clone, Debug, StructOpt)] +#[derive(Clone, Debug, Args)] struct HostsOpt { /// The path to write hosts to - #[structopt(long = "hosts-path", default_value = "/etc/hosts")] + #[clap(long = "hosts-path", default_value = "/etc/hosts")] hosts_path: PathBuf, /// Don't write to any hosts files - #[structopt(long = "no-write-hosts", conflicts_with = "hosts-path")] + #[clap(long = "no-write-hosts", conflicts_with = "hosts-path")] no_write_hosts: bool, } @@ -83,33 +84,33 @@ impl From for Option { } } -#[derive(Clone, Debug, StructOpt)] +#[derive(Clone, Debug, Subcommand)] enum Command { /// Install a new innernet config - #[structopt(alias = "redeem")] + #[clap(alias = "redeem")] Install { /// Path to the invitation file invite: PathBuf, - #[structopt(flatten)] + #[clap(flatten)] hosts: HostsOpt, - #[structopt(flatten)] + #[clap(flatten)] install_opts: InstallOpts, - #[structopt(flatten)] + #[clap(flatten)] nat: NatOpts, }, /// Enumerate all innernet connections - #[structopt(alias = "list")] + #[clap(alias = "list")] Show { /// One-line peer list - #[structopt(short, long)] + #[clap(short, long)] short: bool, /// Display peers in a tree based on the CIDRs - #[structopt(short, long)] + #[clap(short, long)] tree: bool, interface: Option, @@ -119,18 +120,18 @@ enum Command { Up { /// Enable daemon mode i.e. keep the process running, while fetching /// the latest peer list periodically - #[structopt(short, long)] + #[clap(short, long)] daemon: bool, /// Keep fetching the latest peer list at the specified interval in /// seconds. Valid only in daemon mode - #[structopt(long, default_value = "60")] + #[clap(long, default_value = "60")] interval: u64, - #[structopt(flatten)] + #[clap(flatten)] hosts: HostsOpt, - #[structopt(flatten)] + #[clap(flatten)] nat: NatOpts, interface: Option, @@ -140,10 +141,10 @@ enum Command { Fetch { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] hosts: HostsOpt, - #[structopt(flatten)] + #[clap(flatten)] nat: NatOpts, }, @@ -162,7 +163,7 @@ enum Command { AddPeer { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: AddPeerOpts, }, @@ -175,7 +176,7 @@ enum Command { RenamePeer { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: RenamePeerOpts, }, @@ -183,7 +184,7 @@ enum Command { AddCidr { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: AddCidrOpts, }, @@ -191,7 +192,7 @@ enum Command { DeleteCidr { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: DeleteCidrOpts, }, @@ -200,7 +201,7 @@ enum Command { interface: Interface, /// Display CIDRs in tree format - #[structopt(short, long)] + #[clap(short, long)] tree: bool, }, @@ -214,7 +215,7 @@ enum Command { AddAssociation { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: AddAssociationOpts, }, @@ -228,7 +229,7 @@ enum Command { SetListenPort { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: ListenPortOpts, }, @@ -236,14 +237,14 @@ enum Command { OverrideEndpoint { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] sub_opts: OverrideEndpointOpts, }, /// Generate shell completion scripts Completions { - #[structopt(possible_values = &structopt::clap::Shell::variants(), case_insensitive = true)] - shell: structopt::clap::Shell, + #[clap(arg_enum)] + shell: clap_complete::Shell, }, } @@ -1138,7 +1139,7 @@ fn print_peer(peer: &PeerState, short: bool, level: usize) { } fn main() { - let opts = Opts::from_args(); + let opts = Opts::parse(); util::init_logger(opts.verbose); let argv0 = std::env::args().next().unwrap(); @@ -1241,7 +1242,9 @@ fn run(opts: &Opts) -> Result<(), Error> { override_endpoint(&interface, opts, sub_opts)?; }, Command::Completions { shell } => { - Opts::clap().gen_completions_to("innernet", shell, &mut std::io::stdout()); + let mut app = Opts::into_app(); + let app_name = app.get_name().to_string(); + clap_complete::generate(shell, &mut app, app_name, &mut std::io::stdout()); std::process::exit(0); }, } diff --git a/server/Cargo.toml b/server/Cargo.toml index 1168adf..21b7a58 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -18,11 +18,14 @@ v6-test = [] [dependencies] anyhow = "1" bytes = "1" +clap = { version = "3", features = ["derive"] } +clap_complete = "3" colored = "2" dialoguer = { version = "0.9", default-features = false } hyper = { version = "0.14", default-features = false, features = ["http1", "server", "runtime", "stream"] } indoc = "1" ipnetwork = { git = "https://github.com/mcginty/ipnetwork", rev = "393f2d89e41ac6c1c0d80a31fc0997c387a7f7ba" } +lazy_static = "1" libc = "0.2" libsqlite3-sys = "0.23" log = "0.4" @@ -34,7 +37,6 @@ rusqlite = "0.26" serde = { version = "1", features = ["derive"] } serde_json = "1" shared = { path = "../shared" } -structopt = "0.3" subtle = "2" thiserror = "1" tokio = { version = "1", features = ["macros", "rt-multi-thread", "time"] } diff --git a/server/src/db/peer.rs b/server/src/db/peer.rs index 7abce7f..87e72f4 100644 --- a/server/src/db/peer.rs +++ b/server/src/db/peer.rs @@ -9,7 +9,6 @@ use std::{ ops::{Deref, DerefMut}, time::{Duration, SystemTime}, }; -use structopt::lazy_static; pub static CREATE_TABLE_SQL: &str = "CREATE TABLE peers ( id INTEGER PRIMARY KEY, diff --git a/server/src/initialize.rs b/server/src/initialize.rs index acb5991..cbb1422 100644 --- a/server/src/initialize.rs +++ b/server/src/initialize.rs @@ -1,5 +1,6 @@ use crate::*; use anyhow::anyhow; +use clap::{Parser}; use db::DatabaseCidr; use dialoguer::{theme::ColorfulTheme, Input}; use indoc::printdoc; @@ -22,26 +23,26 @@ fn create_database>( Ok(conn) } -#[derive(Debug, Default, Clone, PartialEq, StructOpt)] +#[derive(Debug, Default, Clone, PartialEq, Parser)] pub struct InitializeOpts { /// The network name (ex: evilcorp) - #[structopt(long)] + #[clap(long)] pub network_name: Option, /// The network CIDR (ex: 10.42.0.0/16) - #[structopt(long)] + #[clap(long)] pub network_cidr: Option, /// This server's external endpoint (ex: 100.100.100.100:51820) - #[structopt(long, conflicts_with = "auto-external-endpoint")] + #[clap(long, conflicts_with = "auto-external-endpoint")] pub external_endpoint: Option, /// Auto-resolve external endpoint - #[structopt(long = "auto-external-endpoint")] + #[clap(long = "auto-external-endpoint")] pub auto_external_endpoint: bool, /// Port to listen on (for the WireGuard interface) - #[structopt(long)] + #[clap(long)] pub listen_port: Option, } diff --git a/server/src/main.rs b/server/src/main.rs index df7aad0..e1b74fd 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,4 +1,5 @@ use anyhow::{anyhow, bail}; +use clap::{AppSettings, IntoApp, Parser, Subcommand}; use colored::*; use dialoguer::Confirm; use hyper::{http, server::conn::AddrStream, Body, Request, Response}; @@ -23,7 +24,6 @@ use std::{ sync::Arc, time::Duration, }; -use structopt::{clap::AppSettings, StructOpt}; use subtle::ConstantTimeEq; use wireguard_control::{Backend, Device, DeviceUpdate, InterfaceName, Key, PeerConfigBuilder}; @@ -44,28 +44,29 @@ pub use shared::{Association, AssociationContents}; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -#[derive(Debug, StructOpt)] -#[structopt(name = "innernet-server", about, global_settings(&[AppSettings::ColoredHelp, AppSettings::DeriveDisplayOrder, AppSettings::VersionlessSubcommands, AppSettings::UnifiedHelpMessage]))] +#[derive(Debug, Parser)] +#[clap(name = "innernet-server", author, version, about)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] struct Opts { - #[structopt(subcommand)] + #[clap(subcommand)] command: Command, - #[structopt(short, long, default_value = "/etc/innernet-server")] + #[clap(short, long, default_value = "/etc/innernet-server")] config_dir: PathBuf, - #[structopt(short, long, default_value = "/var/lib/innernet-server")] + #[clap(short, long, default_value = "/var/lib/innernet-server")] data_dir: PathBuf, - #[structopt(flatten)] + #[clap(flatten)] network: NetworkOpts, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] enum Command { /// Create a new network. - #[structopt(alias = "init")] + #[clap(alias = "init")] New { - #[structopt(flatten)] + #[clap(flatten)] opts: InitializeOpts, }, @@ -76,7 +77,7 @@ enum Command { Serve { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] network: NetworkOpts, }, @@ -84,7 +85,7 @@ enum Command { AddPeer { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] args: AddPeerOpts, }, @@ -92,7 +93,7 @@ enum Command { RenamePeer { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] args: RenamePeerOpts, }, @@ -100,7 +101,7 @@ enum Command { AddCidr { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] args: AddCidrOpts, }, @@ -108,14 +109,14 @@ enum Command { DeleteCidr { interface: Interface, - #[structopt(flatten)] + #[clap(flatten)] args: DeleteCidrOpts, }, /// Generate shell completion scripts Completions { - #[structopt(possible_values = &structopt::clap::Shell::variants(), case_insensitive = true)] - shell: structopt::clap::Shell, + #[clap(arg_enum)] + shell: clap_complete::Shell, }, } @@ -235,7 +236,7 @@ async fn main() -> Result<(), Box> { } pretty_env_logger::init(); - let opts = Opts::from_args(); + let opts = Opts::parse(); if unsafe { libc::getuid() } != 0 && !matches!(opts.command, Command::Completions { .. }) { return Err("innernet-server must run as root.".into()); @@ -260,7 +261,9 @@ async fn main() -> Result<(), Box> { Command::AddCidr { interface, args } => add_cidr(&interface, &conf, args)?, Command::DeleteCidr { interface, args } => delete_cidr(&interface, &conf, args)?, Command::Completions { shell } => { - Opts::clap().gen_completions_to("innernet-server", shell, &mut std::io::stdout()); + let mut app = Opts::into_app(); + let app_name = app.get_name().to_string(); + clap_complete::generate(shell, &mut app, app_name, &mut std::io::stdout()); std::process::exit(0); }, } diff --git a/shared/Cargo.toml b/shared/Cargo.toml index f13058c..a551c2c 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -9,6 +9,7 @@ version = "1.5.2" [dependencies] anyhow = "1" atty = "0.2" +clap = { version = "3", features = ["derive"] } colored = "2.0" dialoguer = { version = "0.9", default-features = false } indoc = "1" diff --git a/shared/src/types.rs b/shared/src/types.rs index c022b33..0466d67 100644 --- a/shared/src/types.rs +++ b/shared/src/types.rs @@ -1,4 +1,5 @@ use anyhow::{anyhow, Error}; +use clap::Args; use ipnetwork::IpNetwork; use lazy_static::lazy_static; use regex::Regex; @@ -13,7 +14,6 @@ use std::{ time::{Duration, SystemTime}, vec, }; -use structopt::StructOpt; use url::Host; use wireguard_control::{ AllowedIp, Backend, InterfaceName, InvalidInterfaceName, Key, PeerConfig, PeerConfigBuilder, @@ -283,102 +283,102 @@ pub struct RedeemContents { pub public_key: String, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct InstallOpts { /// Set a specific interface name - #[structopt(long, conflicts_with = "default-name")] + #[clap(long, conflicts_with = "default-name")] pub name: Option, /// Use the network name inside the invitation as the interface name - #[structopt(long = "default-name")] + #[clap(long = "default-name")] pub default_name: bool, /// Delete the invitation after a successful install - #[structopt(short, long)] + #[clap(short, long)] pub delete_invite: bool, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct AddPeerOpts { /// Name of new peer - #[structopt(long)] + #[clap(long)] pub name: Option, /// Specify desired IP of new peer (within parent CIDR) - #[structopt(long, conflicts_with = "auto-ip")] + #[clap(long, conflicts_with = "auto-ip")] pub ip: Option, /// Auto-assign the peer the first available IP within the CIDR - #[structopt(long = "auto-ip")] + #[clap(long = "auto-ip")] pub auto_ip: bool, /// Name of CIDR to add new peer under - #[structopt(long)] + #[clap(long)] pub cidr: Option, /// Make new peer an admin? - #[structopt(long)] + #[clap(long)] pub admin: Option, /// Bypass confirmation - #[structopt(long)] + #[clap(long)] pub yes: bool, /// Save the config to the given location - #[structopt(long)] + #[clap(long)] pub save_config: Option, /// Invite expiration period (eg. '30d', '7w', '2h', '60m', '1000s') - #[structopt(long)] + #[clap(long)] pub invite_expires: Option, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct RenamePeerOpts { /// Name of peer to rename - #[structopt(long)] + #[clap(long)] pub name: Option, /// The new name of the peer - #[structopt(long)] + #[clap(long)] pub new_name: Option, /// Bypass confirmation - #[structopt(long)] + #[clap(long)] pub yes: bool, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct AddCidrOpts { /// The CIDR name (eg. 'engineers') - #[structopt(long)] + #[clap(long)] pub name: Option, /// The CIDR network (eg. '10.42.5.0/24') - #[structopt(long)] + #[clap(long)] pub cidr: Option, /// The CIDR parent name - #[structopt(long)] + #[clap(long)] pub parent: Option, /// Bypass confirmation - #[structopt(long)] + #[clap(long)] pub yes: bool, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct DeleteCidrOpts { /// The CIDR name (eg. 'engineers') - #[structopt(long)] + #[clap(long)] pub name: Option, /// Bypass confirmation - #[structopt(long)] + #[clap(long)] pub yes: bool, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct AddAssociationOpts { /// The first cidr to associate pub cidr1: Option, @@ -387,49 +387,49 @@ pub struct AddAssociationOpts { pub cidr2: Option, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct ListenPortOpts { /// The listen port you'd like to set for the interface - #[structopt(short, long)] + #[clap(short, long)] pub listen_port: Option, /// Unset the local listen port to use a randomized port - #[structopt(short, long, conflicts_with = "listen-port")] + #[clap(short, long, conflicts_with = "listen-port")] pub unset: bool, /// Bypass confirmation - #[structopt(long)] + #[clap(long)] pub yes: bool, } -#[derive(Debug, Clone, PartialEq, StructOpt)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct OverrideEndpointOpts { /// The listen port you'd like to set for the interface - #[structopt(short, long)] + #[clap(short, long)] pub endpoint: Option, /// Unset an existing override to use the automatic endpoint discovery - #[structopt(short, long, conflicts_with = "endpoint")] + #[clap(short, long, conflicts_with = "endpoint")] pub unset: bool, /// Bypass confirmation - #[structopt(long)] + #[clap(long)] pub yes: bool, } -#[derive(Debug, Clone, StructOpt)] +#[derive(Debug, Clone, Args)] pub struct NatOpts { - #[structopt(long)] + #[clap(long)] /// Don't attempt NAT traversal. Note that this still will report candidates /// unless you also specify to exclude all NAT candidates. pub no_nat_traversal: bool, - #[structopt(long)] + #[clap(long)] /// Exclude one or more CIDRs from NAT candidate reporting. /// ex. --exclude-nat-candidates '0.0.0.0/0' would report no candidates. pub exclude_nat_candidates: Vec, - #[structopt(long, conflicts_with = "exclude-nat-candidates")] + #[clap(long, conflicts_with = "exclude-nat-candidates")] /// Don't report any candidates to coordinating server. /// Shorthand for --exclude-nat-candidates '0.0.0.0/0'. pub no_nat_candidates: bool, @@ -454,19 +454,19 @@ impl NatOpts { } } -#[derive(Debug, Clone, Copy, StructOpt)] +#[derive(Debug, Clone, Copy, Args)] pub struct NetworkOpts { - #[structopt(long)] + #[clap(long)] /// Whether the routing should be done by innernet or is done by an /// external tool like e.g. babeld. pub no_routing: bool, - #[structopt(long, default_value, possible_values = Backend::variants())] + #[clap(long, default_value_t, possible_values = Backend::variants())] /// Specify a WireGuard backend to use. /// If not set, innernet will auto-select based on availability. pub backend: Backend, - #[structopt(long)] + #[clap(long)] /// Specify the desired MTU for your interface (default: 1420 for IPv4 and 1400 for IPv6). pub mtu: Option, }