#############################################################################*/
#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>
// Path
const char* path;
+ // Primary
+ const char* primary;
+ isc_sockaddr_t primary_address;
+
// Zones
const char** zones;
unsigned int num_zones;
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
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_xfrin_create(zone, xfrtype, &ctx.primary_address, &source, NULL,
DNS_TRANSPORT_NONE, NULL, ctx.tlsctx_cache, ctx.memctx, &xfrin);
// Start the transfer
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:
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) {
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