Skip to content

DHCP range problematic in AP mode #3532

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

Open
NdK73 opened this issue Aug 18, 2017 · 11 comments
Open

DHCP range problematic in AP mode #3532

NdK73 opened this issue Aug 18, 2017 · 11 comments

Comments

@NdK73
Copy link
Contributor

NdK73 commented Aug 18, 2017

Hello.

I just noticed possible problems when calling WiFi.softAPConfig().
It assumes everybody uses a class-C network, a fixed mask of 24 bits and places the ESP at the start of the network (.1).
If the address given is over 55, the DHCP range collides with the reserved address (.255) and/or the network address (.0).
So I slightly modified the code to accept two optional arguments: dhcp_start and dhcp_end .
That makes it possible for the user to choose more freely the address range to use (I still don't check for network/broadcast collisions: with a great power...), including a whole class-A if desired (not that it's really useful with at most 4 clients, but anyway...).
If the optional arguments are not supplied, the old behaviour is retained, so it won't break existing code.

Hope it can be useful for others.

diff -u ESP8266WiFiAP.h.ori ESP8266WiFiAP.h

--- ESP8266WiFiAP.h.ori	2016-09-27 19:02:02.904865345 +0200
+++ ESP8266WiFiAP.h	2017-08-18 22:29:38.061691447 +0200
@@ -37,7 +37,7 @@
     public:
 
         bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0);
-        bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet);
+        bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, uint32_t dhcp_start=0, uint32_t dhcp_end=0);
         bool softAPdisconnect(bool wifioff = false);
 
         uint8_t softAPgetStationNum();

diff -u ESP8266WiFiAP.cpp.ori ESP8266WiFiAP.cpp

--- ESP8266WiFiAP.cpp.ori	2016-09-27 19:02:02.900865537 +0200
+++ ESP8266WiFiAP.cpp	2017-08-18 22:38:50.736674336 +0200
@@ -175,8 +175,10 @@
  * @param local_ip      access point IP
  * @param gateway       gateway IP
  * @param subnet        subnet mask
+ * @param dhcp_start    DHCP range start
+ * @param dhcp_end      DHCP range end
  */
-bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) {
+bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, uint32_t dhcp_start, uint32_t dhcp_end) {
     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
@@ -201,11 +203,19 @@
 
     struct dhcps_lease dhcp_lease;
     IPAddress ip = local_ip;
-    ip[3] += 99;
+    if(dhcp_start) {
+        ip=(dhcp_start & !info.netmask.addr) + (info.ip.addr&info.netmask.addr);
+    } else {
+        ip[3] += 99;
+    }
     dhcp_lease.start_ip.addr = static_cast<uint32_t>(ip);
     DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());
 
-    ip[3] += 100;
+    if(dhcp_end) {
+        ip=(dhcp_end & !info.netmask.addr) + (info.ip.addr&info.netmask.addr);
+    } else {
+        ip[3] += 100;
+    }
     dhcp_lease.end_ip.addr = static_cast<uint32_t>(ip);
     DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());

@devyte
Copy link
Collaborator

devyte commented Aug 18, 2017 via email

@devyte
Copy link
Collaborator

devyte commented Aug 18, 2017 via email

@NdK73
Copy link
Contributor Author

NdK73 commented Aug 18, 2017

Well, I don't need to actually check, since I apply the usual net-math (and with negated netmap to extract the net address, then add that to network address).
I've never done a PR, but it shouldn't be a big issue :)
I'm using the default of 0 for "use old behaviour".

@devyte
Copy link
Collaborator

devyte commented Aug 19, 2017 via email

@NdK73
Copy link
Contributor Author

NdK73 commented Aug 30, 2017

@igrr Comments? Can it be included in the upcoming release?

@devyte
Copy link
Collaborator

devyte commented Aug 30, 2017

I was just looking at this. I took a crash course of IP network math, and I now understand what you did.

I have two suggestions.

  1. Don't use uint32_t type for the new args . Use IPAddress instead, that is the type used for the current ip/mask/gway args. The args can always be static_cast to uint32 to do the math you did.
  2. Rather than add the optional arguments with defaults, implement a method overload:
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dhcp_start, IPAddress dhcp_end)
{
...
//function body of current code, but do the setup with all args as required
}

bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet)
{
//do your network math to calculate dhcp_start and dhcp_end based on local_ip and subnet
  return softAPConfig(local_ip, gatewaym subnet, dhcp_start, dhcp_end);
}

@NdK73
Copy link
Contributor Author

NdK73 commented Aug 31, 2017

Seems the answer to the mail got lost, so I'll insert it manually.
I used uint32 because I intended 'em as offsets, relative to the network base address.
So, if you have an address like 192.168.1.4/24 you had to pass just 100 and 199 as dhcp start and dhcp_end, not the whole addresses.
Well, actually there's no problem if you pass the whole address, but I think it's more error-prone.
I tried keeping the mods to a minimum, hence the defaults. I'm now working on a more complete solution in line with your suggestions.

@NdK73
Copy link
Contributor Author

NdK73 commented Sep 1, 2017

Created a PR.
Couldn't test as exensively as I'd like, but seems OK. Hope it can be included in upcoming release.

@devyte
Copy link
Collaborator

devyte commented Sep 5, 2017

@NdK73 Thanks for the PR. I'll be testing this myself at some point, I'll let you know as soon as I do.

@ncmreynolds
Copy link

The issue still exists, did anything happen with the PR above? I was just thinking of doing a solution myself but the one above, passing a start and end IP seems perfectly reasonable if tidily integrated.

@d-a-v
Copy link
Collaborator

d-a-v commented Jun 10, 2019

#3562 was reverted 4 days after merging.
Please open a new issue about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants