Skip to content

Add WPA2 Enterprise APIs and example #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions examples/WiFiWebClientWPA2Enterprise/WiFiWebClientWPA2Enterprise.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@

/*
Web client

This sketch connects to a website (http://www.google.com)
using the WiFi module.

This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.

This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.

Circuit:
* Board with NINA module (Arduino MKR WiFi 1010, MKR VIDOR 4000 and UNO WiFi Rev.2)

created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
*/


#include <SPI.h>
#include <WiFiNINA.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "www.google.com"; // name address for Google (using DNS)

// Initialize the Ethernet client library
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the best text would be, but certainly this comment and the two following lines are wrong. Perhaps:

// create a WiFiClient object

// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;

// Initialize the WPA2 Enterprise object
// Just fill the fields you need
// eg. if you are given only an identity and a certificate, initialize it as
// WPA2Enterprise data("myidentity", ca_pem);
// Certificates are stored in secret tab to avoid sharing them.

WPA2Enterprise data(EAP_TLS, "myidentity", "username", "password", ca_pem, client_crt, client_key);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tigoe do you have any suggestions on the API for WPA2 enterprise support?

The way the underlying SDK on the NINA module works is it will accept all the configs (identity, username, password, CA, cert, key), then figure out what to use.

@facchinm has made a WPA2Enterprise class to store it, the full list constructor args is optional.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make the default interface simple, like the macos login: begin(ssid, userid, password). Use defaults for the other properties. Then I'd add functions to set the rest of the properties.

Here's a typical wpa_supplicant record from linux:

ssid="network_name"
  key_mgmt=WPA-EAP
  eap=PEAP
  proto=WPA2
  phase2="auth=MSCHAPV2"
  anonymous_identity="your_username"
  identity="your_username"
  password=your_password

So if you want to be thorough:
.setKeyMgmt()
.setEAP()
.setProto()
.setPhase2()
.setAnonymousID()
.setID()
.setPassword()
That may be overkill, though, and it might be better just to have a version of .begin() that could take a wpa_supplicant-style record.
I think eduroam uses the same ID for identity and anonymous_identity, so you could say if the latter is not set, use the former for both. And PEAP and Mschapv2 seem to be common on wpa enterprise networks I've seen, so those might be good defaults. Double check those against eduroam though, because I think one of the big values of this is login for schools, and many universities worldwide use that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Tom, I'm setting up a test network to test how the ESP firmware performs in the various cases. My concert in that, if username (identity) + password is not covering the 99% of use cases, you'll need to add other information anyway, making the whole process split into 2 (or N) places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I would add the settings for eduroam in the examples then, since it's likely to be a popular use of this feature. Worth putting some notes in the documentation on how to find out these details as well, might want to pass that along to Simone.


void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

// configure the wifi module to use provided WPA2 Enterprise parameters
WiFi.config(data);

// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}

String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}

// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);

// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();

Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println("Connection: close");
client.println();
}
}

void loop() {
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
char c = client.read();
Serial.write(c);
}

// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();

// do nothing forevermore:
while (true);
}
}


void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
127 changes: 127 additions & 0 deletions examples/WiFiWebClientWPA2Enterprise/arduino_secrets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#define SECRET_SSID ""
#define SECRET_PASS ""

// This certificates are completely bogus, but your own should resemble this format

const char * ca_pem = "-----BEGIN CERTIFICATE-----\n"
"MIID3DCCA0WgAwIBAgIJANe5ZSCKoB8fMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD\n"
"VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT\n"
"BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs\n"
"ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X\n"
"DTE2MTEyMzAyNTUwN1oXDTE3MDEyMjAyNTUwN1owgZMxCzAJBgNVBAYTAkZSMQ8w\n"
"DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh\n"
"bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG\n"
"A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN\n"
"AQEBBQADgY0AMIGJAoGBAL03y7N2GvNDO9BN8fVtdNonp0bMiqpj1D0He5+OTM+9\n"
"3ZTIsJCNrbzhLQrRI3vMW7UDy8U7GeWORN9W4dWYlYiy/NFRp3hNMrbePhVmNIOV\n"
"ww4ovGzbD+Xo31gPVkhzQ8I5/jbOIQBmgKMAMZyOMlG9VD6yMmAeYqnZYz68WHKt\n"
"AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUf1MLQIzAEZcRsgZlS8sosfmVI+UwgcgG\n"
"A1UdIwSBwDCBvYAUf1MLQIzAEZcRsgZlS8sosfmVI+WhgZmkgZYwgZMxCzAJBgNV\n"
"BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG\n"
"A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl\n"
"LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDX\n"
"uWUgiqAfHzAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93\n"
"d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA\n"
"GepHc7TE/P+5t/cZPn5TTQkWQ/4/1lgQd82lF36RYWSIW3BdAc0zwYWYZaWixxyp\n"
"s0YOqwz6PZAGRV+SlYO2f8Kf+C3aZs4YHB0GsmksmFOb8r9d7xcDuOKHoA+QV0Zw\n"
"RaK6pttsBAxy7rw3kX/CgTp0Y2puaLdMXv/v9FisCP8=\n"
"-----END CERTIFICATE-----";

