From: Michael Tremer Date: Mon, 11 May 2026 14:05:57 +0000 (+0000) Subject: main: Build out fetching zone data X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f85186b21549625b72a4988d82092c6e2d88aa96;p=zone-sync.git main: Build out fetching zone data This is just about working, but needs a lot more to be robust. Signed-off-by: Michael Tremer --- diff --git a/main.c b/main.c index b3120b9..f712534 100644 --- a/main.c +++ b/main.c @@ -22,12 +22,19 @@ #include #include +#include #include +#include +#include +#include +#include +#include #include #include #include #include +#include #define DEFAULT_PATH "/tmp" @@ -52,6 +59,18 @@ typedef struct ctx { // Network Manager isc_nm_t* netmgr; + + // Zone Manager + dns_zonemgr_t* zonemgr; + + // Dispatch Manager + dns_dispatchmgr_t* dispatchmgr; + + // View + dns_view_t* view; + + // TLS Context Cache + isc_tlsctx_cache_t* tlsctx_cache; } ctx_t; // Create the context @@ -132,25 +151,233 @@ static void setup_logging(void) { /* Tell libdns to register its categories/modules * with this log context, and use it as default */ dns_log_init(ctx.log); - dns_log_setcontext(ctx.log); + //dns_log_setcontext(ctx.log); /* Also make libisc itself use it */ isc_log_setcontext(ctx.log); } -static void do_zone(ctx_t* ctx, const char* name) { - DEBUG(ctx, "Processing zone %s\n", name); +static void transfer_done(dns_zone_t* zone, uint32_t* serial, isc_result_t result) { + int r; + + switch (result) { + case ISC_R_SUCCESS: + DEBUG("Transfer successful\n"); + + // Commit any changes + r = dns_zone_flush(zone); + if (r) { + ERROR("Failed to flush zone\n"); + } + break; + + case DNS_R_UPTODATE: + DEBUG("Zone is up to date\n"); + break; + + default: + ERROR("Zone transfer failed\n"); + break; + } + + // Release the zone from the manager + dns_zonemgr_releasezone(ctx.zonemgr, zone); - // XXX TODO + // Free the zone + dns_zone_detach(&zone); +} + +static int do_transfer(dns_zone_t* zone, uint32_t serial) { + dns_xfrin_t* xfrin = NULL; + isc_sockaddr_t primary; + dns_rdatatype_t xfrtype; + + // Try an incremental xfr if we have a serial + if (serial) { + DEBUG("Zone is at serial %d, trying IXFR\n", serial); + xfrtype = dns_rdatatype_soa; + + // Otherwise force AXFR + } else { + DEBUG("No serial for zone, doing AXFR\n"); + xfrtype = dns_rdatatype_axfr; + } + + struct in_addr a; + inet_pton(AF_INET, "81.3.27.55", &a); + isc_sockaddr_fromin(&primary, &a, 53); + + isc_sockaddr_t source; + struct in_addr any = { .s_addr = INADDR_ANY }; + isc_sockaddr_fromin(&source, &any, 0); + + // Require at least 10 kBit/s to be transmitted over 5 minutes + dns_zone_setminxfrratein(zone, 10240, 300); + + dns_xfrin_create(zone, xfrtype, &primary, &source, NULL, + DNS_TRANSPORT_NONE, NULL, ctx.tlsctx_cache, ctx.memctx, &xfrin); + + // Start the transfer + return dns_xfrin_start(xfrin, transfer_done); +} + +static isc_result_t zone_loaded(void* data) { + dns_zone_t* zone = data; + uint32_t serial = 0; + int r; + + // Fetch the serial + r = dns_zone_getserial(zone, &serial); + switch (r) { + case ISC_R_SUCCESS: + DEBUG("Zone loaded from %s with serial %d\n", dns_zone_getfile(zone), serial); + break; + + case DNS_R_NOTLOADED: + DEBUG("Could not load zone from %s\n", dns_zone_getfile(zone)); + break; + + default: + ERROR("Failed to load zone from %s\n", dns_zone_getfile(zone)); + goto ERROR; + } + + // Initiate the transfer + return do_transfer(zone, serial); + +ERROR: + // Free the zone + dns_zone_detach(&zone); + + return r; +} + +static void do_zone(const char* name) { + dns_fixedname_t fixed = {}; + dns_name_t* origin = NULL; + dns_zone_t* zone = NULL; + isc_buffer_t buffer; + char path[PATH_MAX]; + int r; + + // Create the origin + origin = dns_fixedname_initname(&fixed); + + isc_buffer_constinit(&buffer, name, strlen(name)); + isc_buffer_add(&buffer, strlen(name)); + + dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL); + + DEBUG("Processing zone %s\n", name); + + // Compose the path for the zone + r = snprintf(path, sizeof(path), "%s/%s.zone", ctx.path, name); + if (r < 0) { + ERROR("Failed to make path to zone: %m\n"); + goto ERROR; + } + + // Create a new zone + dns_zone_create(&zone, ctx.memctx, 0); + + // Manage the zone through the zone manager + r = dns_zonemgr_managezone(ctx.zonemgr, zone); + if (r) { + ERROR("Failed to add the zone to the zone manager: %s\n", isc_result_totext(r)); + goto ERROR; + } + + // Set the zone's origin + r = dns_zone_setorigin(zone, origin); + if (r) { + ERROR("Failed to set the zone's origin\n"); + goto ERROR; + } + + // We treat this as a secondary zone + dns_zone_settype(zone, dns_zone_secondary); + + // Set the class + dns_zone_setclass(zone, dns_rdataclass_in); + + // Set the filename of the zone + r = dns_zone_setfile(zone, path, dns_masterformat_text, &dns_master_style_default); + if (r) { + ERROR("Failed to set the zone's filename %s: %m\n", path); + goto ERROR; + } + + // Attach view to the zone + dns_zone_setview(zone, ctx.view); + + // Load the zone from file + r = dns_zone_asyncload(zone, 0, zone_loaded, zone); + switch (r) { + case ISC_R_SUCCESS: + break; + + default: + ERROR("Failed to load zone: %s\n", isc_result_totext(r)); + break; + } + + // Done + return; + +ERROR: + // Destroy the zone + dns_zone_detach(&zone); + + return; } static void run_loop(void* data) { + int r; + DEBUG("Event loop started\n"); + // Create a new dispatch manager + dns_dispatchmgr_create(ctx.memctx, ctx.loopmgr, ctx.netmgr, &ctx.dispatchmgr); + + // Create a zone manager + dns_zonemgr_create(ctx.memctx, ctx.netmgr, &ctx.zonemgr); + + // Create a view + r = dns_view_create(ctx.memctx, ctx.loopmgr, ctx.dispatchmgr, + dns_rdataclass_in, "default", &ctx.view); + if (r) { + ERROR("Failed to create view: %s\n", isc_result_totext(r)); + goto ERROR; + } + // Process all zones - for (unsigned int i = 0; i < ctx.num_zones; i++) { + for (unsigned int i = 0; i < ctx.num_zones; i++) do_zone(ctx.zones[i]); + + // Done + return; + +ERROR: + // Shutdown the event loop on error + isc_loopmgr_shutdown(ctx.loopmgr); +} + +static void destroy_loop(void* data) { + DEBUG("Destroying event loop\n"); + + // Destroy the view + if (ctx.view) + dns_view_detach(&ctx.view); + + // Destroy the zone manager + if (ctx.zonemgr) { + dns_zonemgr_shutdown(ctx.zonemgr); + dns_zonemgr_detach(&ctx.zonemgr); } + + // Detach the dispatch manager + if (ctx.dispatchmgr) + dns_dispatchmgr_detach(&ctx.dispatchmgr); } const char* argp_program_version = PACKAGE_VERSION; @@ -236,22 +463,29 @@ int main(int argc, char* argv[]) { // Setup logging setup_logging(); + // Create the TLS context cache + isc_tlsctx_cache_create(ctx.memctx, &ctx.tlsctx_cache); + // Initialize the loop manager isc_loopmgr_create(ctx.memctx, 1, &ctx.loopmgr); // Create a new netmgr isc_netmgr_create(ctx.memctx, ctx.loopmgr, &ctx.netmgr); - // Register a callback to be called when the loop starts + // Register a callback to be called when the loop starts/finishes isc_loopmgr_setup(ctx.loopmgr, run_loop, &ctx); + isc_loopmgr_teardown(ctx.loopmgr, destroy_loop, &ctx); // Run the event loop isc_loopmgr_run(ctx.loopmgr); ERROR: - isc_netmgr_destroy(&ctx.netmgr); - isc_loopmgr_destroy(&ctx.loopmgr); - + if (ctx.netmgr) + isc_netmgr_destroy(&ctx.netmgr); + if (ctx.loopmgr) + isc_loopmgr_destroy(&ctx.loopmgr); + if (ctx.tlsctx_cache) + isc_tlsctx_cache_detach(&ctx.tlsctx_cache); if (ctx.zones) free(ctx.zones);