|
23 | 23 | #include <lwip/netdb.h>
|
24 | 24 | #include <errno.h>
|
25 | 25 |
|
| 26 | +#define IN6_IS_ADDR_V4MAPPED(a) \ |
| 27 | + ((((__const uint32_t *) (a))[0] == 0) \ |
| 28 | + && (((__const uint32_t *) (a))[1] == 0) \ |
| 29 | + && (((__const uint32_t *) (a))[2] == htonl (0xffff))) |
| 30 | + |
26 | 31 | #define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000)
|
27 | 32 | #define WIFI_CLIENT_MAX_WRITE_RETRY (10)
|
28 | 33 | #define WIFI_CLIENT_SELECT_TIMEOUT_US (1000000)
|
@@ -562,8 +567,24 @@ IPAddress WiFiClient::remoteIP(int fd) const
|
562 | 567 | struct sockaddr_storage addr;
|
563 | 568 | socklen_t len = sizeof addr;
|
564 | 569 | getpeername(fd, (struct sockaddr*)&addr, &len);
|
565 |
| - struct sockaddr_in *s = (struct sockaddr_in *)&addr; |
566 |
| - return IPAddress((uint32_t)(s->sin_addr.s_addr)); |
| 570 | + |
| 571 | + // IPv4 socket, old way |
| 572 | + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { |
| 573 | + struct sockaddr_in *s = (struct sockaddr_in *)&addr; |
| 574 | + return IPAddress((uint32_t)(s->sin_addr.s_addr)); |
| 575 | + } |
| 576 | + |
| 577 | + // IPv6, but it might be IPv4 mapped address |
| 578 | + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { |
| 579 | + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; |
| 580 | + if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { |
| 581 | + return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12); |
| 582 | + } else { |
| 583 | + return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr)); |
| 584 | + } |
| 585 | + } |
| 586 | + log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); |
| 587 | + return (IPAddress(0,0,0,0)); |
567 | 588 | }
|
568 | 589 |
|
569 | 590 | uint16_t WiFiClient::remotePort(int fd) const
|
|
0 commit comments