Skip to content

Commit

Permalink
WiFiClient::remoteIP and remoteIP6 IPv6 support
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
nuclearcat committed May 8, 2022
1 parent 4735f66 commit e8711c0
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 3 deletions.
1 change: 1 addition & 0 deletions cores/esp32/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "Print.h"
#include "Stream.h"
#include "IPAddress.h"
#include "IPv6Address.h"

class Client: public Stream
{
Expand Down
53 changes: 51 additions & 2 deletions libraries/WiFi/src/WiFiClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,52 @@ IPAddress WiFiClient::remoteIP(int fd) const
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
getpeername(fd, (struct sockaddr*)&addr, &len);
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
return IPAddress((uint32_t)(s->sin_addr.s_addr));

// Old way, IPv4
if (((struct sockaddr*)&addr)->sa_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
return IPAddress((uint32_t)(s->sin_addr.s_addr));
}
// IPv6, but it might be IPv4 mapped address
if (((struct sockaddr*)&addr)->sa_family == AF_INET6) {
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) {
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(addr4));
addr4.sin_family = AF_INET;
addr4.sin_port = saddr6->sin6_port;
memcpy(&addr4.sin_addr.s_addr, saddr6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
return IPAddress((uint32_t)(addr4.sin_addr.s_addr));
}
log_e("WiFiClient::remoteIP IPv6 to IPv4 cannot convert");
return (IPAddress(0,0,0,0));
}
log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?");
return (IPAddress(0,0,0,0));
}

IPv6Address WiFiClient::remoteIP6(int fd) const
{
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
getpeername(fd, (struct sockaddr*)&addr, &len);

// IPv4 socket we can print as IPv6 mapped
if (((struct sockaddr*)&addr)->sa_family == AF_INET) {
uint8_t buffer[16] = { 0 };
buffer[10] = 0xFF;
buffer[11] = 0xFF;
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
memcpy(&buffer[12], (uint8_t*)&s->sin_addr.s_addr, 4);
return IPv6Address(buffer);
}
// IPv6
if (((struct sockaddr*)&addr)->sa_family == AF_INET6) {
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr;
return (IPv6Address(saddr6->sin6_addr.s6_addr));
}
log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?");
return (IPv6Address());
}

uint16_t WiFiClient::remotePort(int fd) const
Expand All @@ -579,6 +623,11 @@ IPAddress WiFiClient::remoteIP() const
return remoteIP(fd());
}

IPv6Address WiFiClient::remoteIP6() const
{
return remoteIP6(fd());
}

uint16_t WiFiClient::remotePort() const
{
return remotePort(fd());
Expand Down
7 changes: 7 additions & 0 deletions libraries/WiFi/src/WiFiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class WiFiClient : public ESPLwIPClient

IPAddress remoteIP() const;
IPAddress remoteIP(int fd) const;
IPv6Address remoteIP6() const;
IPv6Address remoteIP6(int fd) const;
uint16_t remotePort() const;
uint16_t remotePort(int fd) const;
IPAddress localIP() const;
Expand All @@ -106,4 +108,9 @@ class WiFiClient : public ESPLwIPClient
using Print::write;
};

#define IN6_IS_ADDR_V4MAPPED(a) \
((((__const uint32_t *) (a))[0] == 0) \
&& (((__const uint32_t *) (a))[1] == 0) \
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))

#endif /* _WIFICLIENT_H_ */
1 change: 0 additions & 1 deletion libraries/WiFi/src/WiFiMulti.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

WiFiMulti::WiFiMulti()
{
ipv6_support = false;
}

WiFiMulti::~WiFiMulti()
Expand Down

0 comments on commit e8711c0

Please sign in to comment.