const char * client_crt = "Certificate:\n"
" Data:\n"
" Version: 3 (0x2)\n"
" Serial Number: 44 (0x2c)\n"
" Signature Algorithm: sha1WithRSAEncryption\n"
" Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./[email protected], CN=Example Certificate Authority\n"
" Validity\n"
" Not Before: Nov 23 02:55:07 2016 GMT\n"
" Not After : Jan 22 02:55:07 2017 GMT\n"
" Subject: C=FR, ST=Radius, O=Example Inc., [email protected]/[email protected]\n"
" Subject Public Key Info:\n"
" Public Key Algorithm: rsaEncryption\n"
" Public-Key: (2048 bit)\n"
" Modulus:\n"
" 00:ac:41:d4:a2:46:0c:dc:67:1d:7b:89:36:7c:15:\n"
" be:a2:c1:fe:4c:f2:fa:af:5d:76:0e:ee:b5:ca:d4:\n"
" d3:01:c8:6b:30:50:df:2d:57:17:f4:43:47:97:ca:\n"
" f1:8d:f7:c0:9d:56:b3:e7:17:7c:58:59:de:f3:be:\n"
" b5:08:5d:f8:3a:ad:83:44:0d:31:c9:f1:3d:f1:9a:\n"
" cf:84:0c:ad:d3:be:5c:bd:3d:58:b5:1d:2c:fe:70:\n"
" 8d:c5:b0:17:87:d4:8e:85:f7:51:4c:0f:d1:e0:8c:\n"
" 7b:a0:25:ab:91:7c:7f:eb:47:73:c9:4b:6c:8b:e6:\n"
" c1:06:d5:94:30:63:ec:45:1a:f5:7f:46:2f:b3:84:\n"
" 78:5d:1c:37:1a:fa:57:ea:45:5e:45:40:ab:14:c7:\n"
" 81:b0:26:3d:7e:cf:da:db:f0:f1:40:a7:a1:4b:54:\n"
" f3:96:1b:c9:30:3c:3c:d8:19:ba:c7:df:b1:ad:a2:\n"
" d6:17:0a:d6:ed:31:b5:cb:12:39:f5:6e:92:6b:85:\n"
" f2:9e:c7:06:6b:bb:89:ed:a7:5f:ec:56:12:46:fd:\n"
" 3a:74:d1:d2:31:30:1d:58:19:25:33:ff:11:ea:3a:\n"
" 52:33:b1:fb:d3:75:8d:1f:5e:36:a5:35:e0:11:5a:\n"
" 4a:2d:97:58:2c:3d:62:3c:32:af:83:69:a9:1a:32:\n"
" 1b:b7\n"
" Exponent: 65537 (0x10001)\n"
" X509v3 extensions:\n"
" X509v3 Extended Key Usage: \n"
" TLS Web Client Authentication\n"
" X509v3 CRL Distribution Points: \n"
"\n"
" Full Name:\n"
" URI:http://www.example.com/example_ca.crl\n"
"\n"
" Signature Algorithm: sha1WithRSAEncryption\n"
" 8b:8d:b6:19:ce:6f:6b:9e:1d:03:8b:6b:10:fc:99:d0:7a:2f:\n"
" e0:37:ce:b8:a4:e4:b9:a1:c2:36:ff:76:b2:ad:d7:d0:df:d1:\n"
" 03:27:93:a7:4e:1e:bf:ed:d2:b7:65:2a:c9:c3:ab:20:aa:e3:\n"
" 10:4c:75:3b:c4:02:ab:34:08:6e:61:91:cf:e3:02:35:6a:e5:\n"
" f3:25:96:51:92:82:6e:52:81:c1:f1:7b:68:02:b0:ce:f4:ba:\n"
" fd:6e:68:35:b3:7e:77:cb:a0:1e:11:5e:58:bf:f3:2a:ed:b3:\n"
" 4c:82:21:5e:1b:47:b6:2f:f3:f5:c9:1b:6a:70:44:6d:ff:ad:\n"
" a6:e3\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDTjCCAregAwIBAgIBLDANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx\n"
"DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF\n"
"eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw\n"
"JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjExMjMw\n"
"MjU1MDdaFw0xNzAxMjIwMjU1MDdaMHExCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS\n"
"YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEZMBcGA1UEAwwQdXNlckBleGFt\n"
"cGxlLmNvbTEfMB0GCSqGSIb3DQEJARYQdXNlckBleGFtcGxlLmNvbTCCASIwDQYJ\n"
"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKxB1KJGDNxnHXuJNnwVvqLB/kzy+q9d\n"
"dg7utcrU0wHIazBQ3y1XF/RDR5fK8Y33wJ1Ws+cXfFhZ3vO+tQhd+Dqtg0QNMcnx\n"
"PfGaz4QMrdO+XL09WLUdLP5wjcWwF4fUjoX3UUwP0eCMe6Alq5F8f+tHc8lLbIvm\n"
"wQbVlDBj7EUa9X9GL7OEeF0cNxr6V+pFXkVAqxTHgbAmPX7P2tvw8UCnoUtU85Yb\n"
"yTA8PNgZusffsa2i1hcK1u0xtcsSOfVukmuF8p7HBmu7ie2nX+xWEkb9OnTR0jEw\n"
"HVgZJTP/Eeo6UjOx+9N1jR9eNqU14BFaSi2XWCw9Yjwyr4NpqRoyG7cCAwEAAaNP\n"
"ME0wEwYDVR0lBAwwCgYIKwYBBQUHAwIwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDov\n"
"L3d3dy5leGFtcGxlLmNvbS9leGFtcGxlX2NhLmNybDANBgkqhkiG9w0BAQUFAAOB\n"
"gQCLjbYZzm9rnh0Di2sQ/JnQei/gN864pOS5ocI2/3ayrdfQ39EDJ5OnTh6/7dK3\n"
"ZSrJw6sgquMQTHU7xAKrNAhuYZHP4wI1auXzJZZRkoJuUoHB8XtoArDO9Lr9bmg1\n"
"s353y6AeEV5Yv/Mq7bNMgiFeG0e2L/P1yRtqcERt/62m4w==\n"
"-----END CERTIFICATE-----";

