From: Michael Tremer Date: Mon, 11 May 2026 15:16:22 +0000 (+0000) Subject: main: Take and resolve the primary IP address X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=580b208249dd7a05c4fd970de8be632333fb6514;p=zone-sync.git main: Take and resolve the primary IP address Signed-off-by: Michael Tremer --- diff --git a/main.c b/main.c index 3dcbbe6..22c9ba3 100644 --- a/main.c +++ b/main.c @@ -19,14 +19,18 @@ #############################################################################*/ #include +#include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -44,6 +48,10 @@ typedef struct ctx { // Path const char* path; + // Primary + const char* primary; + isc_sockaddr_t primary_address; + // Zones const char** zones; unsigned int num_zones; @@ -229,7 +237,6 @@ static void transfer_done(dns_zone_t* zone, uint32_t* serial, isc_result_t resul 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 @@ -243,10 +250,6 @@ static int do_transfer(dns_zone_t* zone, uint32_t serial) { 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); @@ -254,7 +257,7 @@ static int do_transfer(dns_zone_t* zone, uint32_t serial) { // 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_xfrin_create(zone, xfrtype, &ctx.primary_address, &source, NULL, DNS_TRANSPORT_NONE, NULL, ctx.tlsctx_cache, ctx.memctx, &xfrin); // Start the transfer @@ -421,18 +424,58 @@ const char* argp_program_version = PACKAGE_VERSION; static const char* args_doc = "TODO"; enum { - OPT_DEBUG = 1, - OPT_PATH = 2, + OPT_DEBUG = 1, + OPT_PATH = 2, + OPT_PRIMARY = 3, }; static struct argp_option options[] = { - { "debug", OPT_DEBUG, NULL, 0, "Run in debug mode", 0 }, - { "path", OPT_PATH, "PATH", 1, "Path where to store the zones", 0 }, + { "debug", OPT_DEBUG, NULL, 0, "Run in debug mode", 0 }, + { "path", OPT_PATH, "PATH", 1, "Path where to store the zones", 0 }, + { "primary", OPT_PRIMARY, "HOSTNAME", 1, "The hostname of the primary to fetch from", 0 }, { NULL }, }; +static int resolve_primary(void) { + struct addrinfo* res = NULL; + int r; + + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + + // Resolve + r = getaddrinfo(ctx.primary, "53", &hints, &res); + if (r) + goto ERROR; + + // Parse the response + switch (res->ai_family) { + case AF_INET6: + isc_sockaddr_fromin6(&ctx.primary_address, + &((struct sockaddr_in6*)res->ai_addr)->sin6_addr, 53); + break; + + case AF_INET: + isc_sockaddr_fromin(&ctx.primary_address, + &((struct sockaddr_in*)res->ai_addr)->sin_addr, 53); + break; + + default: + abort(); + } + +ERROR: + if (res) + freeaddrinfo(res); + + return r; +} + static error_t parse(int key, char* arg, struct argp_state* state) { const char** zones = NULL; + int r; switch (key) { case OPT_DEBUG: @@ -443,6 +486,10 @@ static error_t parse(int key, char* arg, struct argp_state* state) { ctx.path = arg; break; + case OPT_PRIMARY: + ctx.primary = arg; + break; + case ARGP_KEY_ARG: zones = reallocarray(ctx.zones, ctx.num_zones + 1, sizeof(*ctx.zones)); if (!zones) { @@ -461,6 +508,19 @@ static error_t parse(int key, char* arg, struct argp_state* state) { if (!ctx.zones) { argp_failure(state, EXIT_FAILURE, 0, "You must pass a zone"); } + + // Resolve the primary + if (ctx.primary) { + r = resolve_primary(); + if (r) + argp_failure(state, EXIT_FAILURE, 0, + "Failed to resolve %s: %s", ctx.primary, gai_strerror(r)); + + // Fail if we don't have a primary + } else { + argp_failure(state, EXIT_FAILURE, 0, "You must pass a primary"); + } + break; // Ignore these