Skip to content

Add ability to set start and end ip for softAP #6422

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 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
23 changes: 12 additions & 11 deletions libraries/ESP8266WiFi/examples/StaticLease/StaticLease.ino
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ void loop() {
const char *ssid = "ESPap";
const char *password = "thereisnospoon";

/* List of mac address for static lease */
uint8 mac_CAM[6] = { 0x00, 0x0C, 0x43, 0x01, 0x60, 0x15 };
uint8 mac_PC[6] = { 0xb4, 0x52, 0x7e, 0x9a, 0x19, 0xa5 };

ESP8266WebServer server(80);

/* Set the IP Address you want for your AP */
Expand All @@ -44,7 +48,6 @@ void handleRoot() {
result += String(number_client);
result += "</h1></br>";
while (stat_info != NULL) {

result += "Client ";
result += String(i);
result += " = ";
Expand All @@ -53,7 +56,6 @@ void handleRoot() {
sprintf(wifiClientMac, "%02X:%02X:%02X:%02X:%02X:%02X", MAC2STR(stat_info->bssid));
result += wifiClientMac;
result += "</br>";

stat_info = STAILQ_NEXT(stat_info, next);
i++;
}
Expand All @@ -63,10 +65,6 @@ void handleRoot() {
}

void setup() {
/* List of mac address for static lease */
uint8 mac_CAM[6] = { 0x00, 0x0C, 0x43, 0x01, 0x60, 0x15 };
uint8 mac_PC[6] = { 0xb4, 0x52, 0x7e, 0x9a, 0x19, 0xa5 };

Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
Expand All @@ -75,26 +73,29 @@ void setup() {
WiFi.persistent(false);

WiFi.mode(WIFI_AP);

/* Configure AP with IP = 192.168.0.1 / Gateway = 192.168.0.1 / Subnet = 255.255.255.0
if you specify the ESP8266's IP-address with 192.168.0.1, the function softAPConfig() sets the DHCP-range as 192.168.0.100 - 192.168.0.200
*/
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
/* Setup your static leases.

As it depend from your first address, and need to be done BEFORE any request from client,
this need to be specified after WiFi.softAPConfig() and before WiFi.softAP().
/* Start Access Point. You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid, password);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Starting the softAP before setting up the static leases allows a race condition, where a client could potentially connect as soon as the AP is up, but before the leases are set up. In that case, the lease setup could lead to an address clash. This is the reason behind the current call order.

Copy link
Contributor Author

@mbm60 mbm60 Aug 29, 2019

Choose a reason for hiding this comment

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

Yes but I did test it and if it is before start softAP, "StaticLease" won't work


/* Setup your static leases.
As it depend from your first address, and need to be done BEFORE any request from client,
this need to be specified after WiFi.softAP().
first call to wifi_softap_add_dhcps_lease() will setup first IP address of the range
second call to wifi_softap_add_dhcps_lease() will setup second IP address of the range
...
any client not listed will use next IP address available from the range (here 192.168.0.102 and more)
*/
wifi_softap_add_dhcps_lease(mac_CAM); // always 192.168.0.100
wifi_softap_add_dhcps_lease(mac_PC); // always 192.168.0.101
/* Start Access Point. You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid, password);

Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());

/* Setup HTTP Server */
server.on("/", handleRoot);
server.begin();
Expand Down
72 changes: 64 additions & 8 deletions libraries/ESP8266WiFi/src/ESP8266WiFiAP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
#include "ESP8266WiFi.h"
#include "ESP8266WiFiGeneric.h"
#include "ESP8266WiFiAP.h"
#include "lwip/def.h"

#if LWIP_VERSION_MAJOR == 1
#include "lwip/app/dhcpserver.h"
#else
#include "dhcpserver.h"
#endif

extern "C" {
#include "c_types.h"
Expand All @@ -37,8 +44,6 @@ extern "C" {

#include "debug.h"



// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------- Private functions ------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -194,8 +199,10 @@ bool ESP8266WiFiAPClass::softAP(const String& ssid, const String& passphrase, in
* @param local_ip access point IP
* @param gateway gateway IP (0.0.0.0 to disable)
* @param subnet subnet mask
* @param dhcp_start first IP assigned by DHCP
* @param dhcp_end last IP assigned by DHCP
*/
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) {
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dhcp_start, IPAddress dhcp_end) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe that currently the dhcp server is always on, and there is no way to turn it off. I suggest the following:

  1. Don't add additional parameters here. Instead, implement a method overload that has the additional parameters.
  2. Change the current method to add a bool dhcpEnabled at the end with default true. When true, dhcp is enabled per current defaults. When false, dhcp setup is skipped altogether.
  3. Refactor both methods to not have duplicate code.

DEBUG_WIFI("[APConfig] local_ip: %s gateway: %s subnet: %s\n", local_ip.toString().c_str(), gateway.toString().c_str(), subnet.toString().c_str());
if(!WiFi.enableAP(true)) {
// enable AP failed
Expand All @@ -206,17 +213,48 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA

if ( !local_ip.isV4()
|| !subnet.isV4()
|| !dhcp_start.isV4()
|| !dhcp_end.isV4()
#if LWIP_IPV6
// uninitialized gateway is valid
|| gateway.isV6()
#endif
) {
return false;
}

if( subnet != IPAddress(255,255,255,0)) {
DEBUG_WIFI("[APConfig] invalid netmask. only netmask \"255.255.255.0\" is valid!\n");
return false;
}

struct ip_info info;

info.ip.addr = local_ip.v4();
info.gw.addr = gateway.v4();
info.netmask.addr = subnet.v4();

uint32_t softap_ip = htonl(info.ip.addr);
uint32_t start_ip = htonl(dhcp_start.v4());
uint32_t end_ip = htonl(dhcp_end.v4());

if ((start_ip <= softap_ip)
|| ( end_ip <= softap_ip)) {
DEBUG_WIFI("[APConfig] config ip information can't contain local ip!\n");
return false;
}

if ((end_ip - start_ip) > DHCPS_MAX_LEASE) {
DEBUG_WIFI("[APConfig] the value of dhcp lease is greater than \"DHCPS_MAX_LEASE\"!\n");
return false;
}

softap_ip >>= 8;
if ((start_ip >> 8 != softap_ip)
|| (end_ip >> 8 != softap_ip)) {
DEBUG_WIFI("[APConfig] config ip information must be in the same segment as the local ip!\n");
return false;
}

if(!wifi_softap_dhcps_stop()) {
DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n");
Expand All @@ -228,13 +266,14 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
}

struct dhcps_lease dhcp_lease;
IPAddress ip = local_ip;
ip[3] += 99;
dhcp_lease.start_ip.addr = ip.v4();
dhcp_lease.enable = true;

IPAddress ip = dhcp_start;
dhcp_lease.start_ip.addr = dhcp_start.v4();
DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());

ip[3] += 100;
dhcp_lease.end_ip.addr = ip.v4();
ip = dhcp_end;
dhcp_lease.end_ip.addr = dhcp_end.v4();
DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());

if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
Expand Down Expand Up @@ -277,7 +316,24 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
return ret;
}

/**
* Configure access point
* @param local_ip access point IP
* @param gateway gateway IP
* @param subnet subnet mask
*/
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) {
IPAddress dhcp_start;
IPAddress dhcp_end;

dhcp_start = local_ip;
dhcp_start[3] += 1;
dhcp_end = dhcp_start;
dhcp_end[3] += 100;

bool ret = softAPConfig(local_ip, gateway, subnet, dhcp_start, dhcp_end);
return ret;
}

/**
* Disconnect from the network (close AP)
Expand Down
1 change: 1 addition & 0 deletions libraries/ESP8266WiFi/src/ESP8266WiFiAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ESP8266WiFiAPClass {

bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4);
bool softAP(const String& ssid,const String& passphrase = emptyString,int channel = 1,int ssid_hidden = 0,int max_connection = 4);
bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dhcp_start, IPAddress dhcp_end);
bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet);
bool softAPdisconnect(bool wifioff = false);

Expand Down