mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
CLI parser stuff...
This commit is contained in:
parent
fd6cf33e97
commit
c29a64602a
8 changed files with 331 additions and 23 deletions
|
@ -33,10 +33,15 @@ extern "C" {
|
|||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Default primary UDP port for devices running a ZeroTier endpoint
|
||||
* Default primary UDP port
|
||||
*/
|
||||
#define ZT_DEFAULT_PORT 9993
|
||||
|
||||
/**
|
||||
* Default secondary UDP port (if enabled)
|
||||
*/
|
||||
#define ZT_DEFAULT_SECONDARY_PORT 293
|
||||
|
||||
/**
|
||||
* IP protocol number for naked IP encapsulation (this is not currently used)
|
||||
*/
|
||||
|
|
|
@ -53,14 +53,17 @@ pub use portableatomici64::PortableAtomicI64;
|
|||
pub use virtualnetworkconfig::*;
|
||||
pub use multicastgroup::MulticastGroup;
|
||||
|
||||
/// Recommended minimum thread stack size for ZeroTier threads.
|
||||
/// Recommended minimum thread stack size for background threads.
|
||||
pub const RECOMMENDED_THREAD_STACK_SIZE: usize = 262144;
|
||||
|
||||
/// Default TCP and UDP port for ZeroTier.
|
||||
/// Default TCP and UDP port.
|
||||
pub const DEFAULT_PORT: u16 = ztcore::ZT_DEFAULT_PORT as u16;
|
||||
|
||||
/// Default secondary UDP port if enabled.
|
||||
pub const DEFAULT_SECONDARY_PORT: u16 = ztcore::ZT_DEFAULT_SECONDARY_PORT as u16;
|
||||
|
||||
/// Size of a ZeroTier core "Buffer" in bytes.
|
||||
pub const BUF_SIZE: u32 = ztcore::ZT_BUF_SIZE;
|
||||
pub const BUF_SIZE: usize = ztcore::ZT_BUF_SIZE as usize;
|
||||
|
||||
/// Minimum physical MTU.
|
||||
pub const MIN_MTU: u32 = ztcore::ZT_MIN_MTU;
|
||||
|
|
12
rust-zerotier-service/Cargo.lock
generated
12
rust-zerotier-service/Cargo.lock
generated
|
@ -131,6 +131,7 @@ dependencies = [
|
|||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"term_size",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
|
@ -1037,12 +1038,23 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term_size"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"term_size",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
|
|
|
@ -9,18 +9,18 @@ build = "build.rs"
|
|||
|
||||
[dependencies]
|
||||
zerotier-core = { path = "../rust-zerotier-core" }
|
||||
num_cpus = "1.13"
|
||||
num_cpus = "1"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
warp = "0.3"
|
||||
warp = "0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
futures = "0.3"
|
||||
clap = { version = "2", features = ["default"] }
|
||||
chrono = "0.4"
|
||||
hex = "0.4"
|
||||
futures = "0"
|
||||
clap = { version = "2", features = ["suggestions", "wrap_help"] }
|
||||
chrono = "0"
|
||||
hex = "0"
|
||||
lazy_static = "1"
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.3"
|
||||
num-traits = "0"
|
||||
num-derive = "0"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
winapi = { version = "0.3.9", features = ["handleapi", "ws2ipdef", "ws2tcpip"] }
|
||||
|
|
259
rust-zerotier-service/src/cli.rs
Normal file
259
rust-zerotier-service/src/cli.rs
Normal file
|
@ -0,0 +1,259 @@
|
|||
use std::str::FromStr;
|
||||
use clap::{App, Arg, ArgMatches, ErrorKind};
|
||||
|
||||
fn make_help() -> String {
|
||||
let ver = zerotier_core::version();
|
||||
format!(r###"ZeroTier Network Hypervisor Service Version {}.{}.{}
|
||||
(c)2013-2021 ZeroTier, Inc.
|
||||
Licensed under the ZeroTier BSL (see LICENSE.txt)
|
||||
|
||||
Usage: zerotier [-global options] <command> [command args]
|
||||
|
||||
Global Options:
|
||||
|
||||
-j Output raw JSON where applicable
|
||||
-p <path> Use alternate base path
|
||||
-t <path> Load secret auth token from a file
|
||||
-T <token> Set secret auth token on command line
|
||||
|
||||
Common Operations:
|
||||
|
||||
help Show this help
|
||||
version Print version
|
||||
|
||||
· status Show node status and configuration
|
||||
|
||||
· set [setting] [value] List all settings (with no args)
|
||||
· port <port> Primary P2P port
|
||||
· secondaryport <port/0> Secondary P2P port (0 to disable)
|
||||
· blacklist cidr <IP/bits> <boolean> Toggle physical path blacklisting
|
||||
· blacklist if <prefix> <boolean> Toggle interface prefix blacklisting
|
||||
· portmap <boolean> Toggle use of uPnP or NAT-PMP
|
||||
|
||||
· peer <command> [option]
|
||||
· show <address> Show detailed peer information
|
||||
· list List peers
|
||||
· listroots List root peers
|
||||
· try <address> <endpoint> [...] Try peer at explicit endpoint
|
||||
|
||||
· network <command> [option]
|
||||
· show <network ID> Show detailed network information
|
||||
· list List networks
|
||||
· set <network ID> [option] [value] Get or set network options
|
||||
· manageips <boolean> Is IP management allowed?
|
||||
· manageroutes <boolean> Is route management allowed?
|
||||
· managedns <boolean> Allow network to push DNS config
|
||||
· globalips <boolean> Allow assignment of global IPs?
|
||||
· globalroutes <boolean> Can global IP space routes be set?
|
||||
· defaultroute <boolean> Can default route be overridden?
|
||||
|
||||
· join [-options] <network> Join a virtual network
|
||||
-t <token> Token to submit to controller
|
||||
-c <identity | fingerprint> Controller identity or fingerprint
|
||||
· leave <network> Leave a virtual network
|
||||
|
||||
Advanced Operations:
|
||||
|
||||
service Start this node (runs until stopped)
|
||||
|
||||
controller <command> [option]
|
||||
· list List networks on controller
|
||||
· new Create a new network
|
||||
· set <network> [setting] [value] Show or modify network settings
|
||||
· show <network> [<address>] Show network or member status
|
||||
· auth <address> Authorize a peer
|
||||
· deauth <address> Deauthorize a peer
|
||||
|
||||
identity <command> [args]
|
||||
new [c25519 | p384] Create identity (default: c25519)
|
||||
getpublic <identity> Extract only public part of identity
|
||||
fingerprint <identity> Get an identity's fingerprint
|
||||
validate <identity> Locally validate an identity
|
||||
sign <identity> <file> Sign a file with an identity's key
|
||||
verify <identity> <file> <sig> Verify a signature
|
||||
|
||||
locator <command> [args]
|
||||
new <identity> <endpoint> [...] Create new signed locator
|
||||
verify <identity> <locator> Verify locator signature
|
||||
show <locator> Show contents of a locator
|
||||
|
||||
cert <command> [args]
|
||||
· list List certificates at local node
|
||||
· show <serial> Show certificate details
|
||||
newsid <secret out> Create a new subject unique ID
|
||||
newcsr <subject> <secret> <csr out> Create a subject CSR
|
||||
sign <csr> <identity> <cert out> Sign a CSR to create a certificate
|
||||
verify <cert> Verify certificate (not chain)
|
||||
dump <cert> Verify and print certificate
|
||||
· import <cert> [trust] [...] Import certificate into this node
|
||||
trust flag: rootca Certificate is a root CA
|
||||
trust flag: ztrootset ZeroTier root node set
|
||||
· restore Re-import default certificates
|
||||
· export <serial> [path] Export a certificate from this node
|
||||
· delete <serial|ALL> Delete certificate from this node
|
||||
|
||||
· Command requires a running node and access to a local API token.
|
||||
|
||||
An <address> may be specified as a 10-digit short ZeroTier address, a
|
||||
fingerprint containing both an address and a SHA384 hash, or an identity.
|
||||
The latter two options are equivalent in terms of specificity and may be
|
||||
used if stronger security guarantees are desired than those provided by
|
||||
the basic ZeroTier addressing system. Fields of type <identity> must be
|
||||
full identities and may be specified either verbatim or as a path to a file.
|
||||
|
||||
An <endpoint> is a place where a peer may be reached. Currently these are
|
||||
just 'IP/port' format addresses but other types may be added in the future.
|
||||
|
||||
The 'service' command starts a node. It will run until the node receives
|
||||
an exit signal and is normally not used directly."###, ver.0, ver.1, ver.2)
|
||||
}
|
||||
|
||||
pub(crate) fn print_help() {
|
||||
println!("{}", make_help());
|
||||
}
|
||||
|
||||
fn is_bool(v: String) -> Result<(), String> {
|
||||
if !v.is_empty() {
|
||||
match v.chars().next().unwrap() {
|
||||
'y' | 'Y' | '1' | 't' | 'T' | 'n' | 'N' | '0' | 'f' | 'F' => { return Ok(()); }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Err(format!("invalid boolean value: '{}'", v))
|
||||
}
|
||||
|
||||
fn is_valid_port(v: String) -> Result<(), String> {
|
||||
let i = u16::from_str(v.as_str()).unwrap_or(0);
|
||||
if i >= 1 {
|
||||
return Ok(());
|
||||
}
|
||||
Err(format!("invalid TCP/IP port number: {}", v))
|
||||
}
|
||||
|
||||
/// Parses CLI arguments, prints error and exits on failure.
|
||||
pub(crate) fn parse_cli_args() -> ArgMatches<'static> {
|
||||
let help = make_help();
|
||||
let args = App::new("zerotier")
|
||||
.arg(Arg::with_name("json").short("j"))
|
||||
.arg(Arg::with_name("path").short("p").takes_value(true))
|
||||
.arg(Arg::with_name("token_path").short("t").takes_value(true))
|
||||
.arg(Arg::with_name("token").short("T").takes_value(true))
|
||||
.subcommand(App::new("help"))
|
||||
.subcommand(App::new("version"))
|
||||
.subcommand(App::new("status"))
|
||||
.subcommand(App::new("set")
|
||||
.subcommand(App::new("port")
|
||||
.arg(Arg::with_name("port#").index(1).validator(is_valid_port)))
|
||||
.subcommand(App::new("secondaryport")
|
||||
.arg(Arg::with_name("port#").index(1).validator(is_valid_port)))
|
||||
.subcommand(App::new("blacklist")
|
||||
.subcommand(App::new("cidr")
|
||||
.arg(Arg::with_name("ip/bits").index(1))
|
||||
.arg(Arg::with_name("boolean").index(2).validator(is_bool)))
|
||||
.subcommand(App::new("if")
|
||||
.arg(Arg::with_name("prefix").index(1))
|
||||
.arg(Arg::with_name("boolean").index(2).validator(is_bool))))
|
||||
.subcommand(App::new("portmap")
|
||||
.arg(Arg::with_name("boolean").index(1).validator(is_bool))))
|
||||
.subcommand(App::new("peer")
|
||||
.subcommand(App::new("show")
|
||||
.arg(Arg::with_name("address").index(1).required(true)))
|
||||
.subcommand(App::new("list"))
|
||||
.subcommand(App::new("listroots"))
|
||||
.subcommand(App::new("try")))
|
||||
.subcommand(App::new("network")
|
||||
.subcommand(App::new("show"))
|
||||
.subcommand(App::new("list"))
|
||||
.subcommand(App::new("set")))
|
||||
.subcommand(App::new("join")
|
||||
.arg(Arg::with_name("token").short("t").takes_value(true))
|
||||
.arg(Arg::with_name("controller").short("c").takes_value(true))
|
||||
.arg(Arg::with_name("id").index(1).required(true)))
|
||||
.subcommand(App::new("leave")
|
||||
.arg(Arg::with_name("id").index(1).required(true)))
|
||||
.subcommand(App::new("service"))
|
||||
.subcommand(App::new("controller")
|
||||
.subcommand(App::new("list"))
|
||||
.subcommand(App::new("new"))
|
||||
.subcommand(App::new("set")
|
||||
.arg(Arg::with_name("id").index(1).required(true))
|
||||
.arg(Arg::with_name("setting").index(2))
|
||||
.arg(Arg::with_name("value").index(3)))
|
||||
.subcommand(App::new("show")
|
||||
.arg(Arg::with_name("id").index(1).required(true))
|
||||
.arg(Arg::with_name("member").index(2)))
|
||||
.subcommand(App::new("auth")
|
||||
.arg(Arg::with_name("member").index(1).required(true)))
|
||||
.subcommand(App::new("deauth")
|
||||
.arg(Arg::with_name("member").index(1).required(true))))
|
||||
.subcommand(App::new("identity")
|
||||
.subcommand(App::new("new")
|
||||
.arg(Arg::with_name("type").possible_value("p384").possible_value("c25519").index(1)))
|
||||
.subcommand(App::new("getpublic")
|
||||
.arg(Arg::with_name("identity").index(1).required(true)))
|
||||
.subcommand(App::new("fingerprint")
|
||||
.arg(Arg::with_name("identity").index(1).required(true)))
|
||||
.subcommand(App::new("validate")
|
||||
.arg(Arg::with_name("identity").index(1).required(true)))
|
||||
.subcommand(App::new("sign")
|
||||
.arg(Arg::with_name("identity").index(1).required(true))
|
||||
.arg(Arg::with_name("file").index(2).required(true)))
|
||||
.subcommand(App::new("verify")
|
||||
.arg(Arg::with_name("identity").index(1).required(true))
|
||||
.arg(Arg::with_name("file").index(2).required(true))
|
||||
.arg(Arg::with_name("signature").index(3).required(true))))
|
||||
.subcommand(App::new("locator")
|
||||
.subcommand(App::new("new")
|
||||
.arg(Arg::with_name("identity").index(1).required(true))
|
||||
.arg(Arg::with_name("endpoint").index(2).multiple(true).required(true)))
|
||||
.subcommand(App::new("verify")
|
||||
.arg(Arg::with_name("identity").index(1).required(true))
|
||||
.arg(Arg::with_name("locator").index(2).required(true)))
|
||||
.subcommand(App::new("show")
|
||||
.arg(Arg::with_name("locator").index(1).required(true))))
|
||||
.subcommand(App::new("cert")
|
||||
.subcommand(App::new("list"))
|
||||
.subcommand(App::new("show")
|
||||
.arg(Arg::with_name("serial").index(1).required(true)))
|
||||
.subcommand(App::new("newsid")
|
||||
.arg(Arg::with_name("path").index(1).required(true)))
|
||||
.subcommand(App::new("newcsr")
|
||||
.arg(Arg::with_name("subject").index(1).required(true))
|
||||
.arg(Arg::with_name("secret").index(2).required(true))
|
||||
.arg(Arg::with_name("output").index(3).required(true)))
|
||||
.subcommand(App::new("sign")
|
||||
.arg(Arg::with_name("csr").index(1).required(true))
|
||||
.arg(Arg::with_name("identity").index(2).required(true))
|
||||
.arg(Arg::with_name("output").index(3).required(true)))
|
||||
.subcommand(App::new("verify")
|
||||
.arg(Arg::with_name("cert").index(1).required(true)))
|
||||
.subcommand(App::new("dump")
|
||||
.arg(Arg::with_name("cert").index(1).required(true)))
|
||||
.subcommand(App::new("import")
|
||||
.arg(Arg::with_name("cert").index(1).required(true))
|
||||
.arg(Arg::with_name("trust").possible_value("rootca").possible_value("ztrootset").index(2).multiple(true)))
|
||||
.subcommand(App::new("restore"))
|
||||
.subcommand(App::new("export")
|
||||
.arg(Arg::with_name("serial").index(1).required(true))
|
||||
.arg(Arg::with_name("path").index(2)))
|
||||
.subcommand(App::new("delete")
|
||||
.arg(Arg::with_name("serial").index(1).required(true))))
|
||||
.help(help.as_str())
|
||||
.get_matches_from_safe(std::env::args());
|
||||
|
||||
if args.is_err() {
|
||||
let e = args.err().unwrap();
|
||||
match e.kind {
|
||||
ErrorKind::HelpDisplayed => {}
|
||||
_ => { print_help(); }
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
let args = args.unwrap();
|
||||
if args.subcommand_name().is_none() {
|
||||
print_help();
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
args
|
||||
}
|
|
@ -61,20 +61,20 @@ pub const UNASSIGNED_PRIVILEGED_PORTS: [u16; 299] = [
|
|||
1023,
|
||||
];
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigPhysicalPathConfig {
|
||||
pub blacklist: bool
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigVirtualConfig {
|
||||
#[serde(rename = "try")]
|
||||
pub try_: Vec<InetAddress>
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigNetworkSettings {
|
||||
#[serde(rename = "allowManagedIPs")]
|
||||
|
@ -89,7 +89,7 @@ pub struct LocalConfigNetworkSettings {
|
|||
pub allow_default_route_override: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigSettings {
|
||||
#[serde(rename = "primaryPort")]
|
||||
|
@ -118,7 +118,7 @@ pub struct LocalConfigSettings {
|
|||
pub explicit_addresses: Vec<InetAddress>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfig {
|
||||
pub physical: BTreeMap<InetAddress, LocalConfigPhysicalPathConfig>,
|
||||
|
@ -163,7 +163,6 @@ impl LocalConfigSettings {
|
|||
#[cfg(target_os = "linux")]
|
||||
const DEFAULT_PREFIX_BLACKLIST: [&'static str; 5] = ["lo", "tun", "tap", "ipsec", "zt"];
|
||||
|
||||
// This is not applicable on Windows as it doesn't use the same device name semantics.
|
||||
#[cfg(windows)]
|
||||
const DEFAULT_PREFIX_BLACKLIST: [&'static str; 0] = [];
|
||||
|
||||
|
@ -187,7 +186,7 @@ impl Default for LocalConfigSettings {
|
|||
|
||||
LocalConfigSettings {
|
||||
primary_port: zerotier_core::DEFAULT_PORT,
|
||||
secondary_port: Some(293), // this is one of UNASSIGNED_PRIVILEGED_PORTS that we will default to
|
||||
secondary_port: Some(zerotier_core::DEFAULT_SECONDARY_PORT),
|
||||
auto_port_search: true,
|
||||
port_mapping: true,
|
||||
log_size_max: 1048576,
|
||||
|
@ -212,3 +211,29 @@ impl Default for LocalConfig {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
zerotier_core::implement_to_from_json!(LocalConfig);
|
||||
|
||||
impl LocalConfig {
|
||||
pub fn load(path: &String) -> std::io::Result<LocalConfig> {
|
||||
let md = std::path::Path::new(path).metadata();
|
||||
if md.is_err() {
|
||||
return Err(md.err().unwrap());
|
||||
}
|
||||
if md.unwrap().len() > 1048576 {
|
||||
}
|
||||
let json = std::fs::read_to_string(path);
|
||||
if json.is_err() {
|
||||
return Err(json.err().unwrap());
|
||||
}
|
||||
let json = Self::new_from_json(json.unwrap().as_str());
|
||||
if json.is_err() {
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, json.err().unwrap().to_string()));
|
||||
}
|
||||
Ok(json.unwrap())
|
||||
}
|
||||
|
||||
pub fn save(&self, path: &String) -> std::io::Result<()> {
|
||||
std::fs::write(path, self.to_json())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
mod cli;
|
||||
mod fastudpsocket;
|
||||
mod localconfig;
|
||||
mod physicallink;
|
||||
|
@ -70,6 +71,7 @@ impl NodeEventHandler<Network> for ServiceEventHandler {
|
|||
0
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn path_check(&self, address: Address, id: &Identity, local_socket: i64, sock_addr: &InetAddress) -> bool {
|
||||
true
|
||||
}
|
||||
|
@ -80,6 +82,8 @@ impl NodeEventHandler<Network> for ServiceEventHandler {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let cli_args = Some(cli::parse_cli_args());
|
||||
|
||||
let inaddr_v6_any = IpAddr::from_str("::0").unwrap();
|
||||
let mut process_exit_value: i32 = 0;
|
||||
|
||||
|
@ -137,7 +141,7 @@ fn main() {
|
|||
.or(status)
|
||||
.or(network)
|
||||
.or(peer)
|
||||
)).try_bind_with_graceful_shutdown((inaddr_v6_any, warp_server_port), async { shutdown_rx.await; });
|
||||
)).try_bind_with_graceful_shutdown((inaddr_v6_any, warp_server_port), async { let _ = shutdown_rx.await; });
|
||||
if warp_server.is_err() {
|
||||
// TODO: log unable to bind to primary port
|
||||
run.store(false, Ordering::Relaxed);
|
||||
|
|
|
@ -101,7 +101,7 @@ fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) -
|
|||
|
||||
let mut nd: osdep::in6_ndireq = zeroed();
|
||||
copy_nonoverlapping(dev.as_ptr(), nd.ifname.as_mut_ptr().cast::<u8>(), if dev.len() > (nd.ifname.len() - 1) { nd.ifname.len() - 1 } else { dev.len() });
|
||||
if osdep::ioctl(s, osdep::c_SIOCGIFINFO_IN6, (&nd as *mut osdep::in6_ndireq).cast()) == 0 {
|
||||
if osdep::ioctl(s, osdep::c_SIOCGIFINFO_IN6, (&mut nd as *mut osdep::in6_ndireq).cast::<c_void>()) == 0 {
|
||||
let oldflags = nd.ndi.flags;
|
||||
if perform_nud {
|
||||
nd.ndi.flags |= osdep::ND6_IFF_PERFORMNUD as osdep::u_int32_t;
|
||||
|
@ -109,7 +109,7 @@ fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) -
|
|||
nd.ndi.flags &= !(osdep::ND6_IFF_PERFORMNUD as osdep::u_int32_t);
|
||||
}
|
||||
if nd.ndi.flags != oldflags {
|
||||
if osdep::ioctl(s, osdep::c_SIOCSIFINFO_FLAGS, (&nd as *mut osdep::in6_ndireq).cast()) != 0 {
|
||||
if osdep::ioctl(s, osdep::c_SIOCSIFINFO_FLAGS, (&mut nd as *mut osdep::in6_ndireq).cast::<c_void>()) != 0 {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) -
|
|||
|
||||
let mut ifr: osdep::in6_ifreq = zeroed();
|
||||
copy_nonoverlapping(dev.as_ptr(), ifr.ifr_name.as_mut_ptr().cast::<u8>(), if dev.len() > (ifr.ifr_name.len() - 1) { ifr.ifr_name.len() - 1 } else { dev.len() });
|
||||
if osdep::ioctl(s, if accept_ra { osdep::c_SIOCAUTOCONF_START } else { osdep::c_SIOCAUTOCONF_STOP }, (&ifr as *mut osdep::in6_ifreq).cast()) != 0 {
|
||||
if osdep::ioctl(s, if accept_ra { osdep::c_SIOCAUTOCONF_START } else { osdep::c_SIOCAUTOCONF_STOP }, (&mut ifr as *mut osdep::in6_ifreq).cast::<c_void>()) != 0 {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue