Skip to content

Commit e8711c0

Browse files
committed
WiFiClient::remoteIP and remoteIP6 IPv6 support
For RemoteIP and AF_INET6 socket i added support ip6 to ip4 mapping, so .remoteIP will return IPv4 address on dual stack socket, if available. Scenarios tested: WiFiTelnetToSerial, wifiMulti.IPv6(true), connect both from IPv4 and IPv6 WiFiTelnetToSerial, wifiMulti.IPv6(true); but set to listen on IPv4 only. WiFiTelnetToSerial, IPv6 disabled, with or without bind to specific IP4. AsyncUDPServer, without IPv6 support. Signed-off-by: Denys Fedoryshchenko <[email protected]>
1 parent 4735f66 commit e8711c0

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

Diff for: cores/esp32/Client.h

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "Print.h"
2323
#include "Stream.h"
2424
#include "IPAddress.h"
25+
#include "IPv6Address.h"
2526

2627
class Client: public Stream
2728
{

Diff for: libraries/WiFi/src/WiFiClient.cpp

+51-2
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,52 @@ IPAddress WiFiClient::remoteIP(int fd) const
561561
struct sockaddr_storage addr;
562562
socklen_t len = sizeof addr;
563563
getpeername(fd, (struct sockaddr*)&addr, &len);
564-
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
565-
return IPAddress((uint32_t)(s->sin_addr.s_addr));
564+
565+
// Old way, IPv4
566+
if (((struct sockaddr*)&addr)->sa_family == AF_INET) {
567+
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
568+
return IPAddress((uint32_t)(s->sin_addr.s_addr));
569+
}
570+
// IPv6, but it might be IPv4 mapped address
571+
if (((struct sockaddr*)&addr)->sa_family == AF_INET6) {
572+
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr;
573+
if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) {
574+
struct sockaddr_in addr4;
575+
memset(&addr4, 0, sizeof(addr4));
576+
addr4.sin_family = AF_INET;
577+
addr4.sin_port = saddr6->sin6_port;
578+
memcpy(&addr4.sin_addr.s_addr, saddr6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
579+
return IPAddress((uint32_t)(addr4.sin_addr.s_addr));
580+
}
581+
log_e("WiFiClient::remoteIP IPv6 to IPv4 cannot convert");
582+
return (IPAddress(0,0,0,0));
583+
}
584+
log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?");
585+
return (IPAddress(0,0,0,0));
586+
}
587+
588+
IPv6Address WiFiClient::remoteIP6(int fd) const
589+
{
590+
struct sockaddr_storage addr;
591+
socklen_t len = sizeof addr;
592+
getpeername(fd, (struct sockaddr*)&addr, &len);
593+
594+
// IPv4 socket we can print as IPv6 mapped
595+
if (((struct sockaddr*)&addr)->sa_family == AF_INET) {
596+
uint8_t buffer[16] = { 0 };
597+
buffer[10] = 0xFF;
598+
buffer[11] = 0xFF;
599+
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
600+
memcpy(&buffer[12], (uint8_t*)&s->sin_addr.s_addr, 4);
601+
return IPv6Address(buffer);
602+
}
603+
// IPv6
604+
if (((struct sockaddr*)&addr)->sa_family == AF_INET6) {
605+
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr;
606+
return (IPv6Address(saddr6->sin6_addr.s6_addr));
607+
}
608+
log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?");
609+
return (IPv6Address());
566610
}
567611

568612
uint16_t WiFiClient::remotePort(int fd) const
@@ -579,6 +623,11 @@ IPAddress WiFiClient::remoteIP() const
579623
return remoteIP(fd());
580624
}
581625

626+
IPv6Address WiFiClient::remoteIP6() const
627+
{
628+
return remoteIP6(fd());
629+
}
630+
582631
uint16_t WiFiClient::remotePort() const
583632
{
584633
return remotePort(fd());

Diff for: libraries/WiFi/src/WiFiClient.h

+7
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class WiFiClient : public ESPLwIPClient
9595

9696
IPAddress remoteIP() const;
9797
IPAddress remoteIP(int fd) const;
98+
IPv6Address remoteIP6() const;
99+
IPv6Address remoteIP6(int fd) const;
98100
uint16_t remotePort() const;
99101
uint16_t remotePort(int fd) const;
100102
IPAddress localIP() const;
@@ -106,4 +108,9 @@ class WiFiClient : public ESPLwIPClient
106108
using Print::write;
107109
};
108110

111+
#define IN6_IS_ADDR_V4MAPPED(a) \
112+
((((__const uint32_t *) (a))[0] == 0) \
113+
&& (((__const uint32_t *) (a))[1] == 0) \
114+
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))
115+
109116
#endif /* _WIFICLIENT_H_ */

Diff for: libraries/WiFi/src/WiFiMulti.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
WiFiMulti::WiFiMulti()
3232
{
33-
ipv6_support = false;
3433
}
3534

3635
WiFiMulti::~WiFiMulti()

0 commit comments

Comments
 (0)