const char * client_key = "-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEpgIBAAKCAQEArEHUokYM3Gcde4k2fBW+osH+TPL6r112Du61ytTTAchrMFDf\n"
"LVcX9ENHl8rxjffAnVaz5xd8WFne8761CF34Oq2DRA0xyfE98ZrPhAyt075cvT1Y\n"
"tR0s/nCNxbAXh9SOhfdRTA/R4Ix7oCWrkXx/60dzyUtsi+bBBtWUMGPsRRr1f0Yv\n"
"s4R4XRw3GvpX6kVeRUCrFMeBsCY9fs/a2/DxQKehS1TzlhvJMDw82Bm6x9+xraLW\n"
"FwrW7TG1yxI59W6Sa4XynscGa7uJ7adf7FYSRv06dNHSMTAdWBklM/8R6jpSM7H7\n"
"03WNH142pTXgEVpKLZdYLD1iPDKvg2mpGjIbtwIDAQABAoIBAQCMhO9GqUpYia2d\n"
"VyOhOcPX1dTzRMuHPwDN0aFvIwo2zB3UvkQxInkiA7hldWJz44W3VEFR5PDEyht8\n"
"Tzgy6SVUCLOqUfEpwag8bYOXPxiWQRY6Mc8pf/FyZrLgb3PilFznoAcru0QEn9VB\n"
"oTlCZ4OalSE5NlQIFGemgZhvmTPmcm4OwPW2diBjLtb3AA8eaaw8okWZwr8g4Bcd\n"
"el5KX6pZpDRpGQueh3iKaKxYWbxLYK+c30gKWD65tsAqKyVg2Tm1R2c+kFXgizZt\n"
"EexD95SGMjSkGg3R05sKv6m71iJhlOzVQ4ZCKm18Kqa7wZuZ4SIehVmKIV0gaupz\n"
"gjyr7+NBAoGBAOGjjGI3nxJTZY3O+KeaQo/jqrKowqZxzMOsCgAvW56xDuAvx9TJ\n"
"m4428NGubMl/0RwX6TnxJDm6oe+tnOxLIgE/VnsQLiNzQuFJxrs5JYctdGc4uvk2\n"
"KuXDr7tPEYlU/7OLRReov9emydIXJnsGejkIPllUj+DGNjNFqtXh2VoHAoGBAMNv\n"
"eSgJSkcM6AUaDuUKaXBL2nkKHNoTtRQ0eCEUds6arKyMo0mSP753FNEuOWToVz1O\n"
"oaddSFw81J9t+Xd6XSRbhMj63bQ9nvFKBA1lJfLu+xe3ts0f+vmp1PguOuUHsgNP\n"
"aAm/gLPSKUpBO46NG6KhUrZ2ej6AEg7SuGXrDITRAoGBAKK7s6m6d81dvGZ0GT23\n"
"sb3Y8ul7cTdd59JPp77OaQOgqxvhGfxLkxcUZMa1R9xjhMsAK8MQOZIxGk2kJwL8\n"
"hP/lUFfdKYmDvX6CGQQ6iOhfTg6MCb1m5bVkVr9+nSUw2mIBVclkeUftEK2m6Kfd\n"
"2hR774u5wzLXgYuk+TrcckfNAoGBAJ9X8hacjH0lnr8aIe7I8HLoxbZOcnuz+b4B\n"
"kbiW8M8++W6uNCw2G9b1THnJEG6fqRGJXPASdH8P8eQTTIUHtY2BOOCM+dqNK1xc\n"
"FrW9NJXAF+WcmmTgoEaTG9tGBirafV+JjK/1/b+fqJ6sVRzDHDcbBU9ThhQTY6XG\n"
"VSZz4H8hAoGBAMeQQjiUlKBnpGt1oTgKDZo58b7ui61yftg+dEAwIKs6eb5X20vZ\n"
"Ca4v/zg06k9lKTzyspQjJZuzpMjFUvDK4ReamEvmwQTIc+oYVJm9Af1HUytzrHJH\n"
"u0/dDt0eYpZpzrFqxlP+0oXxlegD8REMVvwNCy+4isyCvjogDaYRfJqi\n"
"-----END RSA PRIVATE KEY-----";
21 changes: 21 additions & 0 deletions src/WiFi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,27 @@ uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase, uint8_t cha
return status;
}

