]> git.ipfire.org Git - zone-sync.git/commitdiff
main: Take and resolve the primary IP address
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 11 May 2026 15:16:22 +0000 (15:16 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 11 May 2026 15:16:22 +0000 (15:16 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
main.c

diff --git a/main.c b/main.c
index 3dcbbe606e50180bd220f201b65a6eb51cbef217..22c9ba336a8a374d82699b0b2cef1f61fe00a837 100644 (file)
--- a/main.c
+++ b/main.c
 #############################################################################*/
 
 #include <argp.h>
+#include <netdb.h>
 #include <stdio.h>
 #include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
 #include <urcu/rculist.h>
 #include <urcu/wfcqueue.h>
 #include <urcu/call-rcu.h>
 
 #include <dns/dispatch.h>
+#include <dns/name.h>
 #include <dns/view.h>
 #include <dns/xfrin.h>
 #include <dns/zone.h>
@@ -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