12#if DETWS_ENABLE_DNS_SERVER
19bool ci_eq(
const char *a,
const char *b)
25 if (ca >=
'A' && ca <=
'Z')
27 if (cb >=
'A' && cb <=
'Z')
39bool parse_question(
const uint8_t *q,
size_t qlen,
char *name,
size_t name_cap, uint16_t *qtype,
size_t *qend)
60 if (n + 1 >= name_cap)
64 for (uint8_t k = 0; k < len; k++)
66 if (n + 1 >= name_cap)
68 name[n++] = (char)q[i++];
74 *qtype = (uint16_t)((q[i] << 8) | q[i + 1]);
83 if (!query || !out || !resolve || qlen < 12)
87 uint8_t opcode = (uint8_t)((query[2] >> 3) & 0xF);
92 memcpy(out, query, 12);
93 out[2] = (uint8_t)(0x84 | (query[2] & 0x01));
96 out[8] = out[9] = out[10] = out[11] = 0;
103 if (!parse_question(query, qlen, name,
sizeof(name), &qtype, &qend))
108 memcpy(out, query, qend);
109 out[2] = (uint8_t)(0x84 | (query[2] & 0x01));
113 out[8] = out[9] = out[10] = out[11] = 0;
115 uint32_t ip = (qtype == 1) ? resolve(name) : 0;
120 out[3] = (qtype == 1) ? 0x03 : 0;
124 if (qend + 16 > out_cap)
135 out[n++] = (uint8_t)(ttl >> 24);
136 out[n++] = (uint8_t)(ttl >> 16);
137 out[n++] = (uint8_t)(ttl >> 8);
138 out[n++] = (uint8_t)ttl;
141 out[n++] = (uint8_t)(ip >> 24);
142 out[n++] = (uint8_t)(ip >> 16);
143 out[n++] = (uint8_t)(ip >> 8);
144 out[n++] = (uint8_t)ip;
165bool dns_server_add(
const char *name, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
167 if (!name || !name[0])
174 memcpy(s_dns.names[s_dns.count], name, nlen + 1);
175 s_dns.ips[s_dns.count] = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d;
184 for (
size_t i = 0; i < s_dns.count; i++)
185 if (ci_eq(s_dns.names[i], name))
201void dns_server_udp_handler(
const uint8_t *data,
size_t len,
struct DetUdpPeer *peer,
void *ctx)
User-facing configuration for DeterministicESPAsyncWebServer.
#define DETWS_DNS_SERVER_MAX_RECORDS
Max A records in the DNS server's fixed table.
#define DETWS_DNS_SERVER_TTL
TTL (seconds) the DNS server puts on its answers.
#define DETWS_DNS_NAME_MAX
Max length of a queried/stored DNS name (bytes, incl NUL).
Authoritative DNS server (UDP/53) - resolve local names on an offline LAN.
uint32_t(* DnsResolveFn)(const char *name)
Resolve a queried name to an IPv4 address.
size_t dns_server_build_response(const uint8_t *query, size_t qlen, uint32_t ttl, DnsResolveFn resolve, uint8_t *out, size_t out_cap)
Build a DNS reply to query. Pure - no clock, no I/O.
bool dns_server_add(const char *name, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
Add an A record to the built-in table (case-insensitive name).
bool dns_server_begin()
Start answering DNS queries on UDP/53 from the built-in table.
uint32_t dns_server_lookup(const char *name)
Look name up in the built-in table.
void dns_server_clear()
Remove every record from the built-in table.
bool det_udp_send(struct DetUdpPeer *peer, const uint8_t *data, size_t len)
Send a datagram back to the peer captured during the handler call.
bool det_udp_listen(uint16_t port, DetUdpHandler handler, void *ctx)
Bind a UDP port and route incoming datagrams to handler.
Layer 4 (Transport) - connectionless UDP datagram service.