Skip to content
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

ip_napt_enable_no defined in lwip/lwip_napt.h, but not there in precompiled lib #6421

Closed
sekarpdkt opened this issue Mar 12, 2022 · 23 comments · Fixed by espressif/esp32-arduino-lib-builder#161
Assignees
Labels
Area: LIB Builder Depends on Lib Builder Type: Feature request Feature request for Arduino ESP32
Milestone

Comments

@sekarpdkt
Copy link

Board

All ESP32 modules

Device Description

ESP-WROOM-32

Hardware Configuration

Issue with enabling NAPT

Version

v2.0.2

IDE Name

Arduino IDE

Operating System

UBUNTU

Flash frequency

40Mhz

PSRAM enabled

no

Upload speed

115200

Description

Looks like, even though in lwip/lwip_napt.h, function void ip_napt_enable_no(u8_t number, int enable); is defined, actual implementation is missing. So while compiling the code, getting undefined reference error

Sketch

I included following define directives and headers

#define CONFIG_LWIP_IP_FORWARD 1
#define CONFIG_LWIP_IPV4_NAPT 1
#define CONFIG_LWIP_L2_TO_L3_COPY 1
#define PROTO_TCP 6
#define PROTO_UDP 17

#include "lwipopts.h"
#include "lwip/opt.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/ip4_addr.h"
#include "lwip/lwip_napt.h"
#include "lwip/ip4_napt.h"

Code that enables NAT

/**
 * Enable/Disable NAPT for a specified interface.
 *
 * @param netif number of the interface: 0 = STA, 1 = AP
 * @param enable non-zero to enable NAPT, or 0 to disable.
 */
ip_napt_enable_no(0, 1);
ip_napt_enable_no(1, 1);


### Debug Message

```plain
Getting following error:


undefined reference to `ip_napt_enable_no'


### Other Steps to Reproduce

_No response_

### I have checked existing issues, online documentation and the Troubleshooting Guide

- [X] I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@sekarpdkt sekarpdkt added the Status: Awaiting triage Issue is waiting for triage label Mar 12, 2022
@Jason2866
Copy link
Collaborator

Yes this is not set in the sdkonfig for the compiled libs used here.
I have set and it should work in my forked build. You can download from https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/729/framework-arduinoespressif32-v4.4_dev-d3c108c910.tar.gz

@sekarpdkt
Copy link
Author

sekarpdkt commented Mar 13, 2022

I just copied all files from /framework-arduinoespressif32/tools/sdk/esp32/lib/ from downloaded gz to ~/.arduino15/packages/esp32/hardware/esp32/2.0.2/tools/sdk/esp32/lib/. Getting new error.

undefined reference to `_printf_float'
undefined reference to `_scanf_float'

Do I need to do something else?

@sekarpdkt
Copy link
Author

I copied two lib files liblwip.a & libvfs.a. Code got compiled. Still unable to get the NAT to work. ESP connected to AP with 192.168.4.x address is unable to reach nodes connected to router directly (192.168.1.x)

@Jason2866
Copy link
Collaborator

You have to copy ALL files. NAPT is working. We use it as wifi range extender.

@VojtechBartoska VojtechBartoska added Type: Question Only question and removed Status: Awaiting triage Issue is waiting for triage labels Mar 16, 2022
@sekarpdkt
Copy link
Author

It worked if I try ip_napt_enable(WiFi.softAPIP(), 1); and not for ip_napt_enable_no(1, 1);. Is it mandatory to enable it for softAPIP()?

@VojtechBartoska
Copy link
Collaborator

Hello, is this still valid @sekarpdkt?

@VojtechBartoska VojtechBartoska added the Resolution: Awaiting response Waiting for response of author label May 10, 2022
@Jason2866
Copy link
Collaborator

@VojtechBartoska yes, since the Options are not set in sdkconfig used by Arduino Lib builder.

