Page 1 of 1

Function getpeername() doesn't work, trying to determine remote IP Address

Posted: Tue Dec 04, 2018 7:56 pm
by mikea101
Hi,

I'm trying to determine the remote IP of a browser connected to the HTTP server (httpd).

When I use the function getpeername() to get the IP address of the remote client browser it is always "0.0.0.0" (which is wrong).

Code: Select all

esp_err_t MyHttpHandler(httpd_req_t *req)
{
	int len = 0;
	char buf[200];

	int socket = httpd_req_to_sockfd(req); // This is the socket for the request

	struct sockaddr_in saddr; // expecting an IPv4 address
	memset(&saddr, 0, sizeof(saddr)); // Clear it to be sure
	socklen_t saddr_len = sizeof(saddr);

	if(getpeername(socket, (struct sockaddr *)&saddr, &saddr_len) == 0)
	{
		len += sprintf(&buf[len], "\n\t\"remip\":\"%s\"", inet_ntoa(saddr.sin_addr));
		len += sprintf(&buf[len], "\n\t\"remport\":%d",       htons(saddr.sin_port));
	}

	httpd_resp_send(req, buf, len);
	return ESP_OK;
}
Results in this:

Code: Select all

	"remip":"0.0.0.0"
	"remport":65198
The port seems to be OK but the ip is not.

Please advise: either a solution for getpeername or another solution that will get me the remote IP.

Thanks.

Re: Function getpeername() doesn't work, trying to determine remote IP Address

Posted: Mon Dec 17, 2018 5:48 pm
by henk-iot
To me this does not look like an esp-idf bug.

I ran into the same problem on both getpeername and getsockname.
It seems the esp_http_server always starts its listener using IPV6 (which is hardcoded in esp-idf), so you cannot use the IPV4 macros on the getpeername/getsockname calls. So struct sockaddr_in is the wrong structure to use in this case.

Using struct sockaddr_in6 instead worked for me.
So after:
struct sockaddr_in6 destAddr;
unsigned socklen=sizeof(destAddr);

if(getpeername(sockfd, (struct sockaddr *)&destAddr, &socklen)<0) {
ESP_LOGE(TAG, "getpeername failed, errno:%d",errno);
}

I did get the correct (ipv4 part of) the address in destAddr.sin6_addr.un.u32_addr[3]

R Henk.