102 lines
2.6 KiB
C
102 lines
2.6 KiB
C
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "lwip/sockets.h"
|
|
#include "lwip/inet.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "esp_log.h"
|
|
#include "dns_server.h"
|
|
|
|
static const char *TAG = "DNS";
|
|
#define DNS_PORT 53
|
|
|
|
static TaskHandle_t s_dns_task = NULL;
|
|
static volatile bool s_dns_running = false;
|
|
|
|
static void dns_task(void *arg)
|
|
{
|
|
(void)arg;
|
|
|
|
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
if (sock < 0) {
|
|
ESP_LOGE(TAG, "❌ socket DNS falhou");
|
|
s_dns_running = false;
|
|
s_dns_task = NULL;
|
|
vTaskDelete(NULL);
|
|
return;
|
|
}
|
|
|
|
int yes = 1;
|
|
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
|
|
|
|
struct sockaddr_in addr = {0};
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(DNS_PORT);
|
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
|
ESP_LOGE(TAG, "❌ bind DNS falhou (porta %d)", DNS_PORT);
|
|
close(sock);
|
|
s_dns_running = false;
|
|
s_dns_task = NULL;
|
|
vTaskDelete(NULL);
|
|
return;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "✅ DNS captive a correr na porta %d (task)", DNS_PORT);
|
|
|
|
while (s_dns_running) {
|
|
uint8_t buf[512];
|
|
struct sockaddr_in source_addr = {0};
|
|
socklen_t slen = sizeof(source_addr);
|
|
|
|
int len = recvfrom(sock, buf, sizeof(buf), 0,
|
|
(struct sockaddr*)&source_addr, &slen);
|
|
|
|
if (len <= 0) {
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
continue;
|
|
}
|
|
|
|
buf[2] |= 0x80; // resposta
|
|
buf[3] |= 0x80; // RA
|
|
buf[6] = 0x00;
|
|
buf[7] = 0x01; // ANCOUNT=1
|
|
|
|
if (len + 16 < (int)sizeof(buf)) {
|
|
buf[len++] = 0xC0; buf[len++] = 0x0C;
|
|
buf[len++] = 0x00; buf[len++] = 0x01;
|
|
buf[len++] = 0x00; buf[len++] = 0x01;
|
|
buf[len++] = 0x00; buf[len++] = 0x00;
|
|
buf[len++] = 0x00; buf[len++] = 0x3C;
|
|
buf[len++] = 0x00; buf[len++] = 0x04;
|
|
buf[len++] = 192; buf[len++] = 168;
|
|
buf[len++] = 4; buf[len++] = 1;
|
|
|
|
sendto(sock, buf, len, 0, (struct sockaddr*)&source_addr, slen);
|
|
}
|
|
}
|
|
|
|
close(sock);
|
|
s_dns_task = NULL;
|
|
ESP_LOGI(TAG, "DNS task terminou");
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void start_dns_server(void)
|
|
{
|
|
if (s_dns_task) {
|
|
ESP_LOGW(TAG, "DNS já está a correr");
|
|
return;
|
|
}
|
|
s_dns_running = true;
|
|
xTaskCreate(dns_task, "dns_task", 4096, NULL, 4, &s_dns_task);
|
|
ESP_LOGI(TAG, "✅ DNS captive portal iniciado na porta %d", DNS_PORT);
|
|
}
|
|
|
|
void stop_dns_server(void)
|
|
{
|
|
s_dns_running = false;
|
|
}
|