@VojtechBartoska VojtechBartoska added Area: LIB Builder Depends on Lib Builder Status: Needs investigation We need to do some research before taking next steps on this issue and removed Resolution: Awaiting response Waiting for response of author labels May 11, 2022
@VojtechBartoska VojtechBartoska removed the Type: Question Only question label May 11, 2022
@me-no-dev
Copy link
Member

From what I gather, this needs:

CONFIG_LWIP_IP_FORWARD=y
CONFIG_LWIP_L2_TO_L3_COPY=y
CONFIG_LWIP_IPV4_NAPT=y

@david-cermak will there be any negative consequences from these setting for people that do not use code that requires them? Mainly CONFIG_LWIP_L2_TO_L3_COPY

@david-cermak
Copy link
Contributor

will there be any negative consequences from these setting for people that do not use code that requires them?

Yes, negative effect on WiFi throughput. And yes, mainly the CONFIG_LWIP_L2_TO_L3_COPY which disables referencing the receive buffer before it's passed to lwip, so every time we receive a packet from WiFi we allocate a new one and make a copy.

Note, that users who are only interested in the NAPT feature, could possibly use IDF with CONFIG_LWIP_L2_TO_L3_COPY=n (receive by reference), on versions that include espressif/esp-lwip@3906826 (v5.0-dev, or upcoming v4.4.2 )

The other two (IP_FORWARD and IPV4_NAPT) have minimal impact on performance, would contribute a little to (mainly) program memory.

@me-no-dev
Copy link
Member

In that case we will hold until 4.4.2 to add NAPT support. Thanks @david-cermak !

me-no-dev added a commit to espressif/esp32-arduino-lib-builder that referenced this issue May 19, 2022
Fixes: espressif/arduino-esp32#6421

Will be part of ESP-IDF 4.4.2
@me-no-dev me-no-dev added Type: Feature request Feature request for Arduino ESP32 Status: In Progress Issue is in progress Status: Pending and removed Status: Needs investigation We need to do some research before taking next steps on this issue labels May 19, 2022
@me-no-dev me-no-dev added this to the 2.0.4 milestone May 19, 2022
@VojtechBartoska VojtechBartoska removed the Status: In Progress Issue is in progress label May 26, 2022
@me-no-dev
Copy link
Member

@david-cermak that PR is merged, but NAPT still selects L2_TO_L3_COPY: https://github.com/espressif/esp-idf/blob/release/v4.4/components/lwip/Kconfig#L182

@VojtechBartoska VojtechBartoska modified the milestones: 2.0.4, 2.1.0 Jul 11, 2022
@as-iotex
Copy link

Hello,
In napt available on 2.0.4?
I am still getting the undefined reference errors.

My sketch:

#include <WiFi.h>
#include <WiFiAP.h>

#define CONFIG_LWIP_IP_FORWARD 1
#define CONFIG_LWIP_IPV4_NAPT 1
#define CONFIG_LWIP_L2_TO_L3_COPY 1
#define PROTO_TCP 6
#define PROTO_UDP 17

#include "lwipopts.h"
#include "lwip/opt.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/ip4_addr.h"
#include "lwip/lwip_napt.h"
#include "lwip/ip4_napt.h"

const char* ssid = "ff";
const char* password = "ff";

const char* assid = "ESP";
const char* asecret = "1234";

