Skip to main content

sl4f_lib/wlan_policy/
commands.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::server::Facade;
6use crate::wlan_policy::facade::WlanPolicyFacade;
7use anyhow::{Error, format_err};
8use async_trait::async_trait;
9use fidl_fuchsia_wlan_policy as fidl_policy;
10use log::*;
11use serde_json::{Value, to_value};
12
13#[async_trait(?Send)]
14impl Facade for WlanPolicyFacade {
15    async fn handle_request(&self, method: String, args: Value) -> Result<Value, Error> {
16        match method.as_ref() {
17            "scan_for_networks" => {
18                info!(tag = "WlanPolicyFacade"; "performing scan for networks");
19                let result = self.scan_for_networks().await?;
20                to_value(result).map_err(|e| format_err!("error handling scan result: {}", e))
21            }
22            "connect" => {
23                let target_ssid = parse_target_ssid(&args)?;
24                let security_type = parse_security_type(&args)?;
25
26                info!(
27                    tag = "WlanPolicyFacade";
28                    "performing wlan connect to SSID: {:?}", target_ssid
29                );
30                let result = self.connect(target_ssid, security_type).await?;
31                to_value(result).map_err(|e| format_err!("error parsing connection result: {}", e))
32            }
33            "remove_network" => {
34                let target_ssid = parse_target_ssid(&args)?;
35                let security_type = parse_security_type(&args)?;
36                let target_pwd = parse_target_pwd(&args)?;
37
38                info!(tag = "WlanPolicyFacade"; "removing network with SSID: {:?}", target_ssid);
39                let result = self.remove_network(target_ssid, security_type, target_pwd).await?;
40                to_value(result)
41                    .map_err(|e| format_err!("error parsing remove network result: {}", e))
42            }
43            "start_client_connections" => {
44                info!(tag = "WlanPolicyFacade"; "attempting to start client connections");
45                let result = self.start_client_connections().await?;
46                to_value(result).map_err(|e| {
47                    format_err!("error handling start client connections result: {}", e)
48                })
49            }
50            "stop_client_connections" => {
51                info!(tag = "WlanPolicyFacade"; "attempting to stop client connections");
52                let result = self.stop_client_connections().await?;
53                to_value(result).map_err(|e| {
54                    format_err!("error handling stop client connections result: {}", e)
55                })
56            }
57            "save_network" => {
58                let target_ssid = parse_target_ssid(&args)?;
59                let security_type = parse_security_type(&args)?;
60                let target_pwd = parse_target_pwd(&args)?;
61
62                info!(tag = "WlanPolicyFacade"; "saving network with SSID: {:?}", target_ssid);
63                let result = self.save_network(target_ssid, security_type, target_pwd).await?;
64                to_value(result)
65                    .map_err(|e| format_err!("error parsing save network result: {}", e))
66            }
67            "get_saved_networks" => {
68                info!(tag = "WlanPolicyFacade"; "attempting to get saved networks");
69                let result = self.get_saved_networks_json().await?;
70                to_value(result)
71                    .map_err(|e| format_err!("error handling get saved networks result: {}", e))
72            }
73            "create_client_controller" => {
74                info!(tag = "WlanPolicyFacade"; "initializing client controller");
75                let result = self.create_client_controller().await?;
76                to_value(result)
77                    .map_err(|e| format_err!("error initializing client controller: {}", e))
78            }
79            "drop_client_controller" => {
80                info!(tag = "WlanPolicyFacade"; "dropping client controller");
81                let result = self.drop_client_controller();
82                to_value(result).map_err(|e| format_err!("error dropping client controller: {}", e))
83            }
84            "remove_all_networks" => {
85                info!(tag = "WlanPolicyFacade"; "Removing all saved client network configs");
86                let result = self.remove_all_networks().await?;
87                to_value(result)
88                    .map_err(|e| format_err!("error removing all saved networks: {}", e))
89            }
90            "get_update" => {
91                info!(tag = "WlanPolicyFacade"; "getting client update");
92                let result = self.get_update().await?;
93                to_value(result).map_err(|e| format_err!("error handling listener update: {}", e))
94            }
95            "set_new_update_listener" => {
96                info!(tag = "WlanPolicyFacade"; "initializing new update listener");
97                let result = self.set_new_listener()?;
98                to_value(result)
99                    .map_err(|e| format_err!("error initializing new update listener: {}", e))
100            }
101            _ => return Err(format_err!("unsupported command!")),
102        }
103    }
104}
105
106fn parse_target_ssid(args: &Value) -> Result<Vec<u8>, Error> {
107    args.get("target_ssid")
108        .and_then(|ssid| ssid.as_str().map(|ssid| ssid.as_bytes().to_vec()))
109        .ok_or_else(|| format_err!("Please provide a target ssid"))
110}
111
112/// In ACTS tests we will require a security type is specified for a call that uses a security
113/// type; none specified will not default to a none security type.
114fn parse_security_type(args: &Value) -> Result<fidl_policy::SecurityType, Error> {
115    let security_type = match args.get("security_type") {
116        Some(Value::String(security)) => security.as_bytes().to_vec(),
117        Some(value) => {
118            info!(tag = "WlanFacade"; "Please check provided security type, must be String");
119            bail!("provided security type arg is not a string, cannot parse {}", value);
120        }
121        None => {
122            info!(tag = "WlanFacade"; "Please check provided security type, none found");
123            bail!("no security type is provided");
124        }
125    };
126
127    // Parse network ID to connect to. The string is made lower case upstream in the pipeline.
128    match std::str::from_utf8(&security_type)? {
129        "none" => Ok(fidl_policy::SecurityType::None),
130        "wep" => Ok(fidl_policy::SecurityType::Wep),
131        "wpa" => Ok(fidl_policy::SecurityType::Wpa),
132        "wpa2" => Ok(fidl_policy::SecurityType::Wpa2),
133        "wpa3" => Ok(fidl_policy::SecurityType::Wpa3),
134        _ => Err(format_err!("failed to parse security type (None, WEP, WPA, WPA2, or WPA3")),
135    }
136}
137
138/// Parse the credential argument. The credential argument must be a string. No credential (for an
139/// open network) must be indicated by an empty string. Tests may omit the password argument, and
140/// if so an empty string will be provided as a default value as an argument. Tests do not need
141/// to specify the type of credential; it will be inferred by the length.
142/// PSK format must be string representation of hexadecimal, not the 32 bytes representation.
143/// PSK will be distinguished from password by the length of password, if 64 bytes it will be PSK.
144fn parse_target_pwd(args: &Value) -> Result<fidl_policy::Credential, Error> {
145    let target_pwd = match args.get("target_pwd") {
146        Some(Value::String(pwd)) => pwd.as_bytes().to_vec(),
147        Some(value) => {
148            info!(tag = "WlanFacade"; "Please check provided credential, must be String");
149            bail!("provided credential is not a string, cannot parse {}", value);
150        }
151        None => {
152            info!(tag = "WlanFacade"; "Please check provided credential, none provided");
153            bail!("no credential argument provided");
154        }
155    };
156
157    const PSK_LEN: usize = 64;
158    let credential = match target_pwd.len() {
159        0 => fidl_policy::Credential::None(fidl_policy::Empty),
160        PSK_LEN => {
161            let psk = hex::decode(target_pwd).map_err(|e| {
162                info!(
163                    tag = "WlanFacade";
164                    "Please check provided credential, PSK must be valid hexadecimal string"
165                );
166                format_err!("provided credential length matches PSK, failed to decode: {:?}", e)
167            })?;
168            fidl_policy::Credential::Psk(psk)
169        }
170        _ => fidl_policy::Credential::Password(target_pwd),
171    };
172    Ok(credential)
173}