| // Copyright 2019 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. |
| |
| //! The special-purpose event loop used by the network manager. |
| //! |
| //! This event loop takes in events from Admin and State FIDL, |
| //! and implements handlers for FIDL calls. |
| //! |
| //! This is implemented with a single mpsc queue for all event types - `EventLoop` holds the |
| //! consumer, and any event handling that requires state within `EventLoop` holds a producer, |
| //! allowing it to delegate work to the `EventLoop` by sending a message. In this documentation, we |
| //! call anything that holds a producer a "worker". |
| //! |
| //! Having a single queue for all of the message types is beneficial, since in guarantees a FIFO |
| //! ordering for all messages - whichever messages arrive first, will be handled first. |
| //! |
| //! We'll look at each type of message, to see how each one is handled - starting with FIDL |
| //! messages, since they can be thought of as the entrypoint for the whole loop (as nothing happens |
| //! until a FIDL call is made). |
| //! |
| //! # FIDL Worker |
| //! |
| //! The FIDL part of the event loop implements the fuchsia.router.config Admin and State |
| //! interfaces. The type of the event loop message for a FIDL call is |
| //! simply the generated FIDL type. When the event loop starts up, we use `fuchsia_app` to start a |
| //! FIDL server that simply sends all of the events it receives to the event loop (via the sender |
| //! end of the mpsc queue). When `EventLoop` receives this message, it calls the |
| //! `handle_fidl_router_admin_request` or `handle_fidl_router_state_request` method, which, |
| //! depending on what the request is, either: |
| //! |
| //! * Responds with the requested information. |
| //! * Modifies the router state byt accessinc netcfg. |
| //! * Updates local state. |
| |
| use fidl_fuchsia_net as fnet; |
| use fidl_fuchsia_net_name as fnet_name; |
| use fidl_fuchsia_router_config::{ |
| Id, Lif, Port, RouterAdminRequest, RouterStateGetPortsResponder, RouterStateRequest, |
| SecurityFeatures, |
| }; |
| use fuchsia_component::server::ServiceFs; |
| |
| use anyhow::{Context as _, Error}; |
| use dns_server_watcher::{DnsServers, DnsServersUpdateSource, DEFAULT_DNS_PORT}; |
| use futures::future; |
| use futures::stream::{self, StreamExt as _, TryStreamExt as _}; |
| use network_manager_core::{ |
| hal::NetCfg, lifmgr::LIFType, packet_filter::PacketFilter, portmgr::PortId, DeviceState, |
| }; |
| |
| use crate::fidl_worker::IncomingFidlRequestStream; |
| |
| macro_rules! router_error { |
| ($code:ident, $desc:expr) => { |
| Some(&mut fidl_fuchsia_router_config::Error { |
| code: fidl_fuchsia_router_config::ErrorCode::$code, |
| description: $desc, |
| }) |
| }; |
| } |
| |
| macro_rules! not_supported { |
| () => { |
| router_error!(NotSupported, None) |
| }; |
| } |
| macro_rules! not_found { |
| () => { |
| router_error!(NotFound, None) |
| }; |
| } |
| macro_rules! internal_error { |
| ($s:expr) => { |
| router_error!(Internal, Some($s.to_string())) |
| }; |
| } |
| |
| fn dns_sockaddr_from_ip(ip: fnet::IpAddress) -> fnet::SocketAddress { |
| match ip { |
| fnet::IpAddress::Ipv4(addr) => fnet::SocketAddress::Ipv4(fnet::Ipv4SocketAddress { |
| address: addr, |
| port: DEFAULT_DNS_PORT, |
| }), |
| fnet::IpAddress::Ipv6(addr) => fnet::SocketAddress::Ipv6(fnet::Ipv6SocketAddress { |
| address: addr, |
| port: DEFAULT_DNS_PORT, |
| zone_index: 0, |
| }), |
| } |
| } |
| |
| /// The event loop. |
| pub struct EventLoop { |
| device: DeviceState, |
| dns_servers: DnsServers, |
| } |
| |
| impl EventLoop { |
| pub fn new() -> Result<Self, Error> { |
| let netcfg = NetCfg::new()?; |
| let packet_filter = PacketFilter::start().context("failed to start packet filter")?; |
| let device = DeviceState::new(netcfg, packet_filter); |
| Ok(EventLoop { device, dns_servers: Default::default() }) |
| } |
| |
| pub async fn run(mut self) -> Result<(), Error> { |
| if let Err(e) = self.device.load_config().await { |
| // TODO(cgibson): Kick off some sort of recovery process here: Prompt the user to |
| // download a recovery app, set a static IP on the first interface and set everything |
| // else down, restructure packet filter rules, etc. |
| error!("Failed to load a device config: {}", e); |
| } |
| self.device.setup_services().await.context("setup_services")?; |
| self.device.populate_state().await.context("populate_state")?; |
| |
| let (stack_stream, netstack_stream) = self.device.take_event_streams(); |
| let stack_stream = stack_stream.map(|r| r.context("Stack event stream")).fuse(); |
| let netstack_stream = netstack_stream.map(|r| r.context("Netstack event stream")).fuse(); |
| let netstack_dns_stream = dns_server_watcher::new_dns_server_stream( |
| DnsServersUpdateSource::Netstack, |
| self.device |
| .get_netstack_dns_server_watcher() |
| .context("failed to get DNS server watcher")?, |
| ) |
| .fuse(); |
| let oir_stream = crate::oir_worker::new_stream() |
| .await |
| .context("starting OIR")? |
| .map(|r| r.context("OIR event stream")) |
| .fuse(); |
| let mut fs = ServiceFs::new_local(); |
| let fidl_server_stream = crate::fidl_worker::new_stream(&mut fs) |
| .context("setting up FIDL services")? |
| .then(futures::future::ok::<_, anyhow::Error>); |
| // Make sure errors encountered when setting up overnet services do not cause |
| // NetworkManager to exit as overnet may not be available on all builds. |
| let overnet_stream = match crate::overnet_worker::new_stream().await { |
| Err(e) => { |
| error!("error setting up overnet services: {}", e); |
| // We use a stream that is always pending so that the loop below may |
| // assume that `overnet_stream` is not expected to end (which is the |
| // case when we successfully setup and publish overnet services). |
| future::Either::Left(stream::pending()) |
| } |
| Ok(o) => future::Either::Right(o.map(|r| r.context("overnet service request stream"))), |
| }; |
| let fidl_req_stream = stream::select(fidl_server_stream, overnet_stream).fuse(); |
| let mut router_admin_streams = stream::SelectAll::new(); |
| let mut router_state_streams = stream::SelectAll::new(); |
| |
| futures::pin_mut!( |
| stack_stream, |
| netstack_stream, |
| netstack_dns_stream, |
| oir_stream, |
| fidl_req_stream |
| ); |
| |
| loop { |
| // Currently, if any of the workers encounters an error, the event loop |
| // will return with the worker's error immediately. |
| // TODO(fxbug.dev/52740): Gracefully handle worker errors. |
| let () = futures::select! { |
| stack_res = stack_stream.try_next() => { |
| let event = stack_res?.ok_or(anyhow::anyhow!("Stack event stream unexpectedly ended"))?; |
| self.handle_stack_event(event).await |
| } |
| netstack_res = netstack_stream.try_next() => { |
| let event = netstack_res?.ok_or(anyhow::anyhow!("Netstack event stream unexpectedly ended"))?; |
| self.handle_netstack_event(event).await |
| } |
| netstack_dns_res = netstack_dns_stream.next() => { |
| let (source, res) = netstack_dns_res.ok_or(anyhow::anyhow!("Netstack DNS Server watcher stream unexpectedly ended"))?; |
| self.handle_dns_server_watcher_event(source, res.context("error getting next DNS server event from netstack")?).await |
| } |
| oir_res = oir_stream.try_next() => { |
| let event = oir_res?.ok_or(anyhow::anyhow!("OIR stream unexpectedly ended"))?; |
| self.handle_oir_event(event).await |
| } |
| fidl_req_res = fidl_req_stream.try_next() => { |
| let req = fidl_req_res?.ok_or(anyhow::anyhow!("FIDL service request stream unexpectedly ended"))?; |
| match req { |
| IncomingFidlRequestStream::RouterAdmin(r) => router_admin_streams.push(r), |
| IncomingFidlRequestStream::RouterState(r) => router_state_streams.push(r), |
| } |
| } |
| router_admin_req_res = router_admin_streams.try_next() => { |
| // We may receive `None` just once if there are no longer any active streams |
| // in the `Stream` set. This is expected for the initial state, or after the |
| // streams are run to completion. Note, the `Stream` set will start to yield |
| // values again (as they become available) once a new `Stream` is added. |
| if let Some(req) = router_admin_req_res? { |
| self.handle_fidl_router_admin_request(req).await |
| } |
| } |
| router_state_req_res = router_state_streams.try_next() => { |
| // We may receive `None` just once if there are no longer any active streams |
| // in the `Stream` set. This is expected for the initial state, or after the |
| // streams are run to completion. Note, the `Stream` set will start to yield |
| // values again (as they become available) once a new `Stream` is added. |
| if let Some(req) = router_state_req_res? { |
| self.handle_fidl_router_state_request(req).await |
| } |
| } |
| complete => break, |
| }; |
| } |
| |
| Ok(()) |
| } |
| |
| async fn handle_dns_server_watcher_event( |
| &mut self, |
| source: DnsServersUpdateSource, |
| servers: Vec<fnet_name::DnsServer_>, |
| ) { |
| trace!("got DNS server event from source = {:?} with servers = {:?}", source, servers); |
| let () = self.dns_servers.set_servers_from_source(source, servers); |
| let () = self |
| .device |
| .set_dns_resolvers(self.dns_servers.consolidated()) |
| .await |
| .map(|_: network_manager_core::ElementId| ()) |
| .unwrap_or_else(|err| warn!("error setting dns servers: {:?}", err)); |
| } |
| |
| async fn handle_stack_event(&mut self, event: fidl_fuchsia_net_stack::StackEvent) { |
| self.device |
| .update_state_for_stack_event(event) |
| .await |
| .unwrap_or_else(|err| warn!("error updating state: {:?}", err)); |
| } |
| |
| async fn handle_netstack_event(&mut self, event: fidl_fuchsia_netstack::NetstackEvent) { |
| self.device |
| .update_state_for_netstack_event(event) |
| .await |
| .unwrap_or_else(|err| warn!("error updating state: {:?}", err)); |
| } |
| |
| async fn handle_oir_event(&mut self, event: network_manager_core::oir::OIRInfo) { |
| self.device |
| .oir_event(event) |
| .await |
| .unwrap_or_else(|err| warn!("error processing oir event: {:?}", err)); |
| } |
| |
| async fn handle_fidl_router_admin_request(&mut self, req: RouterAdminRequest) { |
| match req { |
| RouterAdminRequest::CreateWan { name, vlan, ports, responder } => { |
| let r = self |
| .fidl_create_lif( |
| LIFType::WAN, |
| name, |
| vlan, |
| ports.iter().map(|x| PortId::from(u64::from(*x))).collect(), |
| ) |
| .await; |
| match r { |
| Ok(mut id) => responder.send(Some(&mut id), None), |
| Err(mut e) => responder.send(None, Some(&mut e)), |
| } |
| } |
| RouterAdminRequest::CreateLan { name, vlan, ports, responder } => { |
| let r = self |
| .fidl_create_lif( |
| LIFType::LAN, |
| name, |
| vlan, |
| ports.iter().map(|x| PortId::from(u64::from(*x))).collect(), |
| ) |
| .await; |
| match r { |
| Ok(mut id) => responder.send(Some(&mut id), None), |
| Err(mut e) => responder.send(None, Some(&mut e)), |
| } |
| } |
| RouterAdminRequest::RemoveWan { wan_id, responder } => { |
| let mut r = self.fidl_delete_lif(wan_id).await; |
| responder.send(r.as_mut()).or_else(|e| { |
| error!("Error sending response: {:?}", e); |
| Err(e) |
| }) |
| } |
| RouterAdminRequest::RemoveLan { lan_id, responder } => { |
| let mut r = self.fidl_delete_lif(lan_id).await; |
| responder.send(r.as_mut()).or_else(|e| { |
| error!("Error sending response: {:?}", e); |
| Err(e) |
| }) |
| } |
| RouterAdminRequest::SetWanProperties { wan_id, properties, responder } => { |
| let properties = fidl_fuchsia_router_config::LifProperties::Wan(properties); |
| if self |
| .device |
| .update_lif_properties_fidl(u128::from_ne_bytes(wan_id.uuid), &properties) |
| .await |
| .is_err() |
| { |
| warn!("WAN {:?} found but failed to update properties", wan_id); |
| responder.send(not_found!()) |
| } else { |
| info!("WAN properties updated"); |
| responder.send(None) |
| } |
| } |
| RouterAdminRequest::SetLanProperties { lan_id, properties, responder } => { |
| let properties = fidl_fuchsia_router_config::LifProperties::Lan(properties); |
| if self |
| .device |
| .update_lif_properties_fidl(u128::from_ne_bytes(lan_id.uuid), &properties) |
| .await |
| .is_err() |
| { |
| warn!("failed to update LAN properties"); |
| responder.send(not_found!()) |
| } else { |
| info!("LAN properties updated"); |
| responder.send(None) |
| } |
| } |
| RouterAdminRequest::SetDhcpServerOptions { lan_id, options, responder } => { |
| info!("{:?}, {:?}", lan_id, options); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetDhcpAddressPool { lan_id, pool, responder } => { |
| info!("{:?}, {:?}", lan_id, pool); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetDhcpReservation { lan_id, reservation, responder } => { |
| info!("{:?}, {:?}", lan_id, reservation); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeleteDhcpReservation { reservation_id, responder } => { |
| info!("{:?}", reservation_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetDnsResolver { config, responder } => { |
| info!("{:?}", config); |
| match self |
| .device |
| .set_dns_resolvers( |
| config.search.servers.into_iter().map(dns_sockaddr_from_ip).collect(), |
| ) |
| .await |
| { |
| Ok(i) => responder.send( |
| Some(&mut Id { uuid: i.uuid().to_ne_bytes(), version: i.version() }), |
| None, |
| ), |
| Err(e) => responder.send(None, internal_error!(e.to_string())), |
| } |
| } |
| RouterAdminRequest::SetDnsForwarder { config, responder } => { |
| info!("{:?}", config); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::AddDnsEntry { entry, responder } => { |
| info!("{:?}", entry); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeleteDnsEntry { entry_id, responder } => { |
| info!("{:?}", entry_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetRoute { route, responder } => { |
| info!("{:?}", route); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::UpdateRouteMetric { route_id, metric, responder } => { |
| info!("{:?} {:?}", route_id, metric); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::DeleteRoute { route_id, responder } => { |
| info!("{:?}", route_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetSecurityFeatures { features, responder } => { |
| info!("Updating SecurityFeatures: {:?}", features); |
| match self.update_security_features(&features).await { |
| Ok(_) => responder.send(None), |
| Err(e) => responder.send(internal_error!(e.to_string())), |
| } |
| } |
| RouterAdminRequest::SetPortForward { rule, responder } => { |
| info!("{:?}", rule); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeletePortForward { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetPortTrigger { rule, responder } => { |
| info!("{:?}", rule); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeletePortTrigger { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetFilter { rule, responder } => { |
| let r = self |
| .device |
| // TODO(fxbug.dev/45024): The Router Config FIDL API doesn't have a way to provide a |
| // specific interface identifier. |
| .set_filter_on_interface(&rule, 0u32) |
| .await |
| .context("Error installing new packet filter on all interfaces"); |
| match r { |
| Ok(()) => responder.send(None, None), |
| Err(e) => responder.send(None, internal_error!(e.to_string())), |
| } |
| } |
| RouterAdminRequest::DeleteFilter { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| let r = self |
| .device |
| .delete_filter(rule_id) |
| .await |
| .context("Error deleting packet filter rule"); |
| match r { |
| Ok(()) => responder.send(None), |
| Err(e) => responder.send(internal_error!(e.to_string())), |
| } |
| } |
| RouterAdminRequest::SetIpv6PinHole { rule, responder } => { |
| info!("{:?}", rule); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeleteIpv6PinHole { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetDmzHost { rule, responder } => { |
| info!("{:?}", rule); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeleteDmzHost { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(not_supported!()) |
| } |
| RouterAdminRequest::SetSystemConfig { config, responder } => { |
| info!("{:?}", config); |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::CreateWlanNetwork { responder, .. } => { |
| // TODO(guzt): implement |
| responder.send(None, not_supported!()) |
| } |
| RouterAdminRequest::DeleteWlanNetwork { responder, .. } => { |
| // TODO(guzt): implement |
| responder.send(not_supported!()) |
| } |
| } |
| .unwrap_or_else(|e| error!("Error sending response {}", e)) |
| } |
| |
| async fn fidl_create_lif( |
| &mut self, |
| lif_type: LIFType, |
| name: String, |
| vlan: u16, |
| ports: Vec<PortId>, |
| ) -> Result<Id, fidl_fuchsia_router_config::Error> { |
| let lif = self.device.create_lif(lif_type, name, Some(vlan), &ports).await; |
| match lif { |
| Err(e) => { |
| error!("Error creating lif {:?}", e); |
| Err(fidl_fuchsia_router_config::Error { |
| code: fidl_fuchsia_router_config::ErrorCode::AlreadyExists, |
| description: None, |
| }) |
| } |
| Ok(l) => { |
| let i = l.id(); |
| Ok(Id { uuid: i.uuid().to_ne_bytes(), version: i.version() }) |
| } |
| } |
| } |
| |
| async fn fidl_delete_lif(&mut self, id: Id) -> Option<fidl_fuchsia_router_config::Error> { |
| let lif = self.device.delete_lif(u128::from_ne_bytes(id.uuid)).await; |
| match lif { |
| Err(e) => { |
| error!("Error deleting lif {:?}", e); |
| Some(fidl_fuchsia_router_config::Error { |
| code: fidl_fuchsia_router_config::ErrorCode::NotFound, |
| description: None, |
| }) |
| } |
| Ok(()) => None, |
| } |
| } |
| |
| async fn update_security_features( |
| &mut self, |
| security_features: &SecurityFeatures, |
| ) -> Result<(), Error> { |
| if let Some(nat) = security_features.nat { |
| if nat { |
| self.device.enable_nat(); |
| } else { |
| self.device.disable_nat(); |
| } |
| } |
| // TODO(cgibson): Handle additional SecurityFeatures. |
| Ok(()) |
| } |
| |
| async fn handle_fidl_router_state_request(&mut self, req: RouterStateRequest) { |
| match req { |
| RouterStateRequest::GetWanPorts { wan_id, responder } => { |
| let lif = self.device.lif(u128::from_ne_bytes(wan_id.uuid)); |
| match lif { |
| None => { |
| warn!("WAN {:?} not found", wan_id); |
| responder.send(&[], not_found!()) |
| } |
| Some(l) => { |
| responder.send(&l.ports().map(|p| p.to_u32()).collect::<Vec<_>>(), None) |
| } |
| } |
| } |
| RouterStateRequest::GetLanPorts { lan_id, responder } => { |
| let lif = self.device.lif(u128::from_ne_bytes(lan_id.uuid)); |
| match lif { |
| None => { |
| warn!("LAN {:?} not found", lan_id); |
| responder.send(&[], not_found!()) |
| } |
| Some(l) => { |
| responder.send(&l.ports().map(|p| p.to_u32()).collect::<Vec<_>>(), None) |
| } |
| } |
| } |
| RouterStateRequest::GetWan { wan_id, responder } => { |
| let lif = self.device.lif(u128::from_ne_bytes(wan_id.uuid)); |
| info!("lifs {:?}", lif); |
| match lif { |
| None => { |
| warn!("WAN {:?} not found", wan_id); |
| responder.send( |
| fidl_fuchsia_router_config::Lif { |
| element: None, |
| name: None, |
| port_ids: None, |
| properties: None, |
| vlan: None, |
| type_: None, |
| ..fidl_fuchsia_router_config::Lif::EMPTY |
| }, |
| not_found!(), |
| ) |
| } |
| Some(l) => { |
| let ll = l.into(); |
| responder.send(ll, None) |
| } |
| } |
| } |
| RouterStateRequest::GetLan { lan_id, responder } => { |
| let lif = self.device.lif(u128::from_ne_bytes(lan_id.uuid)); |
| match lif { |
| None => { |
| warn!("LAN {:?} not found", lan_id); |
| responder.send( |
| fidl_fuchsia_router_config::Lif { |
| element: None, |
| name: None, |
| port_ids: None, |
| properties: None, |
| vlan: None, |
| type_: None, |
| ..fidl_fuchsia_router_config::Lif::EMPTY |
| }, |
| not_found!(), |
| ) |
| } |
| Some(l) => { |
| let ll = l.into(); |
| responder.send(ll, None) |
| } |
| } |
| } |
| RouterStateRequest::GetWans { responder } => { |
| let lifs: Vec<Lif> = self.device.lifs(LIFType::WAN).map(|l| l.into()).collect(); |
| info!("result: {:?} ", lifs); |
| responder.send(&mut lifs.into_iter()) |
| } |
| RouterStateRequest::GetLans { responder } => { |
| let lifs: Vec<Lif> = self.device.lifs(LIFType::LAN).map(|l| l.into()).collect(); |
| info!("result: {:?} ", lifs); |
| responder.send(&mut lifs.into_iter()) |
| } |
| RouterStateRequest::GetWanProperties { wan_id, responder } => { |
| info!("{:?}", wan_id); |
| let properties = fidl_fuchsia_router_config::WanProperties { |
| connection_type: None, |
| connection_parameters: None, |
| address_method: None, |
| address_v4: None, |
| gateway_v4: None, |
| connection_v6_mode: None, |
| address_v6: None, |
| gateway_v6: None, |
| hostname: None, |
| clone_mac: None, |
| mtu: None, |
| enable: None, |
| metric: None, |
| ..fidl_fuchsia_router_config::WanProperties::EMPTY |
| }; |
| responder.send(properties, not_supported!()) |
| } |
| RouterStateRequest::GetLanProperties { lan_id, responder } => { |
| info!("{:?}", lan_id); |
| let properties = fidl_fuchsia_router_config::LanProperties { |
| address_v4: None, |
| enable_dhcp_server: None, |
| dhcp_config: None, |
| address_v6: None, |
| enable_dns_forwarder: None, |
| enable: None, |
| ..fidl_fuchsia_router_config::LanProperties::EMPTY |
| }; |
| |
| responder.send(properties, not_supported!()) |
| } |
| RouterStateRequest::GetDhcpConfig { lan_id, responder } => { |
| info!("{:?}", lan_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetDnsResolver { responder } => { |
| let mut resolver = self.device.get_dns_resolver().await; |
| responder.send(&mut resolver) |
| } |
| RouterStateRequest::GetDnsForwarder { responder } => { |
| let config = fidl_fuchsia_router_config::DnsForwarderConfig { |
| element: Id { |
| uuid: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], |
| version: 0, |
| }, |
| search: fidl_fuchsia_router_config::DnsSearch { |
| domain_name: None, |
| servers: vec![], |
| }, |
| }; |
| let mut forwarder = fidl_fuchsia_router_config::DnsForwarder { |
| config, |
| interfaces: vec![], |
| resolver: vec![], |
| }; |
| responder.send(&mut forwarder) |
| } |
| RouterStateRequest::GetRoutes { responder } => responder.send(&mut [].iter_mut()), |
| RouterStateRequest::GetRoute { route_id, responder } => { |
| info!("{:?}", route_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetSecurityFeatures { responder } => { |
| let security_features = fidl_fuchsia_router_config::SecurityFeatures { |
| allow_multicast: None, |
| drop_icmp_echo: None, |
| firewall: None, |
| h323_passthru: None, |
| ipsec_passthru: None, |
| l2_tp_passthru: None, |
| nat: Some(self.device.is_nat_enabled()), |
| pptp_passthru: None, |
| rtsp_passthru: None, |
| sip_passthru: None, |
| upnp: None, |
| v6_firewall: None, |
| ..fidl_fuchsia_router_config::SecurityFeatures::EMPTY |
| }; |
| responder.send(security_features) |
| } |
| RouterStateRequest::GetPortForwards { responder } => responder.send(&mut [].iter_mut()), |
| RouterStateRequest::GetPortForward { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetPorts { responder } => { |
| self.fidl_get_ports(responder).await; |
| Ok(()) |
| } |
| RouterStateRequest::GetPort { port_id, responder } => { |
| info!("{:?}", port_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetPortTrigger { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetPortTriggers { responder } => responder.send(&mut [].iter_mut()), |
| RouterStateRequest::GetFilter { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetFilters { responder } => { |
| let result = self.device.get_filters().await.context("Error getting filters"); |
| let mut filter_rules = Vec::new(); |
| match result { |
| Ok(f) => { |
| filter_rules = f.into_iter().collect(); |
| info!("Filter rules returned: {:?}", filter_rules.len()); |
| } |
| Err(e) => error!("Failed parsing filter rules: {}", e), |
| } |
| responder.send(&mut filter_rules.iter_mut()) |
| } |
| RouterStateRequest::GetIpv6PinHole { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetIpv6PinHoles { responder } => responder.send(&mut [].iter_mut()), |
| RouterStateRequest::GetDmzHost { rule_id, responder } => { |
| info!("{:?}", rule_id); |
| responder.send(None, not_supported!()) |
| } |
| RouterStateRequest::GetSystemConfig { responder } => { |
| let config = fidl_fuchsia_router_config::SystemConfig { |
| element: None, |
| timezone: None, |
| daylight_savings_time_enabled: None, |
| leds_enabled: None, |
| hostname: None, |
| ..fidl_fuchsia_router_config::SystemConfig::EMPTY |
| }; |
| responder.send(config) |
| } |
| RouterStateRequest::GetDevice { responder } => { |
| let device = fidl_fuchsia_router_config::Device { |
| version: None, |
| topology: None, |
| config: None, |
| ..fidl_fuchsia_router_config::Device::EMPTY |
| }; |
| responder.send(device) |
| } |
| RouterStateRequest::GetWlanNetworks { responder } => { |
| responder.send(&mut vec![].into_iter()) |
| } |
| RouterStateRequest::GetRadios { responder } => responder.send(&mut vec![].into_iter()), |
| } |
| .unwrap_or_else(|e| error!("Error sending response {}", e)) |
| } |
| |
| async fn fidl_get_ports(&mut self, responder: RouterStateGetPortsResponder) { |
| let ps = self.device.ports(); |
| let mut ports: Vec<Port> = ps |
| .map(|p| Port { |
| element: Id { uuid: p.e_id.uuid().to_ne_bytes(), version: p.e_id.version() }, |
| id: p.port_id.to_u32(), |
| path: p.path.clone(), |
| }) |
| .collect(); |
| responder.send(&mut ports.iter_mut()).context("Error sending a response").unwrap(); |
| } |
| } |