Page 1 of 1

Problem with socket leak

Posted: Wed Nov 24, 2021 1:29 pm
by qaqa85
Hello guys,

I have a little problem with closing task and socket. I found little library to make dns hijack serwer.

My steps
1. call dns_hijack_srv_start to start DNS serwer. (everything works fine - can make TCP connection)
2. call dns_hijack_srv_stop to stop DNS server
3. call dns_hijack_srv_start to start DNS serwer. - and now i cant make TCP connection (httpd_accept_conn: error in accept (23))

Everything works fine also when i just dont stop DNS serwer. I really don't know what is wrong with function dns_hijack_srv_stop.

I'm grateful for any of your help guys!

Code: Select all

#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_event.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>

#include <byteswap.h>

#include "dns_hijack_srv.h"
static const char *TAG = "KOSA";
#define KOSA_LOG( tag, format, ... ) ESP_LOGE( tag, format, ##__VA_ARGS__)
static dns_hijack_srv_handle_t dns_hijack_srv_handle;

static esp_err_t dns_hijack_srv_cleanup();

static void dns_hijack_srv_task(void *pvParameters) {
    uint8_t rx_buffer[128];

    for(;;) {
        struct sockaddr_in dest_addr;

        dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(53);

        int sock = dns_hijack_srv_handle.sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

        if(sock < 0) {
        	KOSA_LOG(TAG, "Unable to create socket - Hijacked");
            break;
        }

        KOSA_LOG(TAG, "Socket created - Hijacked");

        int err = bind(sock, (struct sockaddr*) &dest_addr, sizeof(dest_addr));

        if(err < 0) {
        	KOSA_LOG(TAG, "Socket unable to bind - Hijacked");
            break;
        }
        
        KOSA_LOG(TAG, "Listening... - Hijacked");

        for(;;) {
            struct sockaddr_in source_addr;
            socklen_t socklen = sizeof(source_addr);

            memset(rx_buffer, 0x00, sizeof(rx_buffer));
            int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer), 0, (struct sockaddr*) &source_addr, &socklen);

            if(len < 0) {
            	KOSA_LOG(TAG, "revfrom failed - Hijacked");
                break;
            }

            if(len > DNS_HIJACK_SRV_HEADER_SIZE + DNS_HIJACK_SRV_QUESTION_MAX_LENGTH) {
            	KOSA_LOG(TAG, "Received more data [%d] than expected. Ignoring. - Hijacked", len);
                continue;
            }

            // Nul termination. To prevent pointer escape
            rx_buffer[sizeof(rx_buffer) - 1] = '\0';

            dns_header_t *header = (dns_header_t*) rx_buffer;

            header->QR      = 1;
            header->OPCODE  = 0;
            header->AA      = 1;
            header->RCODE   = 0;
            header->TC      = 0;
            header->Z       = 0;
            header->RA      = 0;
            header->ANCOUNT = header->QDCOUNT;
            header->NSCOUNT = 0;
            header->ARCOUNT = 0;

            // ptr points to the beginning of the QUESTION
            uint8_t *ptr = rx_buffer + sizeof(dns_header_t);

            // Jump over QNAME
            while(*ptr++);

            // Jump over QTYPE
            ptr += 2;

            // Jump over QCLASS
            ptr += 2;

            dns_hijack_answer_t *answer = (dns_hijack_answer_t*) ptr;

            answer->NAME     = __bswap_16(0xC00C);
            answer->TYPE     = __bswap_16(1);
            answer->CLASS    = __bswap_16(1);
            answer->TTL      = 0;
            answer->RDLENGTH = __bswap_16(4);
            answer->RDATA    = dns_hijack_srv_handle.resolve_ip.addr;

            // Jump over ANSWER
            ptr += sizeof(dns_hijack_answer_t);

            int err = sendto(sock, rx_buffer, ptr - rx_buffer, 0, (struct sockaddr *)&source_addr, sizeof(source_addr));

            if (err < 0) {
            	KOSA_LOG(TAG, "Error occurred during sending - Hijacked");
                break;
            }

            taskYIELD();
        }

        if(sock != -1) {
            dns_hijack_srv_cleanup();
            KOSA_LOG(TAG, "Restarting... Hijacked");
        }
    }

    dns_hijack_srv_stop();
}

static esp_err_t dns_hijack_srv_cleanup() {
	KOSA_LOG(TAG, "Cleanup - Hijacked");

    if(dns_hijack_srv_handle.sockfd != -1) {
        shutdown(dns_hijack_srv_handle.sockfd, 0);
        close(dns_hijack_srv_handle.sockfd);
        KOSA_LOG(TAG, "dns_hijack_closed socket! - Hijacked");
        dns_hijack_srv_handle.sockfd = -1;
    }

    return ESP_OK;
}

esp_err_t dns_hijack_srv_start(const ip4_addr_t resolve_ip_addr) {
    if(dns_hijack_srv_handle.task_handle != NULL) {
        return ESP_OK;
    }

    dns_hijack_srv_handle.resolve_ip = resolve_ip_addr;
    dns_hijack_srv_handle.sockfd = -1;
    
    KOSA_LOG(TAG, "Resolve IP: "IPSTR,
        ip4_addr1(&resolve_ip_addr),
        ip4_addr2(&resolve_ip_addr), 
        ip4_addr3(&resolve_ip_addr),
        ip4_addr4(&resolve_ip_addr));

    xTaskCreate(dns_hijack_srv_task, "dns_hijack_srv", 4096, NULL, 5, &dns_hijack_srv_handle.task_handle);
    return ESP_OK;
}

esp_err_t dns_hijack_srv_stop() {
	if (dns_hijack_srv_handle.task_handle != NULL)
	{
		 vTaskDelete(dns_hijack_srv_handle.task_handle);
		 dns_hijack_srv_handle.task_handle = NULL;
		 KOSA_LOG(TAG, "vTaskDelate - Hijacked");
	}
    dns_hijack_srv_cleanup();
    KOSA_LOG(TAG, "Server stoped.");

    return ESP_OK;
}

Re: Problem with socket leak

Posted: Thu Nov 25, 2021 11:10 am
by ESP_YJM
error in accept (23) means no avaliable socket can be allocated.You can increass socket number by CONFIG_LWIP_MAX_SOCKETS.

Re: Problem with socket leak

Posted: Thu Nov 25, 2021 12:26 pm
by qaqa85
ESP_YJM wrote:
Thu Nov 25, 2021 11:10 am
error in accept (23) means no avaliable socket can be allocated.You can increass socket number by CONFIG_LWIP_MAX_SOCKETS.
Thanks for answear. I know that. I can start dns server + create socket but when I close it and then want to strat again i got error in accept 23. Its seems to be a socket leak. But i don't know why. Code looks fine for me. Sorry for bad english.

Re: Problem with socket leak

Posted: Fri Nov 26, 2021 2:11 am
by ESP_YJM