From a8ae27a8bb3360021cf1db18b57591852b157463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz> Date: Tue, 29 Apr 2014 17:14:46 +0200 Subject: [PATCH] event/update: function cleanup and separation --- src/knot/nameserver/update.c | 48 ++++++++++++++++++++++++++++- src/knot/nameserver/update.h | 8 ++--- src/knot/zone/events.c | 60 ++++++++++++++---------------------- src/knot/zone/zone.c | 2 +- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index 4ecf54a03..99f1d7172 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -10,6 +10,10 @@ #include "libknot/tsig-op.h" #include "knot/zone/zone.h" +/* UPDATE-specific logging (internal, expects 'qdata' variable set). */ +#define UPDATE_LOG(severity, msg...) \ + QUERY_LOG(severity, qdata, "UPDATE", msg) + #warning merge file with ddns.c static int update_forward(knot_pkt_t *pkt, struct query_data *qdata) @@ -185,8 +189,14 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents, return ret; } -int process_ddns_pkt(zone_t *zone, const knot_pkt_t *query, uint16_t *rcode) +static int process_authenticated(uint16_t *rcode, struct query_data *qdata) { + assert(rcode); + assert(qdata); + + const knot_pkt_t *query = qdata->query; + zone_t *zone = (zone_t *)qdata->zone; + int ret = ddns_process_prereqs(query, zone->contents, rcode); if (ret != KNOT_EOK) { return ret; @@ -265,4 +275,40 @@ int process_ddns_pkt(zone_t *zone, const knot_pkt_t *query, uint16_t *rcode) return ret; } + +int update_process_query(knot_pkt_t *pkt, struct query_data *qdata) +{ + assert(pkt); + assert(qdata); + + UPDATE_LOG(LOG_INFO, "Started."); + + /* Keep original state. */ + struct timeval t_start, t_end; + gettimeofday(&t_start, NULL); + const zone_t *zone = qdata->zone; + const uint32_t old_serial = zone_contents_serial(zone->contents); + + /* Process authenticated packet. */ + uint16_t rcode = KNOT_RCODE_NOERROR; + int ret = process_authenticated(&rcode, qdata); + if (ret != KNOT_EOK) { + UPDATE_LOG(LOG_ERR, "%s\n", knot_strerror(ret)); + knot_wire_set_rcode(pkt->wire, rcode); + return ret; + } + + /* Evaluate response. */ + const uint32_t new_serial = zone_contents_serial(zone->contents); + if (new_serial == old_serial) { + UPDATE_LOG(LOG_NOTICE, "No change to zone made."); + return KNOT_EOK; + } + + gettimeofday(&t_end, NULL); + UPDATE_LOG(LOG_INFO, "Serial %u -> %u\n", old_serial, new_serial); + UPDATE_LOG(LOG_INFO, "Finished in %.02fs.", time_diff(&t_start, &t_end) / 1000.0); + return KNOT_EOK; +} + #undef UPDATE_LOG diff --git a/src/knot/nameserver/update.h b/src/knot/nameserver/update.h index 08628e08c..2f4acf5ab 100644 --- a/src/knot/nameserver/update.h +++ b/src/knot/nameserver/update.h @@ -41,18 +41,16 @@ struct query_data; int update_answer(knot_pkt_t *pkt, struct query_data *qdata); -/*! \brief Process already authenticated packet. */ /*! * \brief Processes serialized packet with DDNS. Function expects that the * query is already authenticated and TSIG signature is verified. * - * \param zone Zone to be updated. - * \param query Packet containing DDNS. - * \param rcode Output response code. + * \param pkt Prepared response packet. + * \param qdata Minimal query data context. * * \return KNOT_E* */ -int process_ddns_pkt(zone_t *zone, const knot_pkt_t *query, uint16_t *rcode); +int update_process_query(knot_pkt_t *pkt, struct query_data *qdata); #endif /* _KNOT_UPDATE_H_ */ diff --git a/src/knot/zone/events.c b/src/knot/zone/events.c index d8ea2047d..3e98c690b 100644 --- a/src/knot/zone/events.c +++ b/src/knot/zone/events.c @@ -309,53 +309,39 @@ static int event_xfer(zone_t *zone) return ret; } -static knot_pkt_t *create_ddns_resp(const knot_pkt_t *query, uint16_t rcode) -{ - knot_pkt_t *resp = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL); - if (resp == KNOT_EOK) { - return NULL; - } - - int ret = knot_pkt_init_response(resp, query); - if (ret != KNOT_EOK) { - knot_pkt_free(&resp); - } - - knot_wire_set_rcode(resp->wire, rcode); - return resp; -} - static int event_update(zone_t *zone) { assert(zone); - fprintf(stderr, "UPDATE of '%s' started.\n", zone->conf->name); - struct request_data *update = zone_update_dequeue(zone); - assert(update); - uint16_t rcode = KNOT_RCODE_NOERROR; - const uint32_t old_serial = zone_contents_serial(zone->contents); - int ret = process_ddns_pkt(zone, update->query, &rcode); - const uint32_t new_serial = zone_contents_serial(zone->contents); - - if (old_serial != new_serial) { - fprintf(stderr, "UPDATE of '%s': finished: %s\n.", - zone->conf->name, knot_strerror(ret)); - } else { - fprintf(stderr, "UPDATE of '%s': No change to zone made.\n", - zone->conf->name); - } - - knot_pkt_t *resp = create_ddns_resp(update->query, rcode); + knot_pkt_t *resp = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL); if (resp == NULL) { - knot_pkt_free(&resp); - knot_pkt_free(&update->query); return KNOT_ENOMEM; } - // Send response to knsupdate. + struct request_data *update = zone_update_dequeue(zone); + + /* Initialize query response. */ + assert(update); + assert(update->query); + knot_pkt_init_response(resp, update->query); + + /* Create minimal query data context. */ + struct process_query_param param = {0}; + param.remote = &update->remote; + struct query_data qdata = {0}; + qdata.param = ¶m; + qdata.query = update->query; + qdata.zone = zone; + + /* Process the update query. */ + int ret = update_process_query(resp, &qdata); + + /* Send response. */ +#warning TODO: proper API for this sendto(update->fd, resp->wire, resp->size, 0, - (struct sockaddr *)update->remote, sockaddr_len(update->remote)); + (struct sockaddr *)param.remote, sockaddr_len(param.remote)); + /* Cleanup. */ knot_pkt_free(&resp); knot_pkt_free(&update->query); free(update); diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c index 8abae4539..fee200dac 100644 --- a/src/knot/zone/zone.c +++ b/src/knot/zone/zone.c @@ -319,7 +319,7 @@ int zone_update_enqueue(zone_t *zone, knot_pkt_t *pkt, struct process_query_para memset(req, 0, sizeof(struct request_data)); req->fd = param->socket; - req->remote = param->remote; + memcpy(&req->remote, param->remote, sizeof(struct sockaddr_storage)); req->query = knot_pkt_copy(pkt, NULL); if (req->query == NULL) { free(req); -- GitLab