/// <summary>
        /// Manage the given network interface via M552
        /// </summary>
        /// <param name="index">Index of the network interface</param>
        /// <param name="pParam">P parameter</param>
        /// <param name="sParam">S parameter</param>
        /// <returns>Configuration result</returns>
        public static async Task <Message> SetConfig(int index, CodeParameter pParam, CodeParameter sParam)
        {
            NetworkInterface iface  = Get(index);
            StringBuilder    result = new();

            if (iface.Name.StartsWith('w'))
            {
                // WiFi interface
                if (sParam == null)
                {
                    // Report the status only if no valid S parameter is given
                    await Report(result, iface, index);
                }
                else if (sParam <= 0 || sParam > 2)
                {
                    // Disable WiFi services
                    result.AppendLine(await AccessPoint.Stop());
                    result.AppendLine(await WPA.Stop());

                    // Disable WiFi adapter
                    string linkResult = await Command.Execute("/usr/sbin/ip", $"link set {iface.Name} down");

                    result.AppendLine(linkResult);
                }
                else if (sParam == 1)
                {
                    // Is there a wpa_supplicant.conf?
                    if (!File.Exists("/etc/wpa_supplicant/wpa_supplicant.conf"))
                    {
                        return(new Message(MessageType.Error, "No WiFi configuration found, use M587 to configure at least one SSID"));
                    }

                    // No longer in AP mode
                    result.AppendLine(await AccessPoint.Stop());

                    // Disable the adapter
                    string disableResult = await Command.Execute("/usr/sbin/ip", $"link set {iface.Name} down");

                    result.AppendLine(disableResult);

                    // Start station mode
                    result.AppendLine(await WPA.Start());

                    // Enable the adapter again
                    string enableResult = await Command.Execute("/usr/sbin/ip", $"link set {iface.Name} up");

                    result.AppendLine(enableResult);

                    // Connect to the given SSID (if applicable)
                    if (pParam != null)
                    {
                        // Find the network index
                        string networkList = await Command.Execute("/usr/sbin/wpa_cli", "list_networks");

                        Regex ssidRegex = new($"^(\\d+)\\s+{Regex.Escape(sParam)}\\W", RegexOptions.IgnoreCase);

                        int networkIndex = -1;
                        using (StringReader reader = new(networkList))
                        {
                            do
                            {
                                string line = await reader.ReadLineAsync();

                                if (line == null)
                                {
                                    break;
                                }

                                Match match = ssidRegex.Match(line);
                                if (match.Success)
                                {
                                    networkIndex = int.Parse(match.Groups[1].Value);
                                    break;
                                }
                            }while (!Program.CancellationToken.IsCancellationRequested);
                        }
                        if (networkIndex == -1)
                        {
                            return(new Message(MessageType.Error, "SSID could not be found, use M587 to configure it first"));
                        }

                        // Select it
                        string selectResult = await Command.Execute("/usr/sbin/wpa_cli", $"-i {iface.Name} select_network {networkIndex}");

                        if (selectResult.Trim() != "OK")
                        {
                            result.AppendLine(selectResult);
                        }
                    }
                    // else wpa_supplicant will connect to the next available network
                }
                else if (sParam == 2)
                {
                    // Are the required config files present?
                    if (!File.Exists("/etc/hostapd/wlan0.conf"))
                    {
                        return(new Message(MessageType.Error, "No hostapd configuration found, use M589 to configure the access point first"));
                    }
                    if (!File.Exists("/etc/dnsmasq.conf"))
                    {
                        return(new Message(MessageType.Error, "No dnsmasq configuration found, use M589 to configure the access point first"));
                    }

                    // Is there at least one DHCP profile for AP mode?
                    if (!await DHCP.IsAPConfigured())
                    {
                        return(new Message(MessageType.Error, "No access point configuration found. Use M587 to configure it first"));
                    }

                    // No longer in station mode
                    result.AppendLine(await WPA.Stop());

                    // Disable the adapter
                    string disableResult = await Command.Execute("/usr/sbin/ip", $"link set {iface.Name} down");

                    result.AppendLine(disableResult);

                    // Start AP mode. This will enable the adapter too
                    result.AppendLine(await AccessPoint.Start());
                }
            }
            else
            {
                // Ethernet interface
                if (pParam != null)
                {
                    // Set IP address
                    IPAddress ip        = IPAddress.Parse(pParam);
                    string    setResult = await DHCP.SetIPAddress(iface.Name, ip, null, null, null);

                    result.AppendLine(setResult);
                }

                if (sParam != null && (iface.OperationalStatus != OperationalStatus.Up) != sParam)
                {
                    // Enable or disable the adapter if required
                    result.AppendLine(await Command.Execute("/usr/sbin/ip", $"link set {iface.Name} {(sParam ? "up" : "down")}"));
                }
            }
            return(new Message(MessageType.Success, result.ToString().Trim()));
        }