void WiFiClass::config(WPA2Enterprise& data)
{
WiFiDrv::wpa2EntSetIdentity(data.identity.c_str());
WiFiDrv::wpa2EntSetUsername(data.username.c_str());
WiFiDrv::wpa2EntSetPassword(data.password.c_str());

if (data.ca_pem) {
WiFiStorage.remove("/fs/ca.pem");
WiFiStorage.write("/fs/ca.pem", 0, (uint8_t*)data.ca_pem, strlen(data.ca_pem));
}
if (data.client_crt) {
WiFiStorage.remove("/fs/client.crt");
WiFiStorage.write("/fs/client.crt", 0, (uint8_t*)data.client_crt, strlen(data.client_crt));
}
if (data.client_key) {
WiFiStorage.remove("/fs/client.key");
WiFiStorage.write("/fs/client.key", 0, (uint8_t*)data.client_key, strlen(data.client_key));
}
WiFiDrv::wpa2EntEnable();
}

void WiFiClass::config(IPAddress local_ip)
{
WiFiDrv::config(1, (uint32_t)local_ip, 0, 0);
Expand Down
39 changes: 39 additions & 0 deletions src/WiFi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,39 @@ extern "C" {
#include "WiFiSSLClient.h"
#include "WiFiServer.h"

typedef enum _eap_methods {
EAP_TLS = 0,
EAP_PEAP = 1,
EAP_TTLS = 2,
} eap_method;

class WPA2Enterprise
{
public:
WPA2Enterprise(eap_method method, String identity, String username = "", String password = "",
const char* ca_pem = NULL, const char* client_crt = NULL, const char* client_key = NULL) :
method(method), identity(identity), username(username), password(password),
ca_pem(ca_pem), client_crt(client_crt), client_key(client_key)
{}
WPA2Enterprise(String identity, String username = "", String password = "",
const char* ca_pem = NULL, const char* client_crt = NULL, const char* client_key = NULL) :
method(EAP_TLS), identity(identity), username(username), password(password),
ca_pem(ca_pem), client_crt(client_crt), client_key(client_key)
{}
WPA2Enterprise(String identity, const char* ca_pem = NULL, const char* client_crt = NULL, const char* client_key = NULL) :
method(EAP_TLS), identity(identity), username(""), password(""),
ca_pem(ca_pem), client_crt(client_crt), client_key(client_key)
{}

eap_method method; // TLS: 0, PEAP: 1, TTLS: 2 // looks like it's handled internally
String identity;
String username;
String password;
const char* ca_pem;
const char* client_crt;
const char* client_key;
};

class WiFiClass
{
private:
Expand Down Expand Up @@ -80,6 +113,12 @@ class WiFiClass
uint8_t beginAP(const char *ssid, const char* passphrase);
uint8_t beginAP(const char *ssid, const char* passphrase, uint8_t channel);

/* Add WPA2 Enterprise information for next connection
*
* param data: Static ip configuration
*/
void config(WPA2Enterprise& data);

/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
Expand Down
Loading