}
static rr_type*
-check_apex_soa(namedb_type* namedb, zone_type *zone)
+check_apex_soa(namedb_type* namedb, zone_type *zone, int nolog)
{
uint8_t h[NSEC3_HASH_LEN];
domain_type* domain;
hashed_apex = nsec3_b32_create(tmpregion, zone, h);
domain = domain_table_find(namedb->domains, hashed_apex);
if(!domain) {
- log_msg(LOG_ERR, "%s NSEC3PARAM entry has no hash(apex).",
- domain_to_string(zone->apex));
- log_msg(LOG_ERR, "hash(apex)= %s",
- dname_to_string(hashed_apex, NULL));
+ if(!nolog) {
+ log_msg(LOG_ERR, "%s NSEC3PARAM entry has no hash(apex).",
+ domain_to_string(zone->apex));
+ log_msg(LOG_ERR, "hash(apex)= %s",
+ dname_to_string(hashed_apex, NULL));
+ }
region_destroy(tmpregion);
return NULL;
}
nsec3_rrset = domain_find_rrset(domain, zone, TYPE_NSEC3);
if(!nsec3_rrset) {
- log_msg(LOG_ERR, "%s NSEC3PARAM entry: hash(apex) has no NSEC3 RRset.",
- domain_to_string(zone->apex));
- log_msg(LOG_ERR, "hash(apex)= %s",
- dname_to_string(hashed_apex, NULL));
+ if(!nolog) {
+ log_msg(LOG_ERR, "%s NSEC3PARAM entry: hash(apex) has no NSEC3 RRset.",
+ domain_to_string(zone->apex));
+ log_msg(LOG_ERR, "hash(apex)= %s",
+ dname_to_string(hashed_apex, NULL));
+ }
region_destroy(tmpregion);
return NULL;
}
return &nsec3_rrset->rrs[j];
}
}
- log_msg(LOG_ERR, "%s NSEC3PARAM entry: hash(apex) NSEC3 has no SOA flag.",
- domain_to_string(zone->apex));
- log_msg(LOG_ERR, "hash(apex)= %s",
- dname_to_string(hashed_apex, NULL));
+ if(!nolog) {
+ log_msg(LOG_ERR, "%s NSEC3PARAM entry: hash(apex) NSEC3 has no SOA flag.",
+ domain_to_string(zone->apex));
+ log_msg(LOG_ERR, "hash(apex)= %s",
+ dname_to_string(hashed_apex, NULL));
+ }
region_destroy(tmpregion);
return NULL;
}
+static void
+nsec3param_to_str(struct rr* rr, char* str, size_t buflen)
+{
+ rdata_atom_type* rd = rr->rdatas;
+ size_t len;
+ len = snprintf(str, buflen, "%u %u %u ",
+ (unsigned)rdata_atom_data(rd[0])[0],
+ (unsigned)rdata_atom_data(rd[1])[0],
+ (unsigned)read_uint16(rdata_atom_data(rd[2])));
+ if(rdata_atom_data(rd[3])[0] == 0) {
+ if(buflen > len + 2)
+ str[len++] = '-';
+ } else {
+ len += hex_ntop(rdata_atom_data(rd[3])+1,
+ rdata_atom_data(rd[3])[0], str+len, buflen-len-1);
+ }
+ if(buflen > len + 1)
+ str[len] = 0;
+}
+
static struct rr*
-udb_zone_find_nsec3param(udb_base* udb, udb_ptr* uz, struct zone* z)
+db_find_nsec3param(struct namedb* db, struct zone* z, struct rr* avoid_rr,
+ int checkchain)
+{
+ unsigned i;
+ rrset_type* rrset = domain_find_rrset(z->apex, z, TYPE_NSEC3PARAM);
+ if(!rrset) /* no NSEC3PARAM in mem */
+ return NULL;
+ /* find first nsec3param we can support (SHA1, no flags) */
+ for(i=0; i<rrset->rr_count; i++) {
+ rdata_atom_type* rd = rrset->rrs[i].rdatas;
+ /* do not use the RR that is going to be deleted (in IXFR) */
+ if(&rrset->rrs[i] == avoid_rr) continue;
+ if(rrset->rrs[i].rdata_count < 4) continue;
+ if(rdata_atom_data(rd[0])[0] == NSEC3_SHA1_HASH &&
+ rdata_atom_data(rd[1])[0] == 0) {
+ if(checkchain) {
+ z->nsec3_param = &rrset->rrs[i];
+ if(!check_apex_soa(db, z, 1)) {
+ char str[MAX_RDLENGTH*2+16];
+ nsec3param_to_str(z->nsec3_param,
+ str, sizeof(str));
+ VERBOSITY(1, (LOG_WARNING, "zone %s NSEC3PARAM %s has broken chain, ignoring", domain_to_string(z->apex), str));
+ continue; /* don't use broken chain */
+ }
+ }
+ if(2 <= verbosity) {
+ char str[MAX_RDLENGTH*2+16];
+ nsec3param_to_str(&rrset->rrs[i], str,
+ sizeof(str));
+ VERBOSITY(2, (LOG_INFO, "rehash of zone %s with parameters %s",
+ domain_to_string(z->apex), str));
+ }
+ return &rrset->rrs[i];
+ }
+ }
+ return NULL;
+}
+
+static struct rr*
+udb_zone_find_nsec3param(struct namedb* db, udb_base* udb, udb_ptr* uz,
+ struct zone* z, int checkchain)
{
udb_ptr urr;
unsigned i;
memcmp(RR(&urr)->wire+5, rdata_atom_data(rd[3])+1,
rdata_atom_data(rd[3])[0]) == 0) {
udb_ptr_unlink(&urr, udb);
- return &rrset->rrs[i];
- }
- }
- udb_ptr_unlink(&urr, udb);
- return NULL;
-}
-
-static struct rr*
-db_find_nsec3param(struct zone* z, struct rr* avoid_rr)
-{
- unsigned i;
- rrset_type* rrset = domain_find_rrset(z->apex, z, TYPE_NSEC3PARAM);
- if(!rrset) /* no NSEC3PARAM in mem */
- return NULL;
- /* find first nsec3param we can support (SHA1, no flags) */
- for(i=0; i<rrset->rr_count; i++) {
- rdata_atom_type* rd = rrset->rrs[i].rdatas;
- /* do not use the RR that is going to be deleted (in IXFR) */
- if(&rrset->rrs[i] == avoid_rr) continue;
- if(rrset->rrs[i].rdata_count < 4) continue;
- if(rdata_atom_data(rd[0])[0] == NSEC3_SHA1_HASH &&
- rdata_atom_data(rd[1])[0] == 0) {
- if(2 <= verbosity) {
- char str[MAX_RDLENGTH*2+16];
- char* p;
- p = str+snprintf(str, sizeof(str), "%u %u %u ",
- (unsigned)rdata_atom_data(rd[0])[0],
- (unsigned)rdata_atom_data(rd[1])[0],
- (unsigned)read_uint16(rdata_atom_data(rd[2])));
- if(rdata_atom_data(rd[3])[0] == 0)
- *p++ = '-';
- else {
- p += hex_ntop(rdata_atom_data(rd[3])+1,
- rdata_atom_data(rd[3])[0], p,
- sizeof(str)-strlen(str)-1);
- }
- *p = 0;
- VERBOSITY(2, (LOG_INFO, "rehash of zone %s with parameters %s",
- domain_to_string(z->apex), str));
+ if(checkchain) {
+ z->nsec3_param = &rrset->rrs[i];
+ if(!check_apex_soa(db, z, 1))
+ return db_find_nsec3param(db, z,
+ NULL, checkchain);
}
return &rrset->rrs[i];
}
}
+ udb_ptr_unlink(&urr, udb);
return NULL;
}
void
nsec3_find_zone_param(struct namedb* db, struct zone* zone, udb_ptr* z,
- struct rr* avoid_rr)
+ struct rr* avoid_rr, int checkchain)
{
/* get nsec3param RR from udb */
if(db->udb)
- zone->nsec3_param = udb_zone_find_nsec3param(db->udb, z, zone);
+ zone->nsec3_param = udb_zone_find_nsec3param(db, db->udb,
+ z, zone, checkchain);
/* no db, get from memory, avoid using the rr that is going to be
* deleted, avoid_rr */
- else zone->nsec3_param = db_find_nsec3param(zone, avoid_rr);
+ else zone->nsec3_param = db_find_nsec3param(db, zone, avoid_rr,
+ checkchain);
}
/* check params ok for one RR */
udb_ptr_init(&udbz, db->udb); /* zero the ptr */
}
}
- nsec3_find_zone_param(db, zone, &udbz, NULL);
- if(!zone->nsec3_param || !check_apex_soa(db, zone)) {
+ nsec3_find_zone_param(db, zone, &udbz, NULL, 1);
+ if(!zone->nsec3_param || !check_apex_soa(db, zone, 0)) {
zone->nsec3_param = NULL;
zone->nsec3_last = NULL;
if(db->udb)
prehash_clear(db->domains);
return;
}
+ if(!check_apex_soa(db, zone, 1)) {
+ /* the zone fails apex soa check, prehash complete may
+ * detect other valid chains */
+ prehash_clear(db->domains);
+ prehash_zone_complete(db, zone);
+ return;
+ }
/* process prehash list */
for(d = db->domains->prehash_list; d; d = d->nsec3->prehash_next) {
process_prehash_domain(d, zone);
/* clear prehash list */
prehash_clear(db->domains);
- if(!check_apex_soa(db, zone)) {
+ if(!check_apex_soa(db, zone, 0)) {
zone->nsec3_param = NULL;
zone->nsec3_last = NULL;
}
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_NETDB_H
-#include <netdb.h>
+# include <netdb.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
#endif
/** number of seconds timeout on incoming remote control handshake */
enum { rc_none, rc_hs_read, rc_hs_write } shake_state;
/** the ssl state */
SSL* ssl;
+ /** file descriptor */
+ int fd;
/** the rc this is part of */
struct daemon_remote* rc;
/** stats list next item */
struct xfrd_state* xfrd;
/** commpoints for accepting remote control connections */
struct acceptlist* accept_list;
+ /* if certificates are used */
+ int use_cert;
/** number of active commpoints that are handling remote control */
int active;
/** max active commpoints */
SSL_CTX* ctx;
};
+/**
+ * Connection to print to, either SSL or plain over fd
+ */
+struct remote_stream {
+ /** SSL structure, nonNULL if using SSL */
+ SSL* ssl;
+ /** file descriptor for plain transfer */
+ int fd;
+};
+typedef struct remote_stream RES;
+
/**
* Print fixed line of text over ssl connection in blocking mode
- * @param ssl: print to
+ * @param res: print to
* @param text: the text.
* @return false on connection failure.
*/
-static int ssl_print_text(SSL* ssl, const char* text);
+static int ssl_print_text(RES* res, const char* text);
/**
* printf style printing to the ssl connection
- * @param ssl: the SSL connection to print to. Blocking.
+ * @param res: the RES connection to print to. Blocking.
* @param format: printf style format string.
* @return success or false on a network failure.
*/
-static int ssl_printf(SSL* ssl, const char* format, ...)
+static int ssl_printf(RES* res, const char* format, ...)
ATTR_FORMAT(printf, 2, 3);
/**
* Read until \n is encountered
- * If SSL signals EOF, the string up to then is returned (without \n).
- * @param ssl: the SSL connection to read from. blocking.
+ * If stream signals EOF, the string up to then is returned (without \n).
+ * @param res: the RES connection to read from. blocking.
* @param buf: buffer to read to.
* @param max: size of buffer.
* @return false on connection failure.
*/
-static int ssl_read_line(SSL* ssl, char* buf, size_t max);
+static int ssl_read_line(RES* res, char* buf, size_t max);
/** perform the accept of a new remote control connection */
static void
}
#endif /* BIND8_STATS */
-struct daemon_remote*
-daemon_remote_create(struct nsd_options* cfg)
+static int
+remote_setup_ctx(struct daemon_remote* rc, struct nsd_options* cfg)
{
char* s_cert;
char* s_key;
+ rc->ctx = SSL_CTX_new(SSLv23_server_method());
+ if(!rc->ctx) {
+ log_crypto_err("could not SSL_CTX_new");
+ return 0;
+ }
+ /* no SSLv2, SSLv3 because has defects */
+ if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
+ != SSL_OP_NO_SSLv2){
+ log_crypto_err("could not set SSL_OP_NO_SSLv2");
+ return 0;
+ }
+ if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
+ != SSL_OP_NO_SSLv3){
+ log_crypto_err("could not set SSL_OP_NO_SSLv3");
+ return 0;
+ }
+ s_cert = cfg->server_cert_file;
+ s_key = cfg->server_key_file;
+ VERBOSITY(2, (LOG_INFO, "setup SSL certificates"));
+ if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) {
+ log_msg(LOG_ERR, "Error for server-cert-file: %s", s_cert);
+ log_crypto_err("Error in SSL_CTX use_certificate_file");
+ return 0;
+ }
+ if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) {
+ log_msg(LOG_ERR, "Error for server-key-file: %s", s_key);
+ log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
+ return 0;
+ }
+ if(!SSL_CTX_check_private_key(rc->ctx)) {
+ log_msg(LOG_ERR, "Error for server-key-file: %s", s_key);
+ log_crypto_err("Error in SSL_CTX check_private_key");
+ return 0;
+ }
+ if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
+ log_crypto_err("Error setting up SSL_CTX verify locations");
+ return 0;
+ }
+ SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
+ SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
+ return 1;
+}
+
+struct daemon_remote*
+daemon_remote_create(struct nsd_options* cfg)
+{
struct daemon_remote* rc = (struct daemon_remote*)xalloc_zero(
sizeof(*rc));
rc->max_active = 10;
log_msg(LOG_WARNING, "warning: no entropy, seeding openssl PRNG with time");
}
- rc->ctx = SSL_CTX_new(SSLv23_server_method());
- if(!rc->ctx) {
- log_crypto_err("could not SSL_CTX_new");
- free(rc);
- return NULL;
- }
- /* no SSLv2, SSLv3 because has defects */
- if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
- != SSL_OP_NO_SSLv2){
- log_crypto_err("could not set SSL_OP_NO_SSLv2");
- daemon_remote_delete(rc);
- return NULL;
- }
- if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
- != SSL_OP_NO_SSLv3){
- log_crypto_err("could not set SSL_OP_NO_SSLv3");
- daemon_remote_delete(rc);
- return NULL;
- }
- s_cert = cfg->server_cert_file;
- s_key = cfg->server_key_file;
- VERBOSITY(2, (LOG_INFO, "setup SSL certificates"));
- if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) {
- log_msg(LOG_ERR, "Error for server-cert-file: %s", s_cert);
- log_crypto_err("Error in SSL_CTX use_certificate_file");
- goto setup_error;
- }
- if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) {
- log_msg(LOG_ERR, "Error for server-key-file: %s", s_key);
- log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
- goto setup_error;
- }
- if(!SSL_CTX_check_private_key(rc->ctx)) {
- log_msg(LOG_ERR, "Error for server-key-file: %s", s_key);
- log_crypto_err("Error in SSL_CTX check_private_key");
- goto setup_error;
- }
- if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
- log_crypto_err("Error setting up SSL_CTX verify locations");
- setup_error:
- daemon_remote_delete(rc);
- return NULL;
+ if(options_remote_is_address(cfg)) {
+ if(!remote_setup_ctx(rc, cfg)) {
+ daemon_remote_delete(rc);
+ return NULL;
+ }
+ rc->use_cert = 1;
+ } else {
+ struct ip_address_option* o;
+ rc->ctx = NULL;
+ rc->use_cert = 0;
+ for(o = cfg->control_interface; o; o = o->next) {
+ if(o->address && o->address[0] != '/')
+ log_msg(LOG_WARNING, "control-interface %s is not using TLS, but plain transfer, because first control-interface in config file is a local socket (starts with a /).", o->address);
+ }
}
- SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
- SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
/* and try to open the ports */
if(!daemon_remote_open_ports(rc, cfg)) {
log_msg(LOG_ERR, "could not open remote control port");
- goto setup_error;
+ daemon_remote_delete(rc);
+ return NULL;
}
if(gettimeofday(&rc->boot_time, NULL) == -1)
* @return false on failure.
*/
static int
-add_open(struct daemon_remote* rc, const char* ip, int nr, int noproto_is_err)
+add_open(struct daemon_remote* rc, struct nsd_options* cfg, const char* ip,
+ int nr, int noproto_is_err)
{
struct addrinfo hints;
struct addrinfo* res;
snprintf(port, sizeof(port), "%d", nr);
port[sizeof(port)-1]=0;
memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
- if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
- log_msg(LOG_ERR, "control interface %s:%s getaddrinfo: %s %s",
- ip?ip:"default", port, gai_strerror(r),
+
+ if(ip[0] == '/') {
+ /* This looks like a local socket */
+ fd = create_local_accept_sock(ip, &noproto);
+ /*
+ * Change socket ownership and permissions so users other
+ * than root can access it provided they are in the same
+ * group as the user we run as.
+ */
+ if(fd != -1) {
+#ifdef HAVE_CHOWN
+ if (cfg->username && cfg->username[0] &&
+ nsd.uid != (uid_t)-1) {
+ if(chown(ip, nsd.uid, nsd.gid) == -1)
+ VERBOSITY(2, (LOG_INFO, "cannot chown %u.%u %s: %s",
+ (unsigned)nsd.uid, (unsigned)nsd.gid,
+ ip, strerror(errno)));
+ }
+ chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
+#else
+ (void)cfg;
+#endif
+ }
+ } else {
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
+ log_msg(LOG_ERR, "control interface %s:%s getaddrinfo: %s %s",
+ ip?ip:"default", port, gai_strerror(r),
#ifdef EAI_SYSTEM
- r==EAI_SYSTEM?(char*)strerror(errno):""
+ r==EAI_SYSTEM?(char*)strerror(errno):""
#else
- ""
+ ""
#endif
- );
- return 0;
+ );
+ return 0;
+ }
+
+ /* open fd */
+ fd = create_tcp_accept_sock(res, &noproto);
+ freeaddrinfo(res);
}
- /* open fd */
- fd = create_tcp_accept_sock(res, &noproto);
- freeaddrinfo(res);
if(fd == -1 && noproto) {
if(!noproto_is_err)
return 1; /* return success, but do nothing */
if(cfg->control_interface) {
ip_address_option_type* p;
for(p = cfg->control_interface; p; p = p->next) {
- if(!add_open(rc, p->address, cfg->control_port, 1)) {
+ if(!add_open(rc, cfg, p->address, cfg->control_port, 1)) {
return 0;
}
}
} else {
/* defaults */
- if(cfg->do_ip6 && !add_open(rc, "::1", cfg->control_port, 0)) {
+ if(cfg->do_ip6 && !add_open(rc, cfg, "::1", cfg->control_port, 0)) {
return 0;
}
if(cfg->do_ip4 &&
- !add_open(rc, "127.0.0.1", cfg->control_port, 1)) {
+ !add_open(rc, cfg, "127.0.0.1", cfg->control_port, 1)) {
return 0;
}
}
n->tval.tv_sec = REMOTE_CONTROL_TCP_TIMEOUT;
n->tval.tv_usec = 0L;
+ n->fd = newfd;
event_set(&n->c, newfd, EV_PERSIST|EV_TIMEOUT|EV_READ,
remote_control_callback, n);
VERBOSITY(2, (LOG_INFO, "new control connection from %s", s));
}
- n->shake_state = rc_hs_read;
- n->ssl = SSL_new(rc->ctx);
- if(!n->ssl) {
- log_crypto_err("could not SSL_new");
- event_del(&n->c);
- free(n);
- goto close_exit;
- }
- SSL_set_accept_state(n->ssl);
- (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY);
- if(!SSL_set_fd(n->ssl, newfd)) {
- log_crypto_err("could not SSL_set_fd");
- event_del(&n->c);
- SSL_free(n->ssl);
- free(n);
- goto close_exit;
+ if(rc->ctx) {
+ n->shake_state = rc_hs_read;
+ n->ssl = SSL_new(rc->ctx);
+ if(!n->ssl) {
+ log_crypto_err("could not SSL_new");
+ event_del(&n->c);
+ free(n);
+ goto close_exit;
+ }
+ SSL_set_accept_state(n->ssl);
+ (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY);
+ if(!SSL_set_fd(n->ssl, newfd)) {
+ log_crypto_err("could not SSL_set_fd");
+ event_del(&n->c);
+ SSL_free(n->ssl);
+ free(n);
+ goto close_exit;
+ }
+ } else {
+ n->ssl = NULL;
}
n->rc = rc;
}
static int
-ssl_print_text(SSL* ssl, const char* text)
+ssl_print_text(RES* res, const char* text)
{
int r;
- if(!ssl)
+ if(!res)
return 0;
- ERR_clear_error();
- if((r=SSL_write(ssl, text, (int)strlen(text))) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- VERBOSITY(2, (LOG_WARNING, "in SSL_write, peer "
- "closed connection"));
+ if(res->ssl) {
+ ERR_clear_error();
+ if((r=SSL_write(res->ssl, text, (int)strlen(text))) <= 0) {
+ if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
+ VERBOSITY(2, (LOG_WARNING, "in SSL_write, peer "
+ "closed connection"));
+ return 0;
+ }
+ log_crypto_err("could not SSL_write");
+ return 0;
+ }
+ } else {
+ if(write_socket(res->fd, text, strlen(text)) <= 0) {
+ log_msg(LOG_ERR, "could not write: %s",
+ strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_write");
- return 0;
}
return 1;
}
/** print text over the ssl connection */
static int
-ssl_print_vmsg(SSL* ssl, const char* format, va_list args)
+ssl_print_vmsg(RES* ssl, const char* format, va_list args)
{
char msg[1024];
vsnprintf(msg, sizeof(msg), format, args);
/** printf style printing to the ssl connection */
static int
-ssl_printf(SSL* ssl, const char* format, ...)
+ssl_printf(RES* ssl, const char* format, ...)
{
va_list args;
int ret;
}
static int
-ssl_read_line(SSL* ssl, char* buf, size_t max)
+ssl_read_line(RES* res, char* buf, size_t max)
{
int r;
size_t len = 0;
- if(!ssl)
+ if(!res)
return 0;
while(len < max) {
- ERR_clear_error();
- if((r=SSL_read(ssl, buf+len, 1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- buf[len] = 0;
- return 1;
+ if(res->ssl) {
+ ERR_clear_error();
+ if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) {
+ if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
+ buf[len] = 0;
+ return 1;
+ }
+ log_crypto_err("could not SSL_read");
+ return 0;
+ }
+ } else {
+ while(1) {
+ ssize_t rr = read(res->fd, buf+len, 1);
+ if(rr <= 0) {
+ if(rr == 0) {
+ buf[len] = 0;
+ return 1;
+ }
+ if(errno == EINTR || errno == EAGAIN)
+ continue;
+ log_msg(LOG_ERR, "could not read: %s",
+ strerror(errno));
+ return 0;
+ }
+ break;
}
- log_crypto_err("could not SSL_read");
- return 0;
}
if(buf[len] == '\n') {
/* return string without \n */
/** send the OK to the control client */
static void
-send_ok(SSL* ssl)
+send_ok(RES* ssl)
{
(void)ssl_printf(ssl, "ok\n");
}
/** get zone argument (if any) or NULL, false on error */
static int
-get_zone_arg(SSL* ssl, xfrd_state_type* xfrd, char* arg,
+get_zone_arg(RES* ssl, xfrd_state_type* xfrd, char* arg,
struct zone_options** zo)
{
const dname_type* dname;
/** do the stop command */
static void
-do_stop(SSL* ssl, xfrd_state_type* xfrd)
+do_stop(RES* ssl, xfrd_state_type* xfrd)
{
xfrd->need_to_send_shutdown = 1;
/** do the log_reopen command, it only needs reload_now */
static void
-do_log_reopen(SSL* ssl, xfrd_state_type* xfrd)
+do_log_reopen(RES* ssl, xfrd_state_type* xfrd)
{
xfrd_set_reload_now(xfrd);
send_ok(ssl);
/** do the reload command */
static void
-do_reload(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_reload(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
struct zone_options* zo;
if(!get_zone_arg(ssl, xfrd, arg, &zo))
/** do the write command */
static void
-do_write(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_write(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
struct zone_options* zo;
if(!get_zone_arg(ssl, xfrd, arg, &zo))
/** do the notify command */
static void
-do_notify(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_notify(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
struct zone_options* zo;
if(!get_zone_arg(ssl, xfrd, arg, &zo))
/** do the transfer command */
static void
-do_transfer(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_transfer(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
struct zone_options* zo;
xfrd_zone_type* zone;
RBTREE_FOR(zone, xfrd_zone_type*, xfrd->zones) {
xfrd_handle_notify_and_start_xfr(zone, NULL);
}
- ssl_printf(ssl, "ok, %u zones\n", (unsigned)xfrd->zones->count);
+ ssl_printf(ssl, "ok, %lu zones\n", (unsigned long)xfrd->zones->count);
}
}
/** do the force transfer command */
static void
-do_force_transfer(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_force_transfer(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
struct zone_options* zo;
xfrd_zone_type* zone;
RBTREE_FOR(zone, xfrd_zone_type*, xfrd->zones) {
force_transfer_zone(zone);
}
- ssl_printf(ssl, "ok, %u zones\n", (unsigned)xfrd->zones->count);
+ ssl_printf(ssl, "ok, %lu zones\n", (unsigned long)xfrd->zones->count);
}
}
static int
-print_soa_status(SSL* ssl, const char* str, xfrd_soa_type* soa, time_t acq)
+print_soa_status(RES* ssl, const char* str, xfrd_soa_type* soa, time_t acq)
{
if(acq) {
if(!ssl_printf(ssl, " %s: \"%u since %s\"\n", str,
/** print zonestatus for one domain */
static int
-print_zonestatus(SSL* ssl, xfrd_state_type* xfrd, struct zone_options* zo)
+print_zonestatus(RES* ssl, xfrd_state_type* xfrd, struct zone_options* zo)
{
xfrd_zone_type* xz = (xfrd_zone_type*)rbtree_search(xfrd->zones,
(const dname_type*)zo->node.key);
xz->soa_notified_acquired))
return 0;
} else if(xz->event_added) {
- if(!ssl_printf(ssl, "\twait: \"%u sec between attempts\"\n",
- (unsigned)xz->timeout.tv_sec))
+ if(!ssl_printf(ssl, "\twait: \"%lu sec between attempts\"\n",
+ (unsigned long)xz->timeout.tv_sec))
return 0;
}
/** do the zonestatus command */
static void
-do_zonestatus(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_zonestatus(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
struct zone_options* zo;
if(!get_zone_arg(ssl, xfrd, arg, &zo))
/** do the verbosity command */
static void
-do_verbosity(SSL* ssl, char* str)
+do_verbosity(RES* ssl, char* str)
{
int val = atoi(str);
if(strcmp(str, "") == 0) {
/** find second argument, modifies string */
static int
-find_arg2(SSL* ssl, char* arg, char** arg2)
+find_arg2(RES* ssl, char* arg, char** arg2)
{
char* as = strrchr(arg, ' ');
if(as) {
/** do the status command */
static void
-do_status(SSL* ssl, xfrd_state_type* xfrd)
+do_status(RES* ssl, xfrd_state_type* xfrd)
{
if(!ssl_printf(ssl, "version: %s\n", PACKAGE_VERSION))
return;
/** perform the addzone command for one zone */
static int
-perform_addzone(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+perform_addzone(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
const dname_type* dname;
struct zone_options* zopt;
/** perform the delzone command for one zone */
static int
-perform_delzone(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+perform_delzone(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
const dname_type* dname;
struct zone_options* zopt;
/** do the addzone command */
static void
-do_addzone(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_addzone(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
if(!perform_addzone(ssl, xfrd, arg))
return;
/** do the delzone command */
static void
-do_delzone(SSL* ssl, xfrd_state_type* xfrd, char* arg)
+do_delzone(RES* ssl, xfrd_state_type* xfrd, char* arg)
{
if(!perform_delzone(ssl, xfrd, arg))
return;
/** do the addzones command */
static void
-do_addzones(SSL* ssl, xfrd_state_type* xfrd)
+do_addzones(RES* ssl, xfrd_state_type* xfrd)
{
char buf[2048];
int num = 0;
/** do the delzones command */
static void
-do_delzones(SSL* ssl, xfrd_state_type* xfrd)
+do_delzones(RES* ssl, xfrd_state_type* xfrd)
{
char buf[2048];
int num = 0;
static void
print_ssl_cfg_err(void* arg, const char* str)
{
- SSL** ssl = (SSL**)arg;
+ RES** ssl = (RES**)arg;
if(!*ssl) return;
if(!ssl_printf(*ssl, "%s", str))
*ssl = NULL; /* failed, stop printing */
/** do the repattern command: reread config file and apply keys, patterns */
static void
-do_repattern(SSL* ssl, xfrd_state_type* xfrd)
+do_repattern(RES* ssl, xfrd_state_type* xfrd)
{
region_type* region = region_create(xalloc, free);
struct nsd_options* opt;
/** do the serverpid command: printout pid of server process */
static void
-do_serverpid(SSL* ssl, xfrd_state_type* xfrd)
+do_serverpid(RES* ssl, xfrd_state_type* xfrd)
{
(void)ssl_printf(ssl, "%u\n", (unsigned)xfrd->reload_pid);
}
/** execute a remote control command */
static void
-execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, struct rc_state* rs)
+execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd, struct rc_state* rs)
{
char* p = skipwhite(cmd);
/* compare command */
/** handle remote control request */
static void
-handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
+handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
{
int r;
char pre[10];
}
/* try to read magic UBCT[version]_space_ string */
- ERR_clear_error();
- if((r=SSL_read(ssl, magic, (int)sizeof(magic)-1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN)
+ if(res->ssl) {
+ ERR_clear_error();
+ if((r=SSL_read(res->ssl, magic, (int)sizeof(magic)-1)) <= 0) {
+ if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN)
+ return;
+ log_crypto_err("could not SSL_read");
return;
- log_crypto_err("could not SSL_read");
- return;
+ }
+ } else {
+ while(1) {
+ ssize_t rr = read(res->fd, magic, sizeof(magic)-1);
+ if(rr <= 0) {
+ if(rr == 0) return;
+ if(errno == EINTR || errno == EAGAIN)
+ continue;
+ log_msg(LOG_ERR, "could not read: %s", strerror(errno));
+ return;
+ }
+ r = (int)rr;
+ break;
+ }
}
magic[7] = 0;
if( r != 7 || strncmp(magic, "NSDCT", 5) != 0) {
}
/* read the command line */
- if(!ssl_read_line(ssl, buf, sizeof(buf))) {
+ if(!ssl_read_line(res, buf, sizeof(buf))) {
return;
}
snprintf(pre, sizeof(pre), "NSDCT%d ", NSD_CONTROL_VERSION);
if(strcmp(magic, pre) != 0) {
VERBOSITY(2, (LOG_INFO, "control connection had bad "
"version %s, cmd: %s", magic, buf));
- ssl_printf(ssl, "error version mismatch\n");
+ ssl_printf(res, "error version mismatch\n");
return;
}
VERBOSITY(2, (LOG_INFO, "control cmd: %s", buf));
/* figure out what to do */
- execute_cmd(rc, ssl, buf, s);
+ execute_cmd(rc, res, buf, s);
+}
+
+/** handle SSL_do_handshake changes to the file descriptor to wait for later */
+static void
+remote_handshake_later(struct daemon_remote* rc, struct rc_state* s, int fd,
+ int r, int r2)
+{
+ if(r2 == SSL_ERROR_WANT_READ) {
+ if(s->shake_state == rc_hs_read) {
+ /* try again later */
+ return;
+ }
+ s->shake_state = rc_hs_read;
+ event_del(&s->c);
+ event_set(&s->c, fd, EV_PERSIST|EV_TIMEOUT|EV_READ,
+ remote_control_callback, s);
+ if(event_base_set(xfrd->event_base, &s->c) != 0)
+ log_msg(LOG_ERR, "remote_accept: cannot set event_base");
+ if(event_add(&s->c, &s->tval) != 0)
+ log_msg(LOG_ERR, "remote_accept: cannot add event");
+ return;
+ } else if(r2 == SSL_ERROR_WANT_WRITE) {
+ if(s->shake_state == rc_hs_write) {
+ /* try again later */
+ return;
+ }
+ s->shake_state = rc_hs_write;
+ event_del(&s->c);
+ event_set(&s->c, fd, EV_PERSIST|EV_TIMEOUT|EV_WRITE,
+ remote_control_callback, s);
+ if(event_base_set(xfrd->event_base, &s->c) != 0)
+ log_msg(LOG_ERR, "remote_accept: cannot set event_base");
+ if(event_add(&s->c, &s->tval) != 0)
+ log_msg(LOG_ERR, "remote_accept: cannot add event");
+ return;
+ } else {
+ if(r == 0)
+ log_msg(LOG_ERR, "remote control connection closed prematurely");
+ log_crypto_err("remote control failed ssl");
+ clean_point(rc, s);
+ }
}
static void
remote_control_callback(int fd, short event, void* arg)
{
+ RES res;
struct rc_state* s = (struct rc_state*)arg;
struct daemon_remote* rc = s->rc;
int r;
clean_point(rc, s);
return;
}
- /* (continue to) setup the SSL connection */
- ERR_clear_error();
- r = SSL_do_handshake(s->ssl);
- if(r != 1) {
- int r2 = SSL_get_error(s->ssl, r);
- if(r2 == SSL_ERROR_WANT_READ) {
- if(s->shake_state == rc_hs_read) {
- /* try again later */
- return;
- }
- s->shake_state = rc_hs_read;
- event_del(&s->c);
- event_set(&s->c, fd, EV_PERSIST|EV_TIMEOUT|EV_READ,
- remote_control_callback, s);
- if(event_base_set(xfrd->event_base, &s->c) != 0)
- log_msg(LOG_ERR, "remote_accept: cannot set event_base");
- if(event_add(&s->c, &s->tval) != 0)
- log_msg(LOG_ERR, "remote_accept: cannot add event");
- return;
- } else if(r2 == SSL_ERROR_WANT_WRITE) {
- if(s->shake_state == rc_hs_write) {
- /* try again later */
- return;
- }
- s->shake_state = rc_hs_write;
- event_del(&s->c);
- event_set(&s->c, fd, EV_PERSIST|EV_TIMEOUT|EV_WRITE,
- remote_control_callback, s);
- if(event_base_set(xfrd->event_base, &s->c) != 0)
- log_msg(LOG_ERR, "remote_accept: cannot set event_base");
- if(event_add(&s->c, &s->tval) != 0)
- log_msg(LOG_ERR, "remote_accept: cannot add event");
- return;
- } else {
- if(r == 0)
- log_msg(LOG_ERR, "remote control connection closed prematurely");
- log_crypto_err("remote control failed ssl");
- clean_point(rc, s);
+ if(s->ssl) {
+ /* (continue to) setup the SSL connection */
+ ERR_clear_error();
+ r = SSL_do_handshake(s->ssl);
+ if(r != 1) {
+ int r2 = SSL_get_error(s->ssl, r);
+ remote_handshake_later(rc, s, fd, r, r2);
return;
}
+ s->shake_state = rc_none;
}
- s->shake_state = rc_none;
/* once handshake has completed, check authentication */
- if(SSL_get_verify_result(s->ssl) == X509_V_OK) {
+ if (!rc->use_cert) {
+ VERBOSITY(3, (LOG_INFO, "unauthenticated remote control connection"));
+ } else if(SSL_get_verify_result(s->ssl) == X509_V_OK) {
X509* x = SSL_get_peer_certificate(s->ssl);
if(!x) {
VERBOSITY(2, (LOG_INFO, "remote control connection "
}
/* if OK start to actually handle the request */
- handle_req(rc, s, s->ssl);
+ res.ssl = s->ssl;
+ res.fd = fd;
+ handle_req(rc, s, &res);
if(!s->in_stats_list) {
VERBOSITY(3, (LOG_INFO, "remote control operation completed"));
/** print long number */
static int
-print_longnum(SSL* ssl, char* desc, uint64_t x)
+print_longnum(RES* ssl, char* desc, uint64_t x)
{
if(x > (uint64_t)1024*1024*1024) {
/* more than a Gb */
size_t front = (size_t)(x / (uint64_t)1000000);
size_t back = (size_t)(x % (uint64_t)1000000);
- return ssl_printf(ssl, "%s%u%6.6u\n", desc,
- (unsigned)front, (unsigned)back);
+ return ssl_printf(ssl, "%s%lu%6.6lu\n", desc,
+ (unsigned long)front, (unsigned long)back);
} else {
- return ssl_printf(ssl, "%s%u\n", desc, (unsigned)x);
+ return ssl_printf(ssl, "%s%lu\n", desc, (unsigned long)x);
}
}
/* print one block of statistics. n is name and d is delimiter */
static void
-print_stat_block(SSL* ssl, char* n, char* d, struct nsdst* st)
+print_stat_block(RES* ssl, char* n, char* d, struct nsdst* st)
{
const char* rcstr[] = {"NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN",
"NOTIMP", "REFUSED", "YXDOMAIN", "YXRRSET", "NXRRSET", "NOTAUTH",
if(inhibit_zero && st->qtype[i] == 0 &&
strncmp(rrtype_to_string(i), "TYPE", 4) == 0)
continue;
- if(!ssl_printf(ssl, "%s%snum.type.%s=%u\n", n, d,
- rrtype_to_string(i), (unsigned)st->qtype[i]))
+ if(!ssl_printf(ssl, "%s%snum.type.%s=%lu\n", n, d,
+ rrtype_to_string(i), (unsigned long)st->qtype[i]))
return;
}
for(i=0; i<6; i++) {
if(inhibit_zero && st->opcode[i] == 0 && i != OPCODE_QUERY)
continue;
- if(!ssl_printf(ssl, "%s%snum.opcode.%s=%u\n", n, d,
- opcode2str(i), (unsigned)st->opcode[i]))
+ if(!ssl_printf(ssl, "%s%snum.opcode.%s=%lu\n", n, d,
+ opcode2str(i), (unsigned long)st->opcode[i]))
return;
}
for(i=0; i<4; i++) {
if(inhibit_zero && st->qclass[i] == 0 && i != CLASS_IN)
continue;
- if(!ssl_printf(ssl, "%s%snum.class.%s=%u\n", n, d,
- rrclass_to_string(i), (unsigned)st->qclass[i]))
+ if(!ssl_printf(ssl, "%s%snum.class.%s=%lu\n", n, d,
+ rrclass_to_string(i), (unsigned long)st->qclass[i]))
return;
}
if(inhibit_zero && st->rcode[i] == 0 &&
i > RCODE_YXDOMAIN) /* NSD does not use larger */
continue;
- if(!ssl_printf(ssl, "%s%snum.rcode.%s=%u\n", n, d, rcstr[i],
- (unsigned)st->rcode[i]))
+ if(!ssl_printf(ssl, "%s%snum.rcode.%s=%lu\n", n, d, rcstr[i],
+ (unsigned long)st->rcode[i]))
return;
}
/* edns */
- if(!ssl_printf(ssl, "%s%snum.edns=%u\n", n, d, (unsigned)st->edns))
+ if(!ssl_printf(ssl, "%s%snum.edns=%lu\n", n, d, (unsigned long)st->edns))
return;
/* ednserr */
- if(!ssl_printf(ssl, "%s%snum.ednserr=%u\n", n, d,
- (unsigned)st->ednserr))
+ if(!ssl_printf(ssl, "%s%snum.ednserr=%lu\n", n, d,
+ (unsigned long)st->ednserr))
return;
/* qudp */
- if(!ssl_printf(ssl, "%s%snum.udp=%u\n", n, d, (unsigned)st->qudp))
+ if(!ssl_printf(ssl, "%s%snum.udp=%lu\n", n, d, (unsigned long)st->qudp))
return;
/* qudp6 */
- if(!ssl_printf(ssl, "%s%snum.udp6=%u\n", n, d, (unsigned)st->qudp6))
+ if(!ssl_printf(ssl, "%s%snum.udp6=%lu\n", n, d, (unsigned long)st->qudp6))
return;
/* ctcp */
- if(!ssl_printf(ssl, "%s%snum.tcp=%u\n", n, d, (unsigned)st->ctcp))
+ if(!ssl_printf(ssl, "%s%snum.tcp=%lu\n", n, d, (unsigned long)st->ctcp))
return;
/* ctcp6 */
- if(!ssl_printf(ssl, "%s%snum.tcp6=%u\n", n, d, (unsigned)st->ctcp6))
+ if(!ssl_printf(ssl, "%s%snum.tcp6=%lu\n", n, d, (unsigned long)st->ctcp6))
return;
/* nona */
- if(!ssl_printf(ssl, "%s%snum.answer_wo_aa=%u\n", n, d,
- (unsigned)st->nona))
+ if(!ssl_printf(ssl, "%s%snum.answer_wo_aa=%lu\n", n, d,
+ (unsigned long)st->nona))
return;
/* rxerr */
- if(!ssl_printf(ssl, "%s%snum.rxerr=%u\n", n, d, (unsigned)st->rxerr))
+ if(!ssl_printf(ssl, "%s%snum.rxerr=%lu\n", n, d, (unsigned long)st->rxerr))
return;
/* txerr */
- if(!ssl_printf(ssl, "%s%snum.txerr=%u\n", n, d, (unsigned)st->txerr))
+ if(!ssl_printf(ssl, "%s%snum.txerr=%lu\n", n, d, (unsigned long)st->txerr))
return;
/* number of requested-axfr, number of times axfr served to clients */
- if(!ssl_printf(ssl, "%s%snum.raxfr=%u\n", n, d, (unsigned)st->raxfr))
+ if(!ssl_printf(ssl, "%s%snum.raxfr=%lu\n", n, d, (unsigned long)st->raxfr))
return;
/* truncated */
- if(!ssl_printf(ssl, "%s%snum.truncated=%u\n", n, d,
- (unsigned)st->truncated))
+ if(!ssl_printf(ssl, "%s%snum.truncated=%lu\n", n, d,
+ (unsigned long)st->truncated))
return;
/* dropped */
- if(!ssl_printf(ssl, "%s%snum.dropped=%u\n", n, d,
- (unsigned)st->dropped))
+ if(!ssl_printf(ssl, "%s%snum.dropped=%lu\n", n, d,
+ (unsigned long)st->dropped))
return;
}
}
static void
-zonestat_print(SSL* ssl, xfrd_state_type* xfrd, int clear)
+zonestat_print(RES* ssl, xfrd_state_type* xfrd, int clear)
{
struct zonestatname* n;
struct nsdst stat0, stat1;
}
/* stat0 contains the details that we want to print */
- if(!ssl_printf(ssl, "%s%snum.queries=%u\n", name, ".",
- (unsigned)(stat0.qudp + stat0.qudp6 + stat0.ctcp +
+ if(!ssl_printf(ssl, "%s%snum.queries=%lu\n", name, ".",
+ (unsigned long)(stat0.qudp + stat0.qudp6 + stat0.ctcp +
stat0.ctcp6)))
return;
print_stat_block(ssl, name, ".", &stat0);
#endif /* USE_ZONE_STATS */
static void
-print_stats(SSL* ssl, xfrd_state_type* xfrd, struct timeval* now, int clear)
+print_stats(RES* ssl, xfrd_state_type* xfrd, struct timeval* now, int clear)
{
size_t i;
stc_type total = 0;
/* per CPU and total */
for(i=0; i<xfrd->nsd->child_count; i++) {
- if(!ssl_printf(ssl, "server%d.queries=%u\n", (int)i,
- (unsigned)xfrd->nsd->children[i].query_count))
+ if(!ssl_printf(ssl, "server%d.queries=%lu\n", (int)i,
+ (unsigned long)xfrd->nsd->children[i].query_count))
return;
total += xfrd->nsd->children[i].query_count;
}
- if(!ssl_printf(ssl, "num.queries=%u\n", (unsigned)total))
+ if(!ssl_printf(ssl, "num.queries=%lu\n", (unsigned long)total))
return;
/* time elapsed and uptime (in seconds) */
timeval_subtract(&uptime, now, &xfrd->nsd->rc->boot_time);
timeval_subtract(&elapsed, now, &xfrd->nsd->rc->stats_time);
- if(!ssl_printf(ssl, "time.boot=%u.%6.6u\n",
- (unsigned)uptime.tv_sec, (unsigned)uptime.tv_usec))
+ if(!ssl_printf(ssl, "time.boot=%lu.%6.6lu\n",
+ (unsigned long)uptime.tv_sec, (unsigned long)uptime.tv_usec))
return;
- if(!ssl_printf(ssl, "time.elapsed=%u.%6.6u\n",
- (unsigned)elapsed.tv_sec, (unsigned)elapsed.tv_usec))
+ if(!ssl_printf(ssl, "time.elapsed=%lu.%6.6lu\n",
+ (unsigned long)elapsed.tv_sec, (unsigned long)elapsed.tv_usec))
return;
/* mem info, database on disksize */
print_stat_block(ssl, "", "", &xfrd->nsd->st);
/* zone statistics */
- if(!ssl_printf(ssl, "zone.master=%u\n",
- (unsigned)(xfrd->notify_zones->count - xfrd->zones->count)))
+ if(!ssl_printf(ssl, "zone.master=%lu\n",
+ (unsigned long)(xfrd->notify_zones->count - xfrd->zones->count)))
return;
- if(!ssl_printf(ssl, "zone.slave=%u\n", (unsigned)xfrd->zones->count))
+ if(!ssl_printf(ssl, "zone.slave=%lu\n", (unsigned long)xfrd->zones->count))
return;
#ifdef USE_ZONE_STATS
zonestat_print(ssl, xfrd, clear); /* per-zone statistics */
void
daemon_remote_process_stats(struct daemon_remote* rc)
{
+ RES res;
struct rc_state* s;
struct timeval now;
if(!rc) return;
/* pop one and give it stats */
while((s = rc->stats_list)) {
assert(s->in_stats_list);
- print_stats(s->ssl, rc->xfrd, &now, (s->in_stats_list == 1));
+ res.ssl = s->ssl;
+ res.fd = s->fd;
+ print_stats(&res, rc->xfrd, &now, (s->in_stats_list == 1));
if(s->in_stats_list == 1) {
clear_stats(rc->xfrd);
rc->stats_time = now;
}
#endif /* BIND8_STATS */
+int
+create_local_accept_sock(const char *path, int* noproto)
+{
+#ifdef HAVE_SYS_UN_H
+ int s;
+ struct sockaddr_un usock;
+
+ VERBOSITY(3, (LOG_INFO, "creating unix socket %s", path));
+#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
+ /* this member exists on BSDs, not Linux */
+ usock.sun_len = (unsigned)sizeof(usock);
+#endif
+ usock.sun_family = AF_LOCAL;
+ /* length is 92-108, 104 on FreeBSD */
+ (void)strlcpy(usock.sun_path, path, sizeof(usock.sun_path));
+
+ if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) {
+ log_msg(LOG_ERR, "Cannot create local socket %s (%s)",
+ path, strerror(errno));
+ return -1;
+ }
+
+ if (unlink(path) && errno != ENOENT) {
+ /* The socket already exists and cannot be removed */
+ log_msg(LOG_ERR, "Cannot remove old local socket %s (%s)",
+ path, strerror(errno));
+ goto err;
+ }
+
+ if (bind(s, (struct sockaddr *)&usock,
+ (socklen_t)sizeof(struct sockaddr_un)) == -1) {
+ log_msg(LOG_ERR, "Cannot bind local socket %s (%s)",
+ path, strerror(errno));
+ goto err;
+ }
+
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
+ log_msg(LOG_ERR, "Cannot set non-blocking mode");
+ goto err;
+ }
+
+ if (listen(s, TCP_BACKLOG) == -1) {
+ log_msg(LOG_ERR, "can't listen: %s", strerror(errno));
+ goto err;
+ }
+
+ (void)noproto; /*unused*/
+ return s;
+
+err:
+ close(s);
+ return -1;
+
+#else
+ (void)use_systemd;
+ (void)path;
+ log_msg(LOG_ERR, "Local sockets are not supported");
+ *noproto = 1;
+ return -1;
+#endif
+}
+
#endif /* HAVE_SSL */