mudfish_dns_module.h
Pobierz mudfish_dns_module.h i umieść go w tym samym katalogu co źródło C modułu. Poniżej znajduje się pełny nagłówek udostępniany przez Mudfish DNS, wraz z deklaracjami zgodności. Dla modułów opisanych w tym przewodniku używaj C ABI v2.
Przykład policy.c zawiera polecenia budowania i przykłady działań DNS. Ładowanie modułów, działanie hooków i reguły własności buforów opisano w modułach natywnych.
Typy używane przez moduły v2
| Typ | Zastosowanie |
|---|---|
mudfish_dns_span | Wskaźnik i długość pożyczonych danych wejściowych lub odpowiedzi zastępczej należącej do modułu. Ciągi nie są zakończone NUL. |
mudfish_dns_event | Dane zapytania i odpowiedzi DNS w formacie transmisyjnym, źródło odpowiedzi, pierwotny cel i bieżący stan polityki domen. |
mudfish_dns_web_event | Dane WWW, Host/SNI, cel, protokół, kierunek i bieżący stan polityki domen. Dane HTTPS pozostają zaszyfrowane. |
mudfish_dns_result | Działanie DNS i opcjonalny adres odpowiedzi, TTL lub odpowiedź zastępcza. |
mudfish_dns_module_v2 | Kontekst modułu, opcjonalne callbacki DNS i WWW oraz callback porządkowania zasobów. |
Wyeksportuj mudfish_dns_module_init_v2() z poniższą sygnaturą. Host zaczyna z wszystkimi polami modułu ustawionymi na NULL. Przed zapisem sprawdź wersję ABI i rozmiar struktury. Nieużywane hooki pozostaw jako NULL, a przy powodzeniu zwróć 0.
Jeśli inicjalizacja się nie powiedzie, sam zwolnij przydzielone zasoby. Po pomyślnej inicjalizacji host wywoła destroy() jeden raz, gdy moduł przestanie być używany, przed wyładowaniem biblioteki. Zatrzymaj tam wątki należące do modułu i poczekaj na ich zakończenie.
Pełny nagłówek
#ifndef MUDFISH_DNS_MODULE_H
#define MUDFISH_DNS_MODULE_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MUDFISH_DNS_MODULE_ABI_V1 1
#define MUDFISH_DNS_MODULE_ABI_V2 2
#define MUDFISH_DNS_CONTINUE 0
#define MUDFISH_DNS_REJECT 1
#define MUDFISH_DNS_BLOCK MUDFISH_DNS_REJECT
#define MUDFISH_DNS_ALLOW 2
#define MUDFISH_DNS_DROP 3
#define MUDFISH_DNS_ANSWER 4
#define MUDFISH_DNS_REPLACE 5
#define MUDFISH_DNS_IPV4 4
#define MUDFISH_DNS_IPV6 6
#define MUDFISH_DNS_SOURCE_QUERY 0
#define MUDFISH_DNS_SOURCE_UPSTREAM 1
#define MUDFISH_DNS_SOURCE_CACHE 2
#define MUDFISH_DNS_SOURCE_ORIGINAL 3
#define MUDFISH_DNS_SOURCE_ERROR 4
#define MUDFISH_DNS_SOURCE_MODULE 5
#define MUDFISH_DNS_WEB_UNKNOWN 0
#define MUDFISH_DNS_WEB_HTTP 1
#define MUDFISH_DNS_WEB_HTTPS 2
#define MUDFISH_DNS_TO_SERVER 1
#define MUDFISH_DNS_TO_CLIENT 2
/* Input spans are borrowed for this callback only; strings are not NUL terminated.
* Empty spans have length zero and must not be dereferenced. Never mutate, free,
* or retain any host pointer. DNS messages use wire format without TCP framing.
*/
struct mudfish_dns_span {
const uint8_t *data;
size_t len;
};
struct mudfish_dns_event {
struct mudfish_dns_span query;
struct mudfish_dns_span response; /* Empty in on_dns_query. */
struct mudfish_dns_span original_destination; /* IP:port, empty for loopback. */
uint32_t source;
uint32_t applied; /* Existing domain policy selects protected resolution. */
};
struct mudfish_dns_web_event {
struct mudfish_dns_span data;
struct mudfish_dns_span hostname; /* Normalized Host/SNI, or empty. */
struct mudfish_dns_span destination; /* IP:port. */
uint32_t protocol;
uint32_t direction;
uint32_t applied; /* Existing domain policy selects web protection. */
};
/* Return CONTINUE or REJECT. Any other value fails the request/connection.
* Hooks run in load order and stop at the first non-CONTINUE result.
* Calls for one module instance are serialized, but may use different threads.
* Hooks must finish promptly, must not unwind/longjmp across the ABI, and must
* not call back into the host. HTTPS data is encrypted; no TLS termination.
*/
struct mudfish_dns_module_v1 {
void *context;
int32_t (*on_dns_query)(void *, const struct mudfish_dns_event *);
int32_t (*on_dns_response)(void *, const struct mudfish_dns_event *);
int32_t (*on_web_hello)(void *, const struct mudfish_dns_web_event *);
int32_t (*on_web_data)(void *, const struct mudfish_dns_web_event *);
void (*destroy)(void *);
};
/* Export this exact symbol. The host initializes all fields to NULL.
* Check abi_version and module_size before writing. NULL hooks are optional.
* The output pointer is valid only during init. Return zero on success.
* On failure, clean up your own resources; the host will not call destroy.
* On success, destroy runs once after all users finish, before dlclose. Any
* module-owned threads must stop/join in destroy. Module code runs with the
* service's privileges and must satisfy this contract, including constructors.
*/
int32_t mudfish_dns_module_init_v1(uint32_t abi_version, size_t module_size,
struct mudfish_dns_module_v1 *module);
/* DNS v2 hooks return zero on success, nonzero on error (SERVFAIL).
* The host zeroes result before each call. Set action to:
* CONTINUE: consult the next module, then use the existing resolution/response.
* ALLOW: stop this hook chain and use the existing resolution/response.
* BLOCK: stop this hook chain and return REFUSED.
* DROP: discard this query/response without sending any DNS response.
* ANSWER: replace the response with the IP below, without upstream resolution
* when used in on_dns_query. IPv4 produces A, IPv6 produces AAAA.
* Other question types/classes get empty NOERROR (including an address
* family mismatch); IN/ANY gets the selected address record.
* REPLACE: use result.response as the complete DNS wire response. Valid in
* either DNS hook. The ID, opcode and question must match the query.
* Unknown actions or invalid ANSWER address families fail with SERVFAIL.
* Query results except DROP still pass through the response hook chain.
* Response decisions are final and never invoke response hooks recursively.
* Synthetic/replaced responses are not stored in the host cache.
* The host clears AD on replacements; modules must remove stale DNSSEC records
* when modifying signed data. The host does not re-sign or validate DNSSEC.
* DROP leaves TCP open for subsequent queries, subject to the normal timeout.
* ALLOW does not change domain policy, upstream selection or transport checks.
* All v1 lifetime/threading rules apply; result is writable only during the
* callback and must not be retained. Web hooks retain v1 return semantics.
*/
struct mudfish_dns_result {
uint32_t action;
uint32_t ttl; /* ANSWER: seconds, zero is allowed. */
uint32_t address_family; /* ANSWER: MUDFISH_DNS_IPV4 or MUDFISH_DNS_IPV6. */
uint8_t address[16]; /* Network byte order; IPv4 uses the first 4 bytes. */
/* REPLACE: module-owned wire response (12..65535 bytes, no TCP framing).
* Must remain valid and unchanged until the next callback on this instance
* or destroy; do not return stack memory or an event's borrowed pointer.
* The host copies before unlocking the instance and never frees this span.
*/
struct mudfish_dns_span response;
};
struct mudfish_dns_module_v2 {
void *context;
int32_t (*on_dns_query)(void *, const struct mudfish_dns_event *,
struct mudfish_dns_result *);
int32_t (*on_dns_response)(void *, const struct mudfish_dns_event *,
struct mudfish_dns_result *);
int32_t (*on_web_hello)(void *, const struct mudfish_dns_web_event *);
int32_t (*on_web_data)(void *, const struct mudfish_dns_web_event *);
void (*destroy)(void *);
};
/* Same initialization contract as v1, with ABI_V2 and sizeof(module_v2).
* The host prefers v2 if exported, otherwise loads v1. A failed v2 init is fatal
* and does not fall back to v1. Existing v1 modules need no changes.
*/
int32_t mudfish_dns_module_init_v2(uint32_t abi_version, size_t module_size,
struct mudfish_dns_module_v2 *module);
#ifdef __cplusplus
}
#endif
#endif