diff --git a/extras/net/lwipopts.h b/extras/net/lwipopts.h index 87d0d9a5c..3d8022920 100644 --- a/extras/net/lwipopts.h +++ b/extras/net/lwipopts.h @@ -277,7 +277,7 @@ * (requires the LWIP_RAW option) */ #ifndef MEMP_NUM_RAW_PCB -#define MEMP_NUM_RAW_PCB 0 +#define MEMP_NUM_RAW_PCB 1 #endif /** @@ -642,7 +642,7 @@ * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. */ #ifndef LWIP_RAW -#define LWIP_RAW 0 +#define LWIP_RAW 1 #endif /* diff --git a/libraries/Ethernet/examples/EthernetPing/EthernetPing.ino b/libraries/Ethernet/examples/EthernetPing/EthernetPing.ino new file mode 100644 index 000000000..2baadaadd --- /dev/null +++ b/libraries/Ethernet/examples/EthernetPing/EthernetPing.ino @@ -0,0 +1,83 @@ +/* + Web ICMP Ping + + This sketch pings a device based on the IP address or the hostname + using the Ethernet module. + + created 14 February 2024 + by paulvha + + updated 27 February 2025 + by Fabik111 + + */ + +#include "EthernetC33.h" + +int status = WL_IDLE_STATUS; + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(10, 130, 22, 84); + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // start the Ethernet connection: + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // try to configure using IP address instead of DHCP: + // IN THAT CASE YOU SHOULD CONFIGURE manually THE DNS or USE the IPAddress Server variable above + // that is what is automatically done here... + Ethernet.begin(ip); + } + // give the Ethernet shield a second to initialize: + delay(2000); +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + + // Ping IP + const IPAddress remote_ip(140,82,121,4); + Serial.print("Trying to ping github.com on IP: "); + Serial.println(remote_ip); + + // using default ping count of 1 + int res = Ethernet.ping(remote_ip); + + if (res > 0) { + Serial.print("Ping response time: "); + Serial.print(res); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on IP!"); + } + + // Ping Host + const char* remote_host = "www.google.com"; + Serial.print("Trying to ping host: "); + Serial.println(remote_host); + + // setting ttl to 128 and ping count to 10 + int res1 = Ethernet.ping(remote_host); + + if (res1 > 0) { + Serial.print("Ping average response time: "); + Serial.print(res1); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on host!"); + } + + Serial.println(); + delay(1000); +} diff --git a/libraries/Ethernet/src/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp index 993ea2372..35bbd4fd3 100644 --- a/libraries/Ethernet/src/Ethernet.cpp +++ b/libraries/Ethernet/src/Ethernet.cpp @@ -223,4 +223,27 @@ IPAddress CEthernet::dnsServerIP() { return CLwipIf::getInstance().getDns(); } +/* -------------------------------------------------------------------------- */ +int CEthernet::ping(IPAddress ip, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().ping(ip, ttl); +} + +/* -------------------------------------------------------------------------- */ +int CEthernet::ping(const String &hostname, uint8_t ttl) +/* -------------------------------------------------------------------------- */ +{ + return ping(hostname.c_str(), ttl); +} + +/* -------------------------------------------------------------------------- */ +int CEthernet::ping(const char* host, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + IPAddress ip; + if(CLwipIf::getInstance().getHostByName(host,ip)) { + return CLwipIf::getInstance().ping(ip, ttl); + } + return -1; +} + CEthernet Ethernet; diff --git a/libraries/Ethernet/src/EthernetC33.h b/libraries/Ethernet/src/EthernetC33.h index 5c684fe63..5147d0464 100644 --- a/libraries/Ethernet/src/EthernetC33.h +++ b/libraries/Ethernet/src/EthernetC33.h @@ -69,6 +69,12 @@ class CEthernet { IPAddress gatewayIP(); IPAddress dnsServerIP(); + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128); + int ping(const String &hostname, uint8_t ttl = 128); + int ping(const char* host, uint8_t ttl = 128); friend class EthernetClient; friend class EthernetServer; diff --git a/libraries/WiFi/examples/WiFiPing/WiFiPing.ino b/libraries/WiFi/examples/WiFiPing/WiFiPing.ino new file mode 100644 index 000000000..a8f9ee979 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPing/WiFiPing.ino @@ -0,0 +1,120 @@ +/* + Web ICMP Ping + + This sketch pings a device based on the IP address or the hostname + using the WiFi module. By default the attempt is performed 5 times, but can + be changed to max. 255 + + It requires at least version 0.5.0 of USB Wifi bridge firmware and WiFiS3 library. + + This example is written for a network using WPA encryption. For + WEP or WPA, change the WiFi.begin() call accordingly. + + created 14 February 2024 + by paulvha + + updated 27 February 2025 + by Fabik111 + + */ + +#include "WiFiC3.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; + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // check for the WiFi module: + if (WiFi.status() == WL_NO_MODULE) { + Serial.println("Communication with WiFi module failed."); + // don't continue + while (true); + } + + // 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); + } + + printWifiStatus(); +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + + // Ping IP + const IPAddress remote_ip(140,82,121,4); + Serial.print("Trying to ping github.com on IP: "); + Serial.println(remote_ip); + + // using default ping count of 1 + int res = WiFi.ping(remote_ip); + + if (res > 0) { + Serial.print("Ping response time: "); + Serial.print(res); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on IP!"); + } + + // Ping Host + const char* remote_host = "www.google.com"; + Serial.print("Trying to ping host: "); + Serial.println(remote_host); + + // setting ttl to 128 and ping count to 10 + int res1 = WiFi.ping(remote_host); + + if (res1 > 0) { + Serial.print("Ping average response time: "); + Serial.print(res1); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on host!"); + } + + Serial.println(); + delay(1000); +} + +/* -------------------------------------------------------------------------- */ +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"); +} diff --git a/libraries/WiFi/examples/WiFiPing/arduino_secrets.h b/libraries/WiFi/examples/WiFiPing/arduino_secrets.h new file mode 100644 index 000000000..0c9fdd556 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPing/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index ba19f311c..fe4a7e7b1 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -321,12 +321,33 @@ unsigned long CWifi::getTime() { return 0; } - - void CWifi::setTimeout(unsigned long timeout) { (void)(timeout); } +/* -------------------------------------------------------------------------- */ +int CWifi::ping(IPAddress ip, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().ping(ip, ttl); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::ping(const String &hostname, uint8_t ttl) +/* -------------------------------------------------------------------------- */ +{ + return ping(hostname.c_str(), ttl); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::ping(const char* host, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + IPAddress ip; + if(hostByName(host,ip)) { + return CLwipIf::getInstance().ping(ip, ttl); + } + return -1; +} + CWifi WiFi; diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 2995cdcf9..2ff804d42 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -254,7 +254,12 @@ class CWifi { void setTimeout(unsigned long timeout); - + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128); + int ping(const String &hostname, uint8_t ttl = 128); + int ping(const char* host, uint8_t ttl = 128); }; diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 810b14075..ca1495f50 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -1,5 +1,9 @@ #include "CNetIf.h" #include +#include "lwip/include/lwip/raw.h" +#include "lwip/include/lwip/icmp.h" +#include "lwip/include/lwip/ip_addr.h" +#include "lwip/include/lwip/inet_chksum.h" IPAddress CNetIf::default_ip("192.168.0.10"); IPAddress CNetIf::default_nm("255.255.255.0"); @@ -14,6 +18,33 @@ bool CLwipIf::pending_eth_rx = false; FspTimer CLwipIf::timer; +static u8_t icmp_receive_callback(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) +{ + struct icmp_echo_hdr *iecho; + (void)(pcb); + (void)(addr); + LWIP_ASSERT("p != NULL", p != NULL); + + recv_callback_data* request = (recv_callback_data*)arg; + if ((p->tot_len < (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) || + pbuf_remove_header(p, PBUF_IP_HLEN) != 0) { + return 0; /* don't consume the packet */ + } + + iecho = (struct icmp_echo_hdr *)p->payload; + + if(iecho->id != 0xAFAF || iecho->seqno != lwip_htons(request->seqNum)) { + /* not eaten, restore original packet */ + pbuf_add_header(p, PBUF_IP_HLEN); + return 0; + } + + /* do some ping result processing */ + request->endMillis = millis(); + pbuf_free(p); + return 1; /* consume the packet */ +} + ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr) { IP_ADDR4(ipaddr, ipu8[0], ipu8[1], ipu8[2], ipu8[3]); @@ -120,6 +151,81 @@ void CLwipIf::lwip_task() } } + +int CLwipIf::ping(IPAddress ip, uint8_t ttl) +{ + /* ttl is not supported. Default value used is 255 */ + (void)ttl; + ip_addr_t addr; + addr.addr = ip; + + /* ICMP ping callback data structure */ + static recv_callback_data requestCbkData; + + /* initialize callback data for a new request */ + memset(&requestCbkData, 0, sizeof(recv_callback_data)); + requestCbkData.seqNum = (uint16_t)random(0xffff); + + /* Create a raw socket */ + struct raw_pcb* s = raw_new(IP_PROTO_ICMP); + if (!s) { + return -1; + } + + raw_recv(s, icmp_receive_callback, (void*)&requestCbkData); + raw_bind(s, IP_ADDR_ANY); + + struct pbuf *p; + struct icmp_echo_hdr *iecho; + size_t ping_size = sizeof(struct icmp_echo_hdr) + 32; + + p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM); + if (!p) { + raw_remove(s); + return -1; + } + + if ((p->len == p->tot_len) && (p->next == NULL)) { + iecho = (struct icmp_echo_hdr *)p->payload; + + size_t i; + size_t data_len = ping_size - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = 0xAFAF; + iecho->seqno = lwip_htons(requestCbkData.seqNum); + + /* fill the additional data buffer with some data */ + for(i = 0; i < data_len; i++) { + ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; + } + + iecho->chksum = inet_chksum(iecho, ping_size); + requestCbkData.startMillis = millis(); + raw_sendto(s, p, &addr); + + } + pbuf_free(p); + + CLwipIf::getInstance().startSyncRequest(); + + while (!requestCbkData.endMillis && (millis() - requestCbkData.startMillis) <= 5000) { + CLwipIf::getInstance().lwip_task(); + } + + CLwipIf::getInstance().restartAsyncRequest(); + + raw_remove(s); + + if (!requestCbkData.endMillis) { + return -1; + } + + return requestCbkData.endMillis - requestCbkData.startMillis; +} + /* -------------------------------------------------------------------------- */ /* GET INSTANCE SINGLETONE FUNCTION */ /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 407501b72..21a1ebaf9 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -131,6 +131,12 @@ ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr); uint32_t ip_addr_to_u32(ip_addr_t* ipaddr); +struct recv_callback_data{ + u32_t startMillis; + u32_t endMillis; + u16_t seqNum; +}; + /* Base class implements DHCP, derived class will switch it on or off */ /* -------------------------------------------------------------------------- */ class CNetIf { @@ -436,6 +442,10 @@ class CLwipIf { int setWifiMode(WifiMode_t mode); void lwip_task(); + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128); }; #endif diff --git a/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a b/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a index adaabfb1c..687e03a87 100644 Binary files a/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a and b/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a differ diff --git a/libraries/lwIpWrapper/src/lwipopts.h b/libraries/lwIpWrapper/src/lwipopts.h index 505a5b57b..790512f25 100644 --- a/libraries/lwIpWrapper/src/lwipopts.h +++ b/libraries/lwIpWrapper/src/lwipopts.h @@ -273,7 +273,7 @@ * (requires the LWIP_RAW option) */ #ifndef MEMP_NUM_RAW_PCB -#define MEMP_NUM_RAW_PCB 0 +#define MEMP_NUM_RAW_PCB 1 #endif /** @@ -633,7 +633,7 @@ * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. */ #ifndef LWIP_RAW -#define LWIP_RAW 0 +#define LWIP_RAW 1 #endif /*