Exemple #2
0
        /// <summary>
        /// Configure access point mode
        /// </summary>
        /// <param name="ssid">SSID to use</param>
        /// <param name="psk">Password to use</param>
        /// <param name="ipAddress">IP address</param>
        /// <param name="channel">Optional channel number</param>
        /// <returns></returns>
        public static async Task <Message> Configure(string ssid, string psk, IPAddress ipAddress, int channel)
        {
            string countryCode = await WPA.GetCountryCode();

            if (string.IsNullOrWhiteSpace(countryCode))
            {
                return(new Message(MessageType.Error, "Cannot configure access point because no country code has been set. Use M587 C to set it first"));
            }

            if (ssid == "*")
            {
                // Delete configuration files again
                bool fileDeleted = false;
                if (File.Exists("/etc/hostapd/wlan0.conf"))
                {
                    File.Delete("/etc/hostapd/wlan0.conf");
                    fileDeleted = true;
                }

                if (File.Exists("/etc/dnsmasq.conf"))
                {
                    File.Delete("/etc/dnsmasq.conf");
                    fileDeleted = true;
                }

                if (fileDeleted)
                {
                    // Reset IP address configuration to station mode
                    await WPA.SetIPAddress(IPAddress.Any, null, null, null);
                }
            }
            else
            {
                // Write hostapd config
                using (FileStream hostapdTemplateStream = new(Path.Combine(Directory.GetCurrentDirectory(), "hostapd.conf"), FileMode.Open, FileAccess.Read))
                {
                    using StreamReader reader            = new(hostapdTemplateStream);
                    using FileStream hostapdConfigStream = new("/etc/hostapd/wlan0.conf", FileMode.Create, FileAccess.Write);
                    using StreamWriter writer            = new(hostapdConfigStream);

                    while (!reader.EndOfStream)
                    {
                        string line = await reader.ReadLineAsync();

                        line = line.Replace("{ssid}", ssid);
                        line = line.Replace("{psk}", psk);
                        line = line.Replace("{channel}", channel.ToString());
                        line = line.Replace("{countryCode}", countryCode);
                        await writer.WriteLineAsync(line);
                    }
                }

                // Write dnsmasq config
                using (FileStream dnsmasqTemplateStream = new(Path.Combine(Directory.GetCurrentDirectory(), "dnsmasq.conf"), FileMode.Open, FileAccess.Read))
                {
                    using StreamReader reader            = new(dnsmasqTemplateStream);
                    using FileStream dnsmasqConfigStream = new("/etc/dnsmasq.conf", FileMode.Create, FileAccess.Write);
                    using StreamWriter writer            = new(dnsmasqConfigStream);

                    byte[] ip           = ipAddress.GetAddressBytes();
                    string ipRangeStart = $"{ip[0]}.{ip[1]}.{ip[2]}.{((ip[3] < 100 || ip[3] > 150) ? 100 : 151)}";
                    string ipRangeEnd   = $"{ip[0]}.{ip[1]}.{ip[2]}.{((ip[3] < 100 || ip[3] > 150) ? 150 : 200)}";

                    while (!reader.EndOfStream)
                    {
                        string line = await reader.ReadLineAsync();

                        line = line.Replace("{ipRangeStart}", ipRangeStart);
                        line = line.Replace("{ipRangeEnd}", ipRangeEnd);
                        line = line.Replace("{ipAddress}", ipAddress.ToString());
                        await writer.WriteLineAsync(line);
                    }
                }

                // Set IP address configuration for AP mode
                await WPA.SetIPAddress(ipAddress, null, null, null, true);
            }

            // Done
            return(new Message());
        }