#define DEFAULT_PATH "/tmp"
+#define MAX_ZONES 128
+
+typedef struct zone_ctx {
+ const char* name;
+ dns_zone_t* zone;
+ dns_xfrin_t* xfrin;
+} zone_ctx;
+
typedef struct ctx {
// Log Level
int log_level;
dns_transport_t* transport;
// Zones
- const char** zones;
+ zone_ctx zones[MAX_ZONES];
unsigned int num_zones;
// How many transfers are running?
}
static isc_result_t zone_loaded(void* data) {
- dns_zone_t* zone = data;
+ zone_ctx* zone = data;
uint32_t serial = 0;
int r;
// Fetch the serial
- r = dns_zone_getserial(zone, &serial);
+ r = dns_zone_getserial(zone->zone, &serial);
switch (r) {
case ISC_R_SUCCESS:
- DEBUG("Zone loaded from %s with serial %u\n", dns_zone_getfile(zone), serial);
+ DEBUG("Zone loaded from %s with serial %u\n",
+ dns_zone_getfile(zone->zone), serial);
break;
case DNS_R_NOTLOADED:
- DEBUG("Could not load zone from %s\n", dns_zone_getfile(zone));
+ DEBUG("Could not load zone from %s\n",
+ dns_zone_getfile(zone->zone));
break;
default:
- ERROR("Failed to load zone from %s\n", dns_zone_getfile(zone));
+ ERROR("Failed to load zone from %s\n",
+ dns_zone_getfile(zone->zone));
goto ERROR;
}
// Initiate the transfer
- return do_transfer(zone, serial);
+ return do_transfer(zone->zone, serial);
ERROR:
// Destroy the zone
- zone_done(zone);
+ zone_done(zone->zone);
return r;
}
-static void do_zone(const char* name) {
+static void do_zone(zone_ctx* zone) {
dns_name_t* origin = NULL;
- dns_zone_t* zone = NULL;
char journal_path[PATH_MAX];
char path[PATH_MAX];
int r;
ctx.running++;
// Create the origin
- r = dns_name_from_string(&origin, name);
+ r = dns_name_from_string(&origin, zone->name);
if (r)
goto ERROR;
- DEBUG("Processing zone %s\n", name);
+ DEBUG("Processing zone %s\n", zone->name);
// Compose the path for the zone
- r = snprintf(path, sizeof(path), "%s/%s.zone", ctx.path, name);
+ r = snprintf(path, sizeof(path), "%s/%s.zone", ctx.path, zone->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);
+ dns_zone_create(&zone->zone, ctx.memctx, 0);
// Manage the zone through the zone manager
- r = dns_zonemgr_managezone(ctx.zonemgr, zone);
+ r = dns_zonemgr_managezone(ctx.zonemgr, zone->zone);
if (r) {
ERROR("Failed to add the zone to the zone manager: %s\n", isc_result_totext(r));
ctx.rc = 1;
}
// Set the zone's origin
- r = dns_zone_setorigin(zone, origin);
+ r = dns_zone_setorigin(zone->zone, origin);
if (r) {
ERROR("Failed to set the zone's origin\n");
ctx.rc = 1;
}
// We treat this as a secondary zone
- dns_zone_settype(zone, dns_zone_secondary);
+ dns_zone_settype(zone->zone, dns_zone_secondary);
// Set the class
- dns_zone_setclass(zone, dns_rdataclass_in);
+ dns_zone_setclass(zone->zone, dns_rdataclass_in);
// Set the filename of the zone
- r = dns_zone_setfile(zone, path, dns_masterformat_text, &dns_master_style_default);
+ r = dns_zone_setfile(zone->zone, path, dns_masterformat_text, &dns_master_style_default);
if (r) {
ERROR("Failed to set the zone's filename %s: %m\n", path);
ctx.rc = 1;
}
// Set the path of the journal
- r = dns_zone_setjournal(zone, journal_path);
+ r = dns_zone_setjournal(zone->zone, journal_path);
if (r) {
ERROR("Failed to set the zone's journal path: %s\n", isc_result_totext(r));
ctx.rc = 1;
}
// Attach view to the zone
- dns_zone_setview(zone, ctx.view);
+ dns_zone_setview(zone->zone, ctx.view);
// Load the zone from file
- r = dns_zone_asyncload(zone, 0, zone_loaded, zone);
+ r = dns_zone_asyncload(zone->zone, 0, zone_loaded, zone);
switch (r) {
case ISC_R_SUCCESS:
break;
ERROR:
// Destroy the zone
- zone_done(zone);
+ zone_done(zone->zone);
}
static int configure_transports(void) {
// Process all zones
for (unsigned int i = 0; i < ctx.num_zones; i++)
- do_zone(ctx.zones[i]);
+ do_zone(&ctx.zones[i]);
ERROR:
// Potentially shut down if there is nothing to do
}
static error_t parse(int key, char* arg, struct argp_state* state) {
- const char** zones = NULL;
int r;
switch (key) {
break;
case ARGP_KEY_ARG:
- zones = reallocarray(ctx.zones, ctx.num_zones + 1, sizeof(*ctx.zones));
- if (!zones) {
- argp_failure(state, EXIT_FAILURE, 0, "%m");
+ // Check if we have too many zones
+ if (ctx.num_zones >= MAX_ZONES) {
+ argp_failure(state, EXIT_FAILURE, 0, "Too many zones");
return ARGP_ERR_UNKNOWN;
}
- // Store the pointer to the argument
- zones[ctx.num_zones++] = arg;
-
- ctx.zones = zones;
+ // Store the name of the zone
+ ctx.zones[ctx.num_zones++].name = arg;
break;
case ARGP_KEY_SUCCESS:
// Fail if we don't have any zones
- if (!ctx.zones) {
+ if (!ctx.num_zones) {
argp_failure(state, EXIT_FAILURE, 0, "You must pass a zone");
}
isc_loopmgr_destroy(&ctx.loopmgr);
if (ctx.tlsctx_cache)
isc_tlsctx_cache_detach(&ctx.tlsctx_cache);
- if (ctx.zones)
- free(ctx.zones);
// Exit with our local return code if set
if (r)