Files
SC-F001/main/simple_dns_server.c
Thaddeus Hughes 49e728ec2b storage overhaul
needs tested tho
2026-01-06 17:01:50 -06:00

143 lines
3.8 KiB
C

#include "simple_dns_server.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>
static const char *TAG = "DNS_SERVER";
static int dns_socket = -1;
static TaskHandle_t dns_task_handle = NULL;
static char dns_ip[16] = {0};
// DNS header structure
typedef struct {
uint16_t id;
uint16_t flags;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
} dns_header_t;
static void dns_server_task(void *pvParameters) {
char rx_buffer[512];
char tx_buffer[512];
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);
dns_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (dns_socket < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
vTaskDelete(NULL);
return;
}
int err = bind(dns_socket, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0) {
ESP_LOGE(TAG, "Socket bind failed: errno %d", errno);
close(dns_socket);
vTaskDelete(NULL);
return;
}
ESP_LOGI(TAG, "DNS server started on port 53");
while (1) {
struct sockaddr_in source_addr;
socklen_t socklen = sizeof(source_addr);
int len = recvfrom(dns_socket, rx_buffer, sizeof(rx_buffer) - 1, 0,
(struct sockaddr *)&source_addr, &socklen);
if (len < 0) {
ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
break;
}
if (len < sizeof(dns_header_t)) {
continue;
}
// Parse DNS query (unused)
// dns_header_t *header = (dns_header_t *)rx_buffer;
// Build DNS response
memcpy(tx_buffer, rx_buffer, len);
dns_header_t *response = (dns_header_t *)tx_buffer;
// Set response flags
response->flags = htons(0x8180); // Standard query response, no error
response->ancount = htons(1); // One answer
// Add answer section (Type A record)
int pos = len;
// Name pointer to question
tx_buffer[pos++] = 0xC0;
tx_buffer[pos++] = 0x0C;
// Type A
tx_buffer[pos++] = 0x00;
tx_buffer[pos++] = 0x01;
// Class IN
tx_buffer[pos++] = 0x00;
tx_buffer[pos++] = 0x01;
// TTL (60 seconds)
tx_buffer[pos++] = 0x00;
tx_buffer[pos++] = 0x00;
tx_buffer[pos++] = 0x00;
tx_buffer[pos++] = 0x3C;
// Data length (4 bytes for IPv4)
tx_buffer[pos++] = 0x00;
tx_buffer[pos++] = 0x04;
// IP address
int a, b, c, d;
sscanf(dns_ip, "%d.%d.%d.%d", &a, &b, &c, &d);
tx_buffer[pos++] = a;
tx_buffer[pos++] = b;
tx_buffer[pos++] = c;
tx_buffer[pos++] = d;
// Send response
sendto(dns_socket, tx_buffer, pos, 0,
(struct sockaddr *)&source_addr, sizeof(source_addr));
}
close(dns_socket);
dns_socket = -1;
vTaskDelete(NULL);
}
esp_err_t simple_dns_server_start(const char *ap_ip) {
if (dns_task_handle != NULL) {
ESP_LOGW(TAG, "DNS server already running");
return ESP_ERR_INVALID_STATE;
}
strncpy(dns_ip, ap_ip, sizeof(dns_ip) - 1);
xTaskCreate(dns_server_task, "dns_server", 4096, NULL, 5, &dns_task_handle);
return ESP_OK;
}
void simple_dns_server_stop(void) {
if (dns_task_handle != NULL) {
if (dns_socket >= 0) {
close(dns_socket);
dns_socket = -1;
}
vTaskDelete(dns_task_handle);
dns_task_handle = NULL;
ESP_LOGI(TAG, "DNS server stopped");
}
}