blob: 5da2d3c53d2a04e95501910bc9a08e84c5ece339 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fidl_fuchsia_logger as logger;
use fidl_fuchsia_net as net;
use fidl_fuchsia_net_ext as net_ext;
use argh::FromArgs;
fn parse_log_level_str(value: &str) -> Result<logger::LogLevelFilter, String> {
match &value.to_lowercase()[..] {
"trace" => Ok(logger::LogLevelFilter::Trace),
"debug" => Ok(logger::LogLevelFilter::Debug),
"info" => Ok(logger::LogLevelFilter::Info),
"warn" => Ok(logger::LogLevelFilter::Warn),
"error" => Ok(logger::LogLevelFilter::Error),
"fatal" => Ok(logger::LogLevelFilter::Fatal),
_ => Err("invalid log level".to_string()),
}
}
fn parse_ip_version_str(value: &str) -> Result<net::IpVersion, String> {
match &value.to_lowercase()[..] {
"ipv4" => Ok(net::IpVersion::V4),
"ipv6" => Ok(net::IpVersion::V6),
_ => Err("invalid IP version".to_string()),
}
}
#[derive(FromArgs)]
/// commands for net-cli
pub struct Command {
#[argh(subcommand)]
pub cmd: CommandEnum,
}
#[derive(FromArgs)]
#[argh(subcommand)]
pub enum CommandEnum {
Filter(Filter),
Fwd(Fwd),
If(If),
IpFwd(IpFwd),
Log(Log),
Neigh(Neigh),
Route(Route),
Stat(Stat),
Metric(Metric),
Dhcp(Dhcp),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "filter")]
/// commands for packet filter
pub struct Filter {
#[argh(subcommand)]
pub filter_cmd: FilterEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum FilterEnum {
Disable(FilterDisable),
Enable(FilterEnable),
GetNatRules(FilterGetNatRules),
GetRdrRules(FilterGetRdrRules),
GetRules(FilterGetRules),
IsEnabled(FilterIsEnabled),
SetNatRules(FilterSetNatRules),
SetRdrRules(FilterSetRdrRules),
SetRules(FilterSetRules),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "disable")]
/// disables the packet filter
pub struct FilterDisable {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "enable")]
/// enables the packet filter
pub struct FilterEnable {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "get-nat-rules")]
/// gets nat rules
pub struct FilterGetNatRules {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "get-rdr-rules")]
/// gets rdr rules
pub struct FilterGetRdrRules {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "get-rules")]
/// gets filter rules
pub struct FilterGetRules {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "is-enabled")]
/// is the packet filter enabled?
pub struct FilterIsEnabled {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "set-nat-rules")]
/// sets nat rules (see the netfilter::parser library for the NAT rules format)
pub struct FilterSetNatRules {
#[argh(positional)]
pub rules: String,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "set-rdr-rules")]
/// sets rdr rules (see the netfilter::parser library for the RDR rules format)
pub struct FilterSetRdrRules {
#[argh(positional)]
pub rules: String,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "set-rules")]
/// sets filter rules (see the netfilter::parser library for the rules format)
pub struct FilterSetRules {
#[argh(positional)]
pub rules: String,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "fwd")]
/// commands for forwarding tables
pub struct Fwd {
#[argh(subcommand)]
pub fwd_cmd: FwdEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum FwdEnum {
AddDevice(FwdAddDevice),
AddHop(FwdAddHop),
Del(FwdDel),
List(FwdList),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "add-device")]
/// adds a forwarding table entry to route to a device
pub struct FwdAddDevice {
#[argh(positional)]
pub id: u64,
#[argh(positional)]
pub addr: String,
#[argh(positional)]
pub prefix: u8,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "add-hop")]
/// adds a forwarding table entry to route to a IP address
pub struct FwdAddHop {
#[argh(positional)]
pub next_hop: String,
#[argh(positional)]
pub addr: String,
#[argh(positional)]
pub prefix: u8,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "del")]
/// deletes a forwarding table entry
pub struct FwdDel {
#[argh(positional)]
pub addr: String,
#[argh(positional)]
pub prefix: u8,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "list")]
/// lists forwarding table entries
pub struct FwdList {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "if")]
/// commands for network interfaces
pub struct If {
#[argh(subcommand)]
pub if_cmd: IfEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum IfEnum {
Add(IfAdd),
Addr(IfAddr),
Bridge(IfBridge),
Del(IfDel),
Disable(IfDisable),
Enable(IfEnable),
Get(IfGet),
List(IfList),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "add")]
/// adds a network interface by path
pub struct IfAdd {
// The path must yield a handle to a fuchsia.hardware.ethernet.Device interface.
// Currently this means paths under /dev/class/ethernet.
#[argh(positional)]
pub path: String,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "addr")]
/// commands for updates network interface addresses
pub struct IfAddr {
#[argh(subcommand)]
pub addr_cmd: IfAddrEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum IfAddrEnum {
Add(IfAddrAdd),
Del(IfAddrDel),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "add")]
/// adds an address to the network interface
pub struct IfAddrAdd {
#[argh(positional)]
pub id: u64,
#[argh(positional)]
pub addr: String,
#[argh(positional)]
pub prefix: u8,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "del")]
/// deletes an address from the network interface
pub struct IfAddrDel {
#[argh(positional)]
pub id: u64,
#[argh(positional)]
pub addr: String,
#[argh(positional)]
pub prefix: Option<u8>,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "bridge")]
/// creates a bridge between network interfaces
pub struct IfBridge {
#[argh(positional)]
pub ids: Vec<u32>,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "del")]
/// removes a network interface
pub struct IfDel {
#[argh(positional)]
pub id: u64,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "disable")]
/// disables a network interface
pub struct IfDisable {
#[argh(positional)]
pub id: u64,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "enable")]
/// enables a network interface
pub struct IfEnable {
#[argh(positional)]
pub id: u64,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "get")]
/// queries a network interface
pub struct IfGet {
#[argh(positional)]
pub id: u64,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "list")]
/// lists network interfaces
pub struct IfList {
#[argh(positional)]
pub name_pattern: Option<String>,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "ip-fwd")]
/// commands for IP forwarding
pub struct IpFwd {
#[argh(subcommand)]
pub ip_fwd_cmd: IpFwdEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum IpFwdEnum {
Disable(IpFwdDisable),
Enable(IpFwdEnable),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "disable")]
/// disables IP forwarding
pub struct IpFwdDisable {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "enable")]
/// enables IP forwarding
pub struct IpFwdEnable {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "log")]
/// commands for logging
pub struct Log {
#[argh(subcommand)]
pub log_cmd: LogEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum LogEnum {
SetLevel(LogSetLevel),
SetPackets(LogSetPackets),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "set-level")]
/// syslog severity level / loglevel
pub struct LogSetLevel {
#[argh(positional, from_str_fn(parse_log_level_str))]
pub log_level: logger::LogLevelFilter,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "set-packets")]
/// log packets to stdout
pub struct LogSetPackets {
#[argh(positional)]
pub enabled: bool,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "neigh")]
/// commands for neighbor tables
pub struct Neigh {
#[argh(subcommand)]
pub neigh_cmd: NeighEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum NeighEnum {
Add(NeighAdd),
Clear(NeighClear),
Del(NeighDel),
List(NeighList),
Watch(NeighWatch),
Config(NeighConfig),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "add")]
/// adds an entry to the neighbor table
pub struct NeighAdd {
#[argh(positional)]
pub interface: u64,
#[argh(positional)]
pub ip: net_ext::IpAddress,
#[argh(positional)]
pub mac: net_ext::MacAddress,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "clear")]
/// removes all entries associated with a network interface from the neighbor table
pub struct NeighClear {
#[argh(positional)]
pub interface: u64,
#[argh(positional, from_str_fn(parse_ip_version_str))]
pub ip_version: net::IpVersion,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "list")]
/// lists neighbor table entries
pub struct NeighList {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "del")]
/// removes an entry from the neighbor table
pub struct NeighDel {
#[argh(positional)]
pub interface: u64,
#[argh(positional)]
pub ip: net_ext::IpAddress,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "watch")]
/// watches neighbor table entries for state changes
pub struct NeighWatch {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "config")]
/// commands for the Neighbor Unreachability Detection configuration
pub struct NeighConfig {
#[argh(subcommand)]
pub neigh_config_cmd: NeighConfigEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum NeighConfigEnum {
Get(NeighGetConfig),
Update(NeighUpdateConfig),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "get")]
/// returns the current NUD configuration options for the provided interface
pub struct NeighGetConfig {
#[argh(positional)]
pub interface: u64,
#[argh(positional, from_str_fn(parse_ip_version_str))]
pub ip_version: net::IpVersion,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "update")]
/// updates the current NUD configuration options for the provided interface
pub struct NeighUpdateConfig {
#[argh(positional)]
pub interface: u64,
#[argh(positional, from_str_fn(parse_ip_version_str))]
pub ip_version: net::IpVersion,
/// a base duration, in nanoseconds, for computing the random reachable
/// time
#[argh(option)]
pub base_reachable_time: Option<i64>,
/// learn `base_reachable_time` during runtime from the neighbor discovery
/// protocol, if supported
#[argh(option)]
pub learn_base_reachable_time: Option<bool>,
/// the minimum value of the random factor used for computing reachable
/// time
#[argh(option)]
pub min_random_factor: Option<f32>,
/// the maximum value of the random factor used for computing reachable
/// time
#[argh(option)]
pub max_random_factor: Option<f32>,
/// duration, in nanoseconds, between retransmissions of reachability
/// probes in the PROBE state
#[argh(option)]
pub retransmit_timer: Option<i64>,
/// learn `retransmit_timer` during runtime from the neighbor discovery
/// protocol, if supported
#[argh(option)]
pub learn_retransmit_timer: Option<bool>,
/// duration, in nanoseconds, to wait for a non-Neighbor-Discovery related
/// protocol to reconfirm reachability after entering the DELAY state
#[argh(option)]
pub delay_first_probe_time: Option<i64>,
/// the number of reachability probes to send before concluding negative
/// reachability and deleting the entry from the INCOMPLETE state
#[argh(option)]
pub max_multicast_probes: Option<u32>,
/// the number of reachability probes to send before concluding
/// retransmissions from within the PROBE state should cease and the entry
/// SHOULD be deleted
#[argh(option)]
pub max_unicast_probes: Option<u32>,
/// if the target address is an anycast address, the stack SHOULD delay
/// sending a response for a random time between 0 and this duration, in
/// nanoseconds
#[argh(option)]
pub max_anycast_delay_time: Option<i64>,
/// a node MAY send up to this amount of unsolicited reachability
/// confirmations messages to all-nodes multicast address when a node
/// determines its link-layer address has changed
#[argh(option)]
pub max_reachability_confirmations: Option<u32>,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "route")]
/// commands for routing tables
pub struct Route {
#[argh(subcommand)]
pub route_cmd: RouteEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum RouteEnum {
List(RouteList),
Add(RouteAdd),
Del(RouteDel),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "list")]
/// lists devices
pub struct RouteList {}
macro_rules! route_struct {
($ty_name:ident, $name:literal, $comment:expr) => {
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = $name)]
#[doc = $comment]
pub struct $ty_name {
#[argh(option)]
/// the network id of the destination network
pub destination: std::net::IpAddr,
#[argh(option)]
/// the netmask corresponding to destination
pub netmask: std::net::IpAddr,
#[argh(option)]
/// the ip address of the first hop router
pub gateway: Option<std::net::IpAddr>,
#[argh(option)]
/// the outgoing network interface id of the route
pub nicid: u32,
#[argh(option)]
/// the metric for the route
pub metric: u32,
}
impl Into<fidl_fuchsia_netstack::RouteTableEntry2> for $ty_name {
fn into(self) -> fidl_fuchsia_netstack::RouteTableEntry2 {
let Self { destination, netmask, gateway, nicid, metric } = self;
fidl_fuchsia_netstack::RouteTableEntry2 {
destination: fidl_fuchsia_net_ext::IpAddress(destination).into(),
netmask: fidl_fuchsia_net_ext::IpAddress(netmask).into(),
gateway: gateway
.map(|gateway| Box::new(fidl_fuchsia_net_ext::IpAddress(gateway).into())),
nicid,
metric,
}
}
}
};
}
// TODO(https://github.com/google/argh/issues/48): do this more sanely.
route_struct!(RouteAdd, "add", "adds a route to the route table");
route_struct!(RouteDel, "del", "deletes a route from the route table");
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "stat")]
/// commands for aggregates statistics
pub struct Stat {
#[argh(subcommand)]
pub stat_cmd: StatEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum StatEnum {
Show(StatShow),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "show")]
/// shows classified netstack stats
pub struct StatShow {}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "metric")]
/// commands for interface route metrics
pub struct Metric {
#[argh(subcommand)]
pub metric_cmd: MetricEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum MetricEnum {
Set(MetricSet),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "set")]
/// assigns a route metric to the network interface
pub struct MetricSet {
#[argh(positional)]
// NOTE: id is a u32 because fuchsia.netstack interfaces take u32 interface ids.
// TODO: change id to u64 once fuchsia.netstack is no longer in use.
pub id: u32,
#[argh(positional)]
pub metric: u32,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "dhcp")]
/// commands for an interfaces dhcp client
pub struct Dhcp {
#[argh(subcommand)]
pub dhcp_cmd: DhcpEnum,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand)]
pub enum DhcpEnum {
Start(DhcpStart),
Stop(DhcpStop),
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "start")]
/// starts a dhcp client on the interface
pub struct DhcpStart {
#[argh(positional)]
pub id: u32,
}
#[derive(FromArgs, Clone, Debug)]
#[argh(subcommand, name = "stop")]
/// stops the dhcp client on the interface
pub struct DhcpStop {
#[argh(positional)]
pub id: u32,
}