void setup()
{
    Serial.begin(115200);
    WiFi.begin(ssid,password);
    WiFi.mode(WIFI_AP_STA);

    /**
     * Enable/Disable NAPT for a specified interface.
     *
     * @param netif number of the interface: 0 = STA, 1 = AP
     * @param enable non-zero to enable NAPT, or 0 to disable.
     */
    ip_napt_enable_no(0, 1);
    ip_napt_enable_no(1, 1);

    Serial.println("Creating AP");
    WiFi.softAP(assid,asecret,7,0,5);
    Serial.print("IP address:\t");
    Serial.println(WiFi.softAPIP());
    // Enable napt for softap ip
    ip_napt_enable(WiFi.softAPIP(), 1);

    Serial.print("connecting to…");
    Serial.println(ssid);

    WiFi.begin(ssid,password);

    while(WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

}

void loop()
{

}

I just updated the ESP32 board framework to 2.0.4 and I still get this output when buiding:


/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: sketch/esp32ap.ino.cpp.o:(.literal._Z5setupv+0x40): undefined reference to `ip_napt_enable_no'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: sketch/esp32ap.ino.cpp.o:(.literal._Z5setupv+0x44): undefined reference to `ip_napt_enable'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: sketch/esp32ap.ino.cpp.o: in function `setup()':
/Users/a/Documents/Arduino/esp32ap/esp32ap.ino:28: undefined reference to `ip_napt_enable_no'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /Users/a/Documents/Arduino/esp32ap/esp32ap.ino:36: undefined reference to `ip_napt_enable_no'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /Users/a/Documents/Arduino/esp32ap/esp32ap.ino:42: undefined reference to `ip_napt_enable'
collect2: error: ld returned 1 exit status
Multiple libraries were found for "WiFi.h"
 Used: /Users/a/Library/Arduino15/packages/esp32/hardware/esp32/2.0.4/libraries/WiFi
 Not used: /Applications/Arduino.app/Contents/Java/libraries/WiFi
exit status 1
Error compiling for board ESP32 Wrover Module.

If in fact this is not available in 2.0.4, is there a way I can hack around my local files to make the definitions available?

Thanks

@Jason2866
Copy link
Collaborator

Hello, In napt available on 2.0.4? I am still getting the undefined reference errors.

My sketch:

#include <WiFi.h>
#include <WiFiAP.h>

#define CONFIG_LWIP_IP_FORWARD 1
#define CONFIG_LWIP_IPV4_NAPT 1
#define CONFIG_LWIP_L2_TO_L3_COPY 1
#define PROTO_TCP 6
#define PROTO_UDP 17

#include "lwipopts.h"
#include "lwip/opt.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/ip4_addr.h"
#include "lwip/lwip_napt.h"
#include "lwip/ip4_napt.h"

const char* ssid = "ff";
const char* password = "ff";

const char* assid = "ESP";
const char* asecret = "1234";

void setup()
{
    Serial.begin(115200);
    WiFi.begin(ssid,password);
    WiFi.mode(WIFI_AP_STA);

    /**
     * Enable/Disable NAPT for a specified interface.
     *
     * @param netif number of the interface: 0 = STA, 1 = AP
     * @param enable non-zero to enable NAPT, or 0 to disable.
     */
    ip_napt_enable_no(0, 1);
    ip_napt_enable_no(1, 1);

    Serial.println("Creating AP");
    WiFi.softAP(assid,asecret,7,0,5);
    Serial.print("IP address:\t");
    Serial.println(WiFi.softAPIP());
    // Enable napt for softap ip
    ip_napt_enable(WiFi.softAPIP(), 1);

    Serial.print("connecting to…");
    Serial.println(ssid);

    WiFi.begin(ssid,password);

    while(WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

}

void loop()
{

}

I just updated the ESP32 board framework to 2.0.4 and I still get this output when buiding:


/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: sketch/esp32ap.ino.cpp.o:(.literal._Z5setupv+0x40): undefined reference to `ip_napt_enable_no'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: sketch/esp32ap.ino.cpp.o:(.literal._Z5setupv+0x44): undefined reference to `ip_napt_enable'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: sketch/esp32ap.ino.cpp.o: in function `setup()':
/Users/a/Documents/Arduino/esp32ap/esp32ap.ino:28: undefined reference to `ip_napt_enable_no'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /Users/a/Documents/Arduino/esp32ap/esp32ap.ino:36: undefined reference to `ip_napt_enable_no'
/Users/a/Library/Arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/gcc8_4_0-esp-2021r2-patch3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /Users/a/Documents/Arduino/esp32ap/esp32ap.ino:42: undefined reference to `ip_napt_enable'
collect2: error: ld returned 1 exit status
Multiple libraries were found for "WiFi.h"
 Used: /Users/a/Library/Arduino15/packages/esp32/hardware/esp32/2.0.4/libraries/WiFi
 Not used: /Applications/Arduino.app/Contents/Java/libraries/WiFi
exit status 1
Error compiling for board ESP32 Wrover Module.

If in fact this is not available in 2.0.4, is there a way I can hack around my local files to make the definitions available?

Thanks

In short no. Define changes in Arduino are useless, since in the precompiled libs the "NAPT" parts are missing. you can compile your own Arduino libs with https://github.com/espressif/esp32-arduino-lib-builder with enabled napt settings in sdkconfig. You can use my fork which has enabled napt (and other small changes).

@as-iotex
Copy link

as-iotex commented Aug 28, 2022

@Jason2866 Thanks for this. Much appreciated. I also had the impression that adding the defines to Arduino would't make any changes.

I used your fork and my sketch compiles. Does your fork have the following defines? I can't really tell.

#define CONFIG_LWIP_IP_FORWARD 1
#define CONFIG_LWIP_IPV4_NAPT 1
#define CONFIG_LWIP_L2_TO_L3_COPY 1
#define PROTO_TCP 6
#define PROTO_UDP 17

UPDATE:
I just found out your fork has them enabled except for PROTO_TCP and PROTO_UDP in https://github.com/martin-ger/esp32_nat_router/blob/master/sdkconfig

Let me explain what I am trying to do for more context:
My goal is to make the ESP32 behave line a wifi extender, as you mentioned in a post above. I have seen the following firmware https://github.com/martin-ger/esp32_nat_router. However, this firmware creates a separate NAT network within the ESP. I don't need this in my case, I just want the ESP32 to act as a pure wifi extender and let the upstream router handle routing.
It is my understanding that with NAPT enabled then the packets will be forwarded from/to the upstream router and the ESP32 clients without any need for doing NAT or handling packets in the ESP32.
I might be wrong in my understanding, please correct me if I am.

Now what's actually happening when I run my sketch is the following:

  • The ESP32 creates it's own AP and also connects to the upstream network (which has internet access).
  • However when I connect a client device to the ESP32 ap, then this client has no internet connection.

I would really appreciate if you can shed some light on this. Thanks :)

@Jason2866
Copy link
Collaborator

Wifi extender will work with this settings. We have a Tasmota variant doing this.

@VojtechBartoska
Copy link
Collaborator

Status update: We synced today, this is still pending and we are not able to merge it.

@VojtechBartoska VojtechBartoska modified the milestones: 2.0.6, 3.0.0 Sep 21, 2022
@bwjohns4
Copy link

I'm trying to do this using Arduino as an IDF component without any luck. I have these enabled:
CONFIG_LWIP_L2_TO_L3_COPY=y
CONFIG_LWIP_IP_FORWARD=y
CONFIG_LWIP_IPV4_NAPT=y

I'm trying to do NAT on the station interface so that when my packets leave the STA interface, they get NAT'd on their way into the STA LAN. To test if it's working, I'm opening the STA_AP mode softAP and connecting to that and trying to ping the gateway on the other LAN. So I am like this:
PHONE(192.168.4.2) --> ESP32_AP --- ESP32_STA(192.168.1.152) ----> LAN GATEWAY(192.168.1.1)

Do I only need to do ip_napt_enable_no(0,1) to only enable it on the STA interface, or is there more that I should do? I actually got it to work with part of the code above using:

    /**
     * Enable/Disable NAPT for a specified interface.
     *
     * @param netif number of the interface: 0 = STA, 1 = AP
     * @param enable non-zero to enable NAPT, or 0 to disable.
     */
    ip_napt_enable_no(0, 1);
    //ip_napt_enable_no(1, 1);

    Serial.println("Creating AP");
    WiFi.softAP(assid,asecret,7,0,5);
    Serial.print("IP address:\t");
    Serial.println(WiFi.softAPIP());
    // Enable napt for softap ip
    ip_napt_enable(WiFi.softAPIP(), 1);

I had to comment out the 2nd ip_napt_enable() to get it to work, but then I'm enabling NAT on both interfaces which doesn't seem right, right? The NAT should only happen on the STA interface but when I do that it doesn't work. Am I just misunderstanding the concept here?

Do you have to re-enable napt if an interface goes down/up?

@Jason2866
Copy link
Collaborator

@bwjohns4 Dont know if it solves your problem. This framework has a known working napt setup. We use the function.

@bwjohns4
Copy link

@Jason2866 can I use this one and still build as
framework = espidf, arduino?

Also, which interface should I enable napt on for NAT'ing back into the STA LAN (which also contains the typical home router)? I assume only enable NAT on STA, right?

@Jason2866
Copy link
Collaborator

@bwjohns4 To use for IDF and Arduino do

platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.3/platform-espressif32-2.0.5.3.zip

Maybe you find some usefull code in our implementation in Tasmota

@bwjohns4
Copy link

That works! Thanks so much! For the record, it appears that using a 1 or 0 for ip_napt_enable_no() does not work as expected. It must need more of a handle to the interface than a simple 1 or 0. Neither of these seemed to do anything, I tried in various combinations with successful version (bottom):

ip_napt_enable_no(0, 1);
ip_napt_enable_no(1, 1);

But this did work without either of the above functions:

ip_napt_enable(WiFi.softAPIP(), 1);

It's also strange to me that for this purpose you need to enable NAT on the AP interface even though I want to access the STA network via the NAT mechanism. The NAT must initiate when the packets enter the target interface, then whatever interface they leave would detect that the source IP had been removed and would be triggered to update the NAT table and replace the source IP with the IP of the interface the packet leaves from.

frwololo added a commit to frwololo/PS4_PS5-ESP8266-Server that referenced this issue Sep 6, 2023
This adds support for ESP32.

*** TESTS
Tested:
ESP32 Support fully tested in online mode (Tested with ESP32_DevkitC_V4):
- DNS: playstation.net redirected ok, playstation.com blocked ok
- HTTPS: works ok on PC (with of course certificate warning) and ok on PS5
- PS4 Tests: User Guide redirect works, Tested GoldHEN 2.3 on PS4
- PS5 Tests: User Guide Redirect Works, Tested SpecterDev's exploit on PS5

Untested:
- offline mode not tested
- ESP8266 not fully tested with these changes. It is supposed to have no impact on ESP8266.

**** ESP32 Compilation
For people who want to compile this:
- IP_NAPT errors: Some SDKs don't have NAT support enabled for ESP32 so I had to use an unofficial build of the ESP32 Library for Arduino. See:  espressif/arduino-esp32#6421 (comment)

- TAG ESP_LOGI errors: ESP32_HTTPS_SERVER seems to have some code incompatible with some SDKs, I had to manually edit one of the files, see:  fhessel/esp32_https_server#156 (comment)
@VojtechBartoska
Copy link
Collaborator

Possibly relates to #8760

@Jason2866
Copy link
Collaborator

Jason2866 commented Feb 28, 2024

With IDF 5.1 used for Arduino Core 3.0.0 the features

CONFIG_LWIP_IP_FORWARD=y
CONFIG_LWIP_IPV4_NAPT=y

can be enabled, since the do use just a bit of RAM. The performance degeneration option

CONFIG_LWIP_L2_TO_L3_COPY=y

is not needed anymore to enable NAPT (with IDF 5.1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: LIB Builder Depends on Lib Builder Type: Feature request Feature request for Arduino ESP32
Projects
7 participants