Commit 8de33ea6 authored by Marek Vavrusa's avatar Marek Vavrusa

Reworked NOTIFY event mechanism to be truly thread-safe, bugfixes, more helpful output to log.

Commit refs #1253.
parent ed7295aa
...@@ -92,15 +92,15 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone); ...@@ -92,15 +92,15 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
//#define KNOT_RESPONSE_DEBUG //#define KNOT_RESPONSE_DEBUG
//#define KNOT_ZONEDB_DEBUG //#define KNOT_ZONEDB_DEBUG
//#define KNOT_DNAME_DEBUG //#define KNOT_DNAME_DEBUG
#define KNOT_NODE_DEBUG //#define KNOT_NODE_DEBUG
//#define KNOT_PACKET_DEBUG //#define KNOT_PACKET_DEBUG
//#define KNOT_EDNS_DEBUG //#define KNOT_EDNS_DEBUG
#define KNOT_RRSET_DEBUG //#define KNOT_RRSET_DEBUG
//#define KNOT_NSEC3_DEBUG //#define KNOT_NSEC3_DEBUG
//#define CUCKOO_DEBUG //#define CUCKOO_DEBUG
//#define CUCKOO_DEBUG_HASH //#define CUCKOO_DEBUG_HASH
#define KNOT_NS_DEBUG //#define KNOT_NS_DEBUG
#define KNOT_XFR_DEBUG //#define KNOT_XFR_DEBUG
//#define KNOT_DDNS_DEBUG //#define KNOT_DDNS_DEBUG
#ifdef KNOT_NS_DEBUG #ifdef KNOT_NS_DEBUG
......
...@@ -192,6 +192,11 @@ int main(int argc, char **argv) ...@@ -192,6 +192,11 @@ int main(int argc, char **argv)
"PID = %ld\n", (long)getpid()); "PID = %ld\n", (long)getpid());
} }
log_server_info("PID stored in %s\n", pidfile); log_server_info("PID stored in %s\n", pidfile);
size_t zcount = server->nameserver->zone_db->zone_count;
if (!zcount) {
log_server_warning("Server started, but no zones served.\n");
}
// Setup signal handler // Setup signal handler
struct sigaction sa; struct sigaction sa;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
//#define KNOTD_JOURNAL_DEBUG //#define KNOTD_JOURNAL_DEBUG
//#define KNOTD_NET_DEBUG //#define KNOTD_NET_DEBUG
//#define KNOTD_ZONES_DEBUG //#define KNOTD_ZONES_DEBUG
#define KNOTD_XFR_DEBUG //#define KNOTD_XFR_DEBUG
//#define KNOTD_NOTIFY_DEBUG //#define KNOTD_NOTIFY_DEBUG
//#define KNOTD_ZDUMP_DEBUG //#define KNOTD_ZDUMP_DEBUG
//#define KNOTD_ZLOAD_DEBUG //#define KNOTD_ZLOAD_DEBUG
......
...@@ -204,7 +204,7 @@ static int notify_check_and_schedule(knot_nameserver_t *nameserver, ...@@ -204,7 +204,7 @@ static int notify_check_and_schedule(knot_nameserver_t *nameserver,
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
int notify_process_request(knot_nameserver_t *nameserver, int notify_process_request(knot_nameserver_t *ns,
knot_packet_t *notify, knot_packet_t *notify,
sockaddr_t *from, sockaddr_t *from,
uint8_t *buffer, size_t *size) uint8_t *buffer, size_t *size)
...@@ -213,7 +213,7 @@ int notify_process_request(knot_nameserver_t *nameserver, ...@@ -213,7 +213,7 @@ int notify_process_request(knot_nameserver_t *nameserver,
* - it will be fine to merge the code somehow. * - it will be fine to merge the code somehow.
*/ */
if (notify == NULL || nameserver == NULL || buffer == NULL if (notify == NULL || ns == NULL || buffer == NULL
|| size == NULL || from == NULL) { || size == NULL || from == NULL) {
debug_notify("notify: invalid parameters for query\n"); debug_notify("notify: invalid parameters for query\n");
return KNOTD_EINVAL; return KNOTD_EINVAL;
...@@ -226,7 +226,10 @@ int notify_process_request(knot_nameserver_t *nameserver, ...@@ -226,7 +226,10 @@ int notify_process_request(knot_nameserver_t *nameserver,
ret = knot_packet_parse_rest(notify); ret = knot_packet_parse_rest(notify);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
debug_notify("notify: failed to parse NOTIFY query\n"); debug_notify("notify: failed to parse NOTIFY query\n");
return KNOTD_EMALF; knot_ns_error_response(ns, knot_packet_id(notify),
KNOT_RCODE_FORMERR, buffer,
size);
return KNOTD_EOK;
} }
} }
...@@ -235,20 +238,26 @@ int notify_process_request(knot_nameserver_t *nameserver, ...@@ -235,20 +238,26 @@ int notify_process_request(knot_nameserver_t *nameserver,
ret = notify_create_response(notify, buffer, size); ret = notify_create_response(notify, buffer, size);
if (ret != KNOTD_EOK) { if (ret != KNOTD_EOK) {
debug_notify("notify: failed to create NOTIFY response\n"); debug_notify("notify: failed to create NOTIFY response\n");
return KNOTD_ERROR; /*! \todo Some other error. */ knot_ns_error_response(ns, knot_packet_id(notify),
KNOT_RCODE_SERVFAIL, buffer,
size);
return KNOTD_EOK;
} }
// find the zone // find the zone
debug_notify("notify: looking up zone by name\n"); debug_notify("notify: looking up zone by name\n");
const knot_dname_t *qname = knot_packet_qname(notify); const knot_dname_t *qname = knot_packet_qname(notify);
const knot_zone_t *z = knot_zonedb_find_zone_for_name( const knot_zone_t *z = knot_zonedb_find_zone_for_name(
nameserver->zone_db, qname); ns->zone_db, qname);
if (z == NULL) { if (z == NULL) {
debug_notify("notify: failed to find zone by name\n"); debug_notify("notify: failed to find zone by name\n");
return KNOTD_ERROR; /*! \todo Some other error. */ knot_ns_error_response(ns, knot_packet_id(notify),
KNOT_RCODE_REFUSED, buffer,
size);
return KNOTD_EOK;
} }
notify_check_and_schedule(nameserver, z, from); notify_check_and_schedule(ns, z, from);
return KNOTD_EOK; return KNOTD_EOK;
} }
...@@ -281,9 +290,9 @@ int notify_process_response(knot_nameserver_t *nameserver, ...@@ -281,9 +290,9 @@ int notify_process_response(knot_nameserver_t *nameserver,
/* Match ID against awaited. */ /* Match ID against awaited. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone); zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
pthread_mutex_lock(&zd->lock);
uint16_t pkt_id = knot_packet_id(notify); uint16_t pkt_id = knot_packet_id(notify);
notify_ev_t *ev = 0, *match = 0; notify_ev_t *ev = 0, *match = 0;
pthread_mutex_lock(&zd->lock);
WALK_LIST(ev, zd->notify_pending) { WALK_LIST(ev, zd->notify_pending) {
if ((int)pkt_id == ev->msgid) { if ((int)pkt_id == ev->msgid) {
match = ev; match = ev;
...@@ -299,14 +308,9 @@ int notify_process_response(knot_nameserver_t *nameserver, ...@@ -299,14 +308,9 @@ int notify_process_response(knot_nameserver_t *nameserver,
} }
/* NOTIFY is now finished. */ /* NOTIFY is now finished. */
evsched_t *sched = ((server_t *)knot_ns_get_data(nameserver))->sched; zones_cancel_notify(zd, match);
if (match->timer) {
log_zone_info("NOTIFY query for zone %s answered.\n", /* Zone was removed/reloaded. */
zd->conf->name);
evsched_cancel(sched, (event_t *)match->timer);
evsched_schedule(sched, (event_t *)match->timer, 0);
match->timer = 0;
}
pthread_mutex_unlock(&zd->lock); pthread_mutex_unlock(&zd->lock);
log_server_info("Received response for pending NOTIFY query ID=%u\n", log_server_info("Received response for pending NOTIFY query ID=%u\n",
......
...@@ -32,7 +32,7 @@ typedef struct notify_ev_t { ...@@ -32,7 +32,7 @@ typedef struct notify_ev_t {
int retries; /*!< Number of retries. */ int retries; /*!< Number of retries. */
int msgid; /*!< ID of pending NOTIFY. */ int msgid; /*!< ID of pending NOTIFY. */
sockaddr_t addr; /*!< Slave server address. */ sockaddr_t addr; /*!< Slave server address. */
volatile struct event_t *timer; /*!< Event timer. */ struct event_t *timer; /*!< Event timer. */
knot_zone_t *zone; /*!< Associated zone. */ knot_zone_t *zone; /*!< Associated zone. */
} notify_ev_t; } notify_ev_t;
......
...@@ -42,6 +42,7 @@ static int evsched_run(dthread_t *thread) ...@@ -42,6 +42,7 @@ static int evsched_run(dthread_t *thread)
/* Process termination event. */ /* Process termination event. */
if (ev->type == EVSCHED_TERM) { if (ev->type == EVSCHED_TERM) {
evsched_event_finished(s);
evsched_event_free(s, ev); evsched_event_free(s, ev);
break; break;
} }
...@@ -49,7 +50,9 @@ static int evsched_run(dthread_t *thread) ...@@ -49,7 +50,9 @@ static int evsched_run(dthread_t *thread)
/* Process event. */ /* Process event. */
if (ev->type == EVSCHED_CB && ev->cb) { if (ev->type == EVSCHED_CB && ev->cb) {
ev->cb(ev); ev->cb(ev);
evsched_event_finished(s);
} else { } else {
evsched_event_finished(s);
evsched_event_free(s, ev); evsched_event_free(s, ev);
} }
......
...@@ -64,12 +64,9 @@ int udp_handle(uint8_t *qbuf, size_t qbuflen, size_t *resp_len, ...@@ -64,12 +64,9 @@ int udp_handle(uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
case KNOT_RESPONSE_NORMAL: case KNOT_RESPONSE_NORMAL:
res = zones_process_response(ns, addr, packet, res = zones_process_response(ns, addr, packet,
qbuf, resp_len); qbuf, resp_len);
// res = knot_ns_process_response();
break; break;
case KNOT_RESPONSE_AXFR: case KNOT_RESPONSE_AXFR:
case KNOT_RESPONSE_IXFR: case KNOT_RESPONSE_IXFR:
/*! \todo SLAVE DISABLED */
break;
case KNOT_RESPONSE_NOTIFY: case KNOT_RESPONSE_NOTIFY:
res = notify_process_response(ns, packet, addr, res = notify_process_response(ns, packet, addr,
qbuf, resp_len); qbuf, resp_len);
...@@ -91,8 +88,6 @@ int udp_handle(uint8_t *qbuf, size_t qbuflen, size_t *resp_len, ...@@ -91,8 +88,6 @@ int udp_handle(uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
case KNOT_QUERY_NOTIFY: case KNOT_QUERY_NOTIFY:
res = notify_process_request(ns, packet, addr, res = notify_process_request(ns, packet, addr,
qbuf, resp_len); qbuf, resp_len);
*resp_len = 0;
res = KNOTD_EOK;
break; break;
case KNOT_QUERY_UPDATE: case KNOT_QUERY_UPDATE:
default: default:
......
...@@ -96,7 +96,6 @@ static inline void qr_response_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -96,7 +96,6 @@ static inline void qr_response_ev(struct ev_loop *loop, ev_io *w, int revents)
msg.msg_namelen = qw->addr.len; msg.msg_namelen = qw->addr.len;
/* Receive msg. */ /* Receive msg. */
debug_xfr("qr_response_ev: reading response\n");
ssize_t n = recvmsg(w->fd, &msg, 0); ssize_t n = recvmsg(w->fd, &msg, 0);
size_t resp_len = sizeof(qbuf); size_t resp_len = sizeof(qbuf);
if (n > 0) { if (n > 0) {
...@@ -109,8 +108,10 @@ static inline void qr_response_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -109,8 +108,10 @@ static inline void qr_response_ev(struct ev_loop *loop, ev_io *w, int revents)
((server_t *)knot_ns_get_data(qw->ns))->sched; ((server_t *)knot_ns_get_data(qw->ns))->sched;
if (qw->ev) { if (qw->ev) {
evsched_cancel(sched, qw->ev); evsched_cancel(sched, qw->ev);
evsched_event_free(sched, qw->ev); if (qw->ev) {
qw->ev = 0; evsched_event_free(sched, qw->ev);
qw->ev = 0;
}
} }
/* Close after receiving response. */ /* Close after receiving response. */
...@@ -204,7 +205,7 @@ static inline void xfr_client_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -204,7 +205,7 @@ static inline void xfr_client_ev(struct ev_loop *loop, ev_io *w, int revents)
knotd_strerror(ret)); knotd_strerror(ret));
} }
} }
debug_xfr("xfr_client_ev: AXFR/IN transfer finished\n"); log_server_info("AXFR/IN transfer finished.\n");
break; break;
case XFR_TYPE_IIN: case XFR_TYPE_IIN:
/* Save changesets. */ /* Save changesets. */
...@@ -228,7 +229,7 @@ static inline void xfr_client_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -228,7 +229,7 @@ static inline void xfr_client_ev(struct ev_loop *loop, ev_io *w, int revents)
free(chs->sets); free(chs->sets);
free(chs); free(chs);
request->data = 0; request->data = 0;
debug_xfr("xfr_client_ev: IXFR/IN transfer finished\n"); log_server_info("IXFR/IN transfer finished.\n");
break; break;
default: default:
ret = KNOTD_EINVAL; ret = KNOTD_EINVAL;
...@@ -314,14 +315,49 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -314,14 +315,49 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents)
return; return;
} }
/* Update address. */
sockaddr_update(&req->addr);
int r_port = -1;
#ifdef DISABLE_IPV6
char r_addr[INET_ADDRSTRLEN];
memset(r_addr, 0, sizeof(r_addr));
#else
/* Load IPv6 addr if default. */
char r_addr[INET6_ADDRSTRLEN];
memset(r_addr, 0, sizeof(r_addr));
if (req->addr.family == AF_INET6) {
r_port = ntohs(req->addr.addr6.sin6_port);
inet_ntop(req->addr.family, &req->addr.addr6.sin6_addr,
r_addr, sizeof(r_addr));
}
#endif
/* Load IPv4 if set. */
if (req->addr.family == AF_INET) {
r_port = ntohs(req->addr.addr4.sin_port);
inet_ntop(req->addr.family, &req->addr.addr4.sin_addr,
r_addr, sizeof(r_addr));
}
/* Connect to remote. */ /* Connect to remote. */
if (req->session <= 0) { if (req->session <= 0) {
int fd = socket_create(req->addr.family, SOCK_STREAM); int fd = socket_create(req->addr.family, SOCK_STREAM);
if (fd < 0) { if (fd < 0) {
log_server_warning("Failed to create socket "
"(type=%s, family=%s).\n",
"SOCK_STREAM",
req->addr.family == AF_INET ?
"AF_INET" : "AF_INET6");
return; return;
} }
ret = connect(fd, req->addr.ptr, req->addr.len); ret = connect(fd, req->addr.ptr, req->addr.len);
if (ret < 0) { if (ret < 0) {
log_server_warning("Failed to connect to %cXFR master "
"at %s:%d.\n",
req->type == XFR_TYPE_AIN ? 'A' : 'I',
r_addr, r_port);
if (!knot_zone_contents(zone)) {
log_zone_notice("Zone AXFR bootstrap failed.\n");
}
return; return;
} }
...@@ -337,7 +373,8 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -337,7 +373,8 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents)
const knot_zone_contents_t *contents = knot_zone_contents(zone); const knot_zone_contents_t *contents = knot_zone_contents(zone);
if (!contents && req->type == XFR_TYPE_IIN) { if (!contents && req->type == XFR_TYPE_IIN) {
rcu_read_unlock(); rcu_read_unlock();
debug_xfr("xfr_in: failed start IXFR on zone with no contents\n"); log_server_warning("Failed start IXFR on zone with no "
"contents\n");
socket_close(req->session); socket_close(req->session);
return; return;
} }
...@@ -369,11 +406,13 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents) ...@@ -369,11 +406,13 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents)
} }
/* Send XFR query. */ /* Send XFR query. */
debug_xfr("xfr_in: sending XFR query (%zu bytes)\n", bufsize); log_server_info("Sending %cXFR query to %s:%d (%zu bytes).\n",
req->type == XFR_TYPE_AIN ? 'A' : 'I',
r_addr, r_port, bufsize);
ret = req->send(req->session, &req->addr, req->wire, bufsize); ret = req->send(req->session, &req->addr, req->wire, bufsize);
if (ret != bufsize) { if (ret != bufsize) {
debug_xfr("xfr_in: failed to send XFR query type %d\n", log_server_notice("Failed to send %cXFR query.",
req->type); req->type == XFR_TYPE_AIN ? 'A' : 'I');
socket_close(req->session); socket_close(req->session);
return; return;
} }
...@@ -569,14 +608,14 @@ int xfr_master(dthread_t *thread) ...@@ -569,14 +608,14 @@ int xfr_master(dthread_t *thread)
char r_addr[INET6_ADDRSTRLEN]; char r_addr[INET6_ADDRSTRLEN];
memset(r_addr, 0, sizeof(r_addr)); memset(r_addr, 0, sizeof(r_addr));
if (xfr.addr.family == AF_INET6) { if (xfr.addr.family == AF_INET6) {
r_port = xfr.addr.addr6.sin6_port; r_port = ntohs(xfr.addr.addr6.sin6_port);
inet_ntop(xfr.addr.family, &xfr.addr.addr6.sin6_addr, inet_ntop(xfr.addr.family, &xfr.addr.addr6.sin6_addr,
r_addr, sizeof(r_addr)); r_addr, sizeof(r_addr));
} }
#endif #endif
/* Load IPv4 if set. */ /* Load IPv4 if set. */
if (xfr.addr.family == AF_INET) { if (xfr.addr.family == AF_INET) {
r_port = xfr.addr.addr4.sin_port; r_port = ntohs(xfr.addr.addr4.sin_port);
inet_ntop(xfr.addr.family, &xfr.addr.addr4.sin_addr, inet_ntop(xfr.addr.family, &xfr.addr.addr4.sin_addr,
r_addr, sizeof(r_addr)); r_addr, sizeof(r_addr));
} }
......
...@@ -64,18 +64,9 @@ static int zonedata_destroy(knot_zone_t *zone) ...@@ -64,18 +64,9 @@ static int zonedata_destroy(knot_zone_t *zone)
/* Remove list of pending NOTIFYs. */ /* Remove list of pending NOTIFYs. */
pthread_mutex_lock(&zd->lock); pthread_mutex_lock(&zd->lock);
node *n = 0; notify_ev_t *ev = 0, *evn = 0;
WALK_LIST(n, zd->notify_pending) { WALK_LIST_DELSAFE(ev, evn, zd->notify_pending) {
notify_ev_t *ev = (notify_ev_t *)n; zones_cancel_notify(zd, ev);
if (ev->timer) {
ev->zone = 0;
evsched_t *sch = ev->timer->parent;
evsched_cancel(sch, (event_t *)ev->timer);
evsched_event_free(sch, (event_t *)ev->timer);
rem_node(&ev->n);
ev->timer = 0;
free(ev);
}
} }
pthread_mutex_unlock(&zd->lock); pthread_mutex_unlock(&zd->lock);
...@@ -255,8 +246,10 @@ static int zones_expire_ev(event_t *e) ...@@ -255,8 +246,10 @@ static int zones_expire_ev(event_t *e)
zonedata_t *zd = (zonedata_t *)zone->data; zonedata_t *zd = (zonedata_t *)zone->data;
if (zd->xfr_in.timer) { if (zd->xfr_in.timer) {
evsched_cancel(e->parent, zd->xfr_in.timer); evsched_cancel(e->parent, zd->xfr_in.timer);
evsched_event_free(e->parent, zd->xfr_in.timer); if (zd->xfr_in.timer) {
zd->xfr_in.timer = 0; evsched_event_free(e->parent, zd->xfr_in.timer);
zd->xfr_in.timer = 0;
}
} }
/* Delete self. */ /* Delete self. */
...@@ -311,9 +304,6 @@ static int zones_refresh_ev(event_t *e) ...@@ -311,9 +304,6 @@ static int zones_refresh_ev(event_t *e)
if (!knot_zone_contents(zone)) { if (!knot_zone_contents(zone)) {
/* Bootstrap from XFR master. */ /* Bootstrap from XFR master. */
evsched_cancel(e->parent, e);
/* Prepare XFR client transfer. */
knot_ns_xfr_t xfr_req; knot_ns_xfr_t xfr_req;
memset(&xfr_req, 0, sizeof(knot_ns_xfr_t)); memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
memcpy(&xfr_req.addr, &zd->xfr_in.master, sizeof(sockaddr_t)); memcpy(&xfr_req.addr, &zd->xfr_in.master, sizeof(sockaddr_t));
...@@ -327,7 +317,8 @@ static int zones_refresh_ev(event_t *e) ...@@ -327,7 +317,8 @@ static int zones_refresh_ev(event_t *e)
rcu_read_unlock(); rcu_read_unlock();
/* Enqueue XFR request. */ /* Enqueue XFR request. */
debug_zones("xfr_in: attempting to bootstrap zone from master\n"); log_zone_info("Attempting to bootstrap zone %s from master\n",
zd->conf->name);
return xfr_request(zd->server->xfr_h, &xfr_req); return xfr_request(zd->server->xfr_h, &xfr_req);
} }
...@@ -393,30 +384,36 @@ static int zones_notify_send(event_t *e) ...@@ -393,30 +384,36 @@ static int zones_notify_send(event_t *e)
{ {
notify_ev_t *ev = (notify_ev_t *)e->data; notify_ev_t *ev = (notify_ev_t *)e->data;
knot_zone_t *zone = ev->zone; knot_zone_t *zone = ev->zone;
knot_zone_contents_t *contents = knot_zone_get_contents(zone); if (!zone) {
if (!zone || !knot_zone_data(zone) || !contents) {
log_zone_error("notify: NOTIFY invalid event received\n"); log_zone_error("notify: NOTIFY invalid event received\n");
evsched_event_free(e->parent, (event_t *)ev->timer); evsched_event_free(e->parent, e);
free(ev); free(ev);
return KNOTD_EINVAL; return KNOTD_EINVAL;
} }
/* Check for answered/cancelled query. */ /* Check for answered/cancelled query. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone); zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
pthread_mutex_lock(&zd->lock); knot_zone_contents_t *contents = knot_zone_get_contents(zone);
if (ev->timer == NULL) {
debug_zones("notify: cancelling old NOTIFY timer for %s.\n", debug_notify("notify: NOTIFY timer event\n");
zd->conf->name);
evsched_cancel(e->parent, e); /* Reduce number of available retries. */
evsched_event_free(e->parent, e); --ev->retries;
/* Check number of retries. */
if (ev->retries < 0) {
log_server_notice("NOTIFY query maximum number of retries "
"for zone %s exceeded.\n",
zd->conf->name);
pthread_mutex_lock(&zd->lock);
debug_notify("notify: Deleting NOTIFY event because "
"maximum number of retries was reached.\n");
rem_node(&ev->n); rem_node(&ev->n);
pthread_mutex_unlock(&zd->lock); evsched_event_free(e->parent, e);
free(ev); free(ev);
return KNOTD_EOK; pthread_mutex_unlock(&zd->lock);
return KNOTD_EMALF;
} }
pthread_mutex_unlock(&zd->lock);
debug_zones("notify: NOTIFY timer event\n");
/* Prepare buffer for query. */ /* Prepare buffer for query. */
uint8_t qbuf[SOCKET_MTU_SZ]; uint8_t qbuf[SOCKET_MTU_SZ];
...@@ -456,32 +453,14 @@ static int zones_notify_send(event_t *e) ...@@ -456,32 +453,14 @@ static int zones_notify_send(event_t *e)
} }
/* Reduce number of available retries. */
--ev->retries;
/* Check number of retries. */
if (ev->retries <= 0) {
log_server_notice("NOTIFY query maximum number of retries "
"for zone %s exceeded.\n",
zd->conf->name);
pthread_mutex_lock(&zd->lock);
if (ev->timer) {
evsched_cancel(e->parent, e);
evsched_schedule(e->parent, e, 0);
ev->timer = 0;
}
pthread_mutex_unlock(&zd->lock);
return KNOTD_EMALF;
}
/* RFC suggests 60s, but it is configurable. */ /* RFC suggests 60s, but it is configurable. */
int retry_tmr = ev->timeout * 1000; int retry_tmr = ev->timeout * 1000;
/* Reschedule. */ /* Reschedule. */
evsched_schedule(e->parent, e, retry_tmr); evsched_schedule(e->parent, e, retry_tmr);
debug_zones("notify: RETRY after %u secs\n", debug_notify("notify: RETRY after %u secs\n",
retry_tmr / 1000); retry_tmr / 1000);
return ret; return ret;
} }
...@@ -1039,8 +1018,7 @@ static int zones_insert_zones(knot_nameserver_t *ns, ...@@ -1039,8 +1018,7 @@ static int zones_insert_zones(knot_nameserver_t *ns,
int ret = KNOT_ERROR; int ret = KNOT_ERROR;
if (reload) { if (reload) {
/* Zone file not exists and has master set. */ /* Zone file not exists and has master set. */
/*! \todo SLAVE DISABLED Bootstrapping is disabled. */ if (stat_ret < 0 && !EMPTY_LIST(z->acl.xfr_in)) {
if (0 && stat_ret < 0 && !EMPTY_LIST(z->acl.xfr_in)) {
/* Create stub database. */ /* Create stub database. */
debug_zones("Loading stub zone for bootstrap.\n"); debug_zones("Loading stub zone for bootstrap.\n");
...@@ -1998,27 +1976,39 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch) ...@@ -1998,27 +1976,39 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
/* Remove list of pending NOTIFYs. */ /* Remove list of pending NOTIFYs. */
pthread_mutex_lock(&zd->lock); pthread_mutex_lock(&zd->lock);
node *n = 0; notify_ev_t *ev = 0, *evn = 0;
WALK_LIST(n, zd->notify_pending) { WALK_LIST_DELSAFE(ev, evn, zd->notify_pending) {
notify_ev_t *ev = (notify_ev_t *)n; zones_cancel_notify(zd, ev);
if (ev->timer) {
evsched_cancel(sch, (event_t *)ev->timer);
evsched_schedule(sch, (event_t *)ev->timer, 0);
ev->timer = 0;
}
} }
pthread_mutex_unlock(&zd->lock); pthread_mutex_unlock(&zd->lock);
/* Check XFR/IN master server. */ /* Check XFR/IN master server. */
/*! \todo SLAVE DISABLED */ if (zd->xfr_in.master.ptr) {
// if (zd->xfr_in.master.ptr) {
// /* Schedule REFRESH timer. */ /* Schedule REFRESH timer. */
// uint32_t refresh_tmr = zones_soa_refresh(zone); uint32_t refresh_tmr = zones_soa_refresh(zone);
// zd->xfr_in.timer = evsched_schedule_cb(sch, zones_refresh_ev, zd->xfr_in.timer = evsched_schedule_cb(sch, zones_refresh_ev,
// zone, refresh_tmr); zone, refresh_tmr);
// debug_zones("notify: REFRESH set to %u\n", refresh_tmr); debug_zones("notify: REFRESH set to %u\n", refresh_tmr);
// } }
/* Schedule IXFR database syncing. */
/*! \todo Sync timer should not be reset after each xfr. */
int sync_timeout = cfzone->dbsync_timeout * 1000; /* Convert to ms. */
if (zd->ixfr_dbsync) {
evsched_cancel(sch, zd->ixfr_dbsync);
evsched_event_free(sch, zd->ixfr_dbsync);
zd->ixfr_dbsync = 0;
}
zd->ixfr_dbsync = evsched_schedule_cb(sch,
zones_zonefile_sync_ev,
zone, sync_timeout);
/* Do not issue NOTIFY queries if stub. */
if (!knot_zone_contents(zone)) {
conf_read_unlock();
return KNOTD_EOK;
}
/* Schedule NOTIFY to slaves. */ /* Schedule NOTIFY to slaves. */
conf_remote_t *r = 0; conf_remote_t *r = 0;
...@@ -2050,7 +2040,7 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch) ...@@ -2050,7 +2040,7 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
/* Prepare request. */ /* Prepare request. */
ev->retries = cfzone->notify_retries + 1; /* first + N retries*/ ev->retries = cfzone->notify_retries + 1; /* first + N retries*/
ev->msgid = -1; ev->msgid = 0;
ev->zone = zone; ev->zone = zone;
ev->timeout = cfzone->notify_timeout; ev->timeout = cfzone->notify_timeout;
...@@ -2066,19 +2056,49 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch) ...@@ -2066,19 +2056,49 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
tmr_s, cfg_if->address, cfg_if->port); tmr_s, cfg_if->address, cfg_if->port);
} }
/* Schedule IXFR database syncing. */ conf_read_unlock();
/*! \todo Sync timer should not be reset after each xfr. */
int sync_timeout = cfzone->dbsync_timeout * 1000; /* Convert to ms. */ return KNOTD_EOK;
if (zd->ixfr_dbsync) { }
evsched_cancel(sch, zd->ixfr_dbsync);
evsched_event_free(sch, zd->ixfr_dbsync); int zones_cancel_notify(zonedata_t *zd, notify_ev_t *ev)
zd->ixfr_dbsync = 0; {
if (!zd || !ev || !ev->timer) {
return KNOTD_EINVAL;
} }
zd->ixfr_dbsync = evsched_schedule_cb(sch,
zones_zonefile_sync_ev,
zone, sync_timeout);
conf_read_unlock();