Skip to content
Snippets Groups Projects
Commit 812dc1aa authored by Daniel Salzman's avatar Daniel Salzman
Browse files

Merge branch 'nsupdate_update_fixed' into 'master'

Nsupdate Update Fixed
parents b6c4c4e7 1529c1b7
No related branches found
No related tags found
No related merge requests found
......@@ -10,6 +10,10 @@
#include "common/descriptor.h"
#include "knot/server/zones.h"
/* AXFR-specific logging (internal, expects 'qdata' variable set). */
#define UPDATE_LOG(severity, msg...) \
QUERY_LOG(severity, qdata, "UPDATE", msg)
static int update_forward(struct query_data *qdata)
{
/*! \todo This will be implemented when RESPONSE and REQUEST processors
......@@ -62,18 +66,6 @@ static int update_forward(struct query_data *qdata)
return NS_PROC_FAIL;
}
static int update_process(knot_pkt_t *resp, struct query_data *qdata)
{
/*! \todo Reusing the API for compatibility reasons. */
knot_rcode_t rcode = qdata->rcode;
int ret = zones_process_update_auth((knot_zone_t *)qdata->zone, qdata->query,
&rcode,
&qdata->param->query_source,
qdata->sign.tsig_key);
qdata->rcode = rcode;
return ret;
}
static int update_prereq_check(struct query_data *qdata)
{
knot_pkt_t *query = qdata->query;
......@@ -97,24 +89,42 @@ static int update_prereq_check(struct query_data *qdata)
return ret;
}
static int update_process(knot_pkt_t *resp, struct query_data *qdata)
{
/* Check prerequisites. */
int ret = update_prereq_check(qdata);
if (ret != KNOT_EOK) {
return ret;
}
/*! \todo Reusing the API for compatibility reasons. */
knot_rcode_t rcode = qdata->rcode;
ret = zones_process_update_auth((knot_zone_t *)qdata->zone, qdata->query,
&rcode,
&qdata->param->query_source,
qdata->sign.tsig_key);
qdata->rcode = rcode;
return ret;
}
int update_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata)
{
/* RFC1996 require SOA question. */
NS_NEED_QTYPE(qdata, KNOT_RRTYPE_SOA, KNOT_RCODE_FORMERR);
/* Need valid transaction security. */
zonedata_t *zone_data = (zonedata_t *)knot_zone_data(qdata->zone);
NS_NEED_AUTH(zone_data->update_in, qdata);
/*! \note NOTIFY/RFC1996 isn't clear on error RCODEs.
* Most servers use NOTAUTH from RFC2136. */
NS_NEED_VALID_ZONE(qdata, KNOT_RCODE_NOTAUTH);
/* Allow pass-through of an unknown TSIG in DDNS forwarding (must have zone). */
zonedata_t *zone_data = (zonedata_t *)knot_zone_data(qdata->zone);
if (zone_data->xfr_in.has_master) {
return update_forward(qdata);
}
/* Need valid transaction security. */
NS_NEED_AUTH(zone_data->update_in, qdata);
/*
* Check if UPDATE not running already.
*/
......@@ -126,21 +136,30 @@ int update_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qda
return NS_PROC_FAIL;
}
struct timeval t_start = {0}, t_end = {0};
gettimeofday(&t_start, NULL);
UPDATE_LOG(LOG_INFO, "Started (serial %u).", knot_zone_serial(qdata->zone->contents));
/* Reserve space for TSIG. */
knot_pkt_reserve(pkt, tsig_wire_maxsize(qdata->sign.tsig_key));
/* Check prerequisites. */
if (update_prereq_check(qdata) != KNOT_EOK) {
pthread_mutex_unlock(&zone_data->ddns_lock);
return NS_PROC_FAIL;
}
/* Process UPDATE. */
if (update_process(pkt, qdata) != KNOT_EOK) {
pthread_mutex_unlock(&zone_data->ddns_lock);
return NS_PROC_FAIL;
}
int ret = update_process(pkt, qdata);
pthread_mutex_unlock(&zone_data->ddns_lock);
return NS_PROC_DONE;
/* Evaluate */
switch(ret) {
case KNOT_EOK: /* Last response. */
gettimeofday(&t_end, NULL);
UPDATE_LOG(LOG_INFO, "Finished in %.02fs.",
time_diff(&t_start, &t_end) / 1000.0);
return NS_PROC_DONE;
break;
default: /* Generic error. */
UPDATE_LOG(LOG_ERR, "%s", knot_strerror(ret));
return NS_PROC_FAIL;
}
}
#undef UPDATE_LOG
......@@ -943,7 +943,6 @@ int zones_process_update_auth(knot_zone_t *zone, knot_pkt_t *query,
assert(addr);
int ret = KNOT_EOK;
dbg_zones_verb("TSIG check successful. Answering query.\n");
/* Create log message prefix. */
char *keytag = NULL;
......@@ -956,7 +955,6 @@ int zones_process_update_auth(knot_zone_t *zone, knot_pkt_t *query,
zone_name, r_str ? r_str : "'unknown'");
free(r_str);
free(keytag);
log_zone_info("%s Started.\n", msg);
/*!
* We must prepare a changesets_t structure even though there will
......@@ -984,10 +982,8 @@ int zones_process_update_auth(knot_zone_t *zone, knot_pkt_t *query,
ret = knot_ns_process_update(query, old_contents, &new_contents,
chgsets, rcode, new_serial);
if (ret != KNOT_EOK) {
if (ret < 0) {
log_zone_error("%s %s\n", msg, knot_strerror(ret));
} else {
log_zone_notice("%s No change to zone made.\n", msg);
if (ret > 0) {
log_zone_notice("%s: No change to zone made.\n", msg);
*rcode = KNOT_RCODE_NOERROR;
}
......@@ -1174,9 +1170,8 @@ int zones_process_update_auth(knot_zone_t *zone, knot_pkt_t *query,
assert(ret == KNOT_EOK);
*rcode = KNOT_RCODE_NOERROR; /* Mark as successful. */
if (new_signatures) {
log_zone_info("%s Signed.\n", msg);
log_zone_info("%s: Signed.\n", msg);
}
log_zone_info("%s Finished.\n", msg);
free(msg);
msg = NULL;
......
......@@ -486,7 +486,6 @@ void print_packet(const knot_pkt_t *packet,
uint16_t arcount = additional->count;
uint16_t ancount = answers->count;
// Print packet information header.
if (style->show_header) {
print_header(packet, style);
......
......@@ -34,6 +34,7 @@
#include "common/descriptor.h"
#include "libknot/common.h"
#include "libknot/libknot.h"
#include "libknot/dnssec/random.h"
/* Declarations of cmd parse functions. */
typedef int (*cmd_handle_f)(const char *lp, nsupdate_params_t *params);
......@@ -287,44 +288,28 @@ static srv_info_t *parse_host(const char *lp, const char* default_port)
return srv;
}
static int pkt_append(nsupdate_params_t *p, int sect)
/* Append parsed RRSet to list. */
static int rr_list_append(scanner_t *s, list_t *target_list, mm_ctx_t *mm)
{
/* Check packet state first. */
int ret = KNOT_EOK;
knot_dname_t * qname = NULL;
scanner_t *s = p->rrp;
if (!p->pkt) {
p->pkt = create_empty_packet(MAX_PACKET_SIZE);
qname = knot_dname_from_str(p->zone);
ret = knot_pkt_put_question(p->pkt, qname, p->class_num, p->type_num);
knot_dname_free(&qname);
if (ret != KNOT_EOK)
return ret;
knot_wire_set_opcode(p->pkt->wire, KNOT_OPCODE_UPDATE);
}
/* Form a rrset. */
knot_dname_t *o = knot_dname_copy(s->r_owner);
if (!o) {
DBG("%s: failed to create dname - %s\n",
__func__, knot_strerror(ret));
knot_dname_t *owner = knot_dname_copy(s->r_owner);
if (!owner) {
DBG("%s: failed to create dname\n", __func__);
return KNOT_ENOMEM;
}
knot_rrset_t *rr = knot_rrset_new(o, s->r_type, s->r_class, s->r_ttl);
knot_rrset_t *rr = knot_rrset_new(owner, s->r_type, s->r_class, s->r_ttl);
if (!rr) {
DBG("%s: failed to create rrset - %s\n",
__func__, knot_strerror(ret));
knot_dname_free(&o);
DBG("%s: failed to create rrset\n", __func__);
knot_dname_free(&owner);
return KNOT_ENOMEM;
}
/* Create RDATA (not for NXRRSET prereq). */
if (s->r_data_length > 0 && sect != PQ_NXRRSET) {
/* Create RDATA. */
if (s->r_data_length > 0) {
size_t pos = 0;
ret = knot_rrset_rdata_from_wire_one(rr, s->r_data, &pos,
s->r_data_length,
s->r_data_length);
int ret = knot_rrset_rdata_from_wire_one(rr, s->r_data, &pos,
s->r_data_length,
s->r_data_length);
if (ret != KNOT_EOK) {
DBG("%s: failed to set rrset from wire - %s\n",
__func__, knot_strerror(ret));
......@@ -333,43 +318,72 @@ static int pkt_append(nsupdate_params_t *p, int sect)
}
}
/* Add to correct section.
* ZONES ... QD section.
* UPDATE ... NS section.
* PREREQ ... AN section.
* ADDIT. ... same.
*/
switch(sect) {
case UP_ADD:
case UP_DEL:
ret = knot_pkt_put(p->pkt, 0, rr, KNOT_PF_NOTRUNC);
break;
case PQ_NXDOMAIN:
case PQ_NXRRSET:
case PQ_YXDOMAIN:
case PQ_YXRRSET:
ret = knot_pkt_put(p->pkt, 0, rr, KNOT_PF_NOTRUNC);
break;
default:
assert(0); /* Should never happen. */
break;
if (ptrlist_add(target_list, rr, mm) == NULL) {
knot_rrset_free(&rr);
return KNOT_ENOMEM;
}
if (ret != KNOT_EOK) {
DBG("%s: failed to append rdata to appropriate section - %s\n",
__func__, knot_strerror(ret));
if (ret == KNOT_ESPACE) {
ERR("exceeded UPDATE message maximum size %zu\n",
p->pkt->max_size);
return KNOT_EOK;
}
/*! \brief Write RRSet list to packet section. */
static int rr_list_to_packet(knot_pkt_t *dst, list_t *list)
{
assert(dst != NULL);
assert(list != NULL);
int ret = KNOT_EOK;
ptrnode_t *node = NULL;
WALK_LIST(node, *list) {
ret = knot_pkt_put(dst, COMPR_HINT_NONE, (knot_rrset_t *)node->d, 0);
if (ret != KNOT_EOK) {
break;
}
}
return ret;
}
static int pkt_sendrecv(nsupdate_params_t *params,
uint8_t *qwire, size_t qlen,
uint8_t *rwire, size_t rlen)
/*! \brief Build UPDATE query. */
static int build_query(nsupdate_params_t *params)
{
/* Clear old query. */
knot_pkt_t *query = params->query;
knot_pkt_clear(query);
/* Write question. */
knot_wire_set_id(query->wire, knot_random_uint16_t());
knot_wire_set_opcode(query->wire, KNOT_OPCODE_UPDATE);
knot_dname_t *qname = knot_dname_from_str(params->zone);
int ret = knot_pkt_put_question(query, qname, params->class_num, params->type_num);
knot_dname_free(&qname);
if (ret != KNOT_EOK)
return ret;
/* Now, PREREQ => ANSWER section. */
ret = knot_pkt_begin(query, KNOT_ANSWER);
if (ret != KNOT_EOK) {
return ret;
}
/* Write PREREQ. */
ret = rr_list_to_packet(query, &params->prereq_list);
if (ret != KNOT_EOK) {
return ret;
}
/* Now, UPDATE data => AUTHORITY section. */
ret = knot_pkt_begin(query, KNOT_AUTHORITY);
if (ret != KNOT_EOK) {
return ret;
}
/* Write UPDATE data. */
return rr_list_to_packet(query, &params->update_list);
}
static int pkt_sendrecv(nsupdate_params_t *params)
{
net_t net;
int ret;
......@@ -390,20 +404,25 @@ static int pkt_sendrecv(nsupdate_params_t *params,
return -1;
}
ret = net_send(&net, qwire, qlen);
ret = net_send(&net, params->query->wire, params->query->size);
if (ret != KNOT_EOK) {
net_close(&net);
net_clean(&net);
return -1;
}
/* Clear response buffer. */
knot_pkt_clear(params->answer);
/* Wait for reception. */
int rb = net_receive(&net, rwire, rlen);
int rb = net_receive(&net, params->answer->wire, params->answer->max_size);
DBG("%s: receive_msg = %d\n", __func__, rb);
if (rb <= 0) {
net_close(&net);
net_clean(&net);
return -1;
} else {
params->answer->size = rb;
}
net_close(&net);
......@@ -431,31 +450,24 @@ static int nsupdate_process_line(char *lp, int len, void *arg)
int ret = tok_find(lp, cmd_array);
if (ret < 0) {
return KNOT_EOK; /* Syntax error - do nothing. */
return ret; /* Syntax error - do nothing. */
}
const char *cmd = cmd_array[ret];
const char *val = tok_skipspace(lp + TOK_L(cmd));
ret = cmd_handle[ret](val, params);
if (ret != KNOT_EOK) {
DBG("operation '%s' failed (%s)\n",
TOK_S(cmd), knot_strerror(ret));
DBG("operation '%s' failed (%s) on line '%s'\n",
TOK_S(cmd), knot_strerror(ret), lp);
}
return KNOT_EOK;
return ret;
}
static int nsupdate_process(nsupdate_params_t *params, FILE *fp)
{
/* Process lines. */
int ret = tok_process_lines(fp, nsupdate_process_line, params);
/* Free last answer. */
if (params->resp) {
knot_pkt_free(&params->resp);
}
return ret;
return tok_process_lines(fp, nsupdate_process_line, params);
}
int nsupdate_exec(nsupdate_params_t *params)
......@@ -516,23 +528,18 @@ int cmd_add(const char* lp, nsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
scanner_t *rrp = params->rrp;
if (parse_full_rr(rrp, lp) != KNOT_EOK) {
if (parse_full_rr(params->parser, lp) != KNOT_EOK) {
return KNOT_EPARSEFAIL;
}
/* Parsed RR */
DBG("%s: parsed rr cls=%u, ttl=%u, type=%u (rdata len=%u)\n",
__func__, rrp->r_class, rrp->r_ttl,rrp->r_type, rrp->r_data_length);
return pkt_append(params, UP_ADD); /* Append to packet. */
return rr_list_append(params->parser, &params->update_list, &params->mm);
}
int cmd_del(const char* lp, nsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
scanner_t *rrp = params->rrp;
scanner_t *rrp = params->parser;
if (parse_partial_rr(rrp, lp, PARSE_NODEFAULT) != KNOT_EOK) {
return KNOT_EPARSEFAIL;
}
......@@ -552,11 +559,7 @@ int cmd_del(const char* lp, nsupdate_params_t *params)
rrp->r_class = KNOT_CLASS_NONE;
}
/* Parsed RR */
DBG("%s: parsed rr cls=%u, ttl=%u, type=%u (rdata len=%u)\n",
__func__, rrp->r_class, rrp->r_ttl,rrp->r_type, rrp->r_data_length);
return pkt_append(params, UP_DEL); /* Append to packet. */
return rr_list_append(rrp, &params->update_list, &params->mm);
}
int cmd_class(const char* lp, nsupdate_params_t *params)
......@@ -570,7 +573,7 @@ int cmd_class(const char* lp, nsupdate_params_t *params)
return KNOT_EPARSEFAIL;
} else {
params->class_num = cls;
scanner_t *s = params->rrp;
scanner_t *s = params->parser;
s->default_class = params->class_num;
}
......@@ -604,7 +607,7 @@ int cmd_prereq_domain(const char *lp, nsupdate_params_t *params, unsigned type)
UNUSED(type);
DBG("%s: lp='%s'\n", __func__, lp);
scanner_t *s = params->rrp;
scanner_t *s = params->parser;
int ret = parse_partial_rr(s, lp, PARSE_NODEFAULT|PARSE_NAMEONLY);
if (ret != KNOT_EOK) {
return ret;
......@@ -618,7 +621,7 @@ int cmd_prereq_rrset(const char *lp, nsupdate_params_t *params, unsigned type)
UNUSED(type);
DBG("%s: lp='%s'\n", __func__, lp);
scanner_t *rrp = params->rrp;
scanner_t *rrp = params->parser;
if (parse_partial_rr(rrp, lp, 0) != KNOT_EOK) {
return KNOT_EPARSEFAIL;
}
......@@ -629,10 +632,6 @@ int cmd_prereq_rrset(const char *lp, nsupdate_params_t *params, unsigned type)
return KNOT_EPARSEFAIL;
}
/* Parsed RR */
DBG("%s: parsed rr cls=%u, ttl=%u, type=%u (rdata len=%u)\n",
__func__, rrp->r_class, rrp->r_ttl,rrp->r_type, rrp->r_data_length);
return KNOT_EOK;
}
......@@ -642,20 +641,20 @@ int cmd_prereq(const char* lp, nsupdate_params_t *params)
/* Scan prereq specifier ([ny]xrrset|[ny]xdomain) */
int ret = KNOT_EOK;
int bp = tok_find(lp, pq_array);
if (bp < 0) return bp; /* Syntax error. */
int prereq_type = tok_find(lp, pq_array);
if (prereq_type < 0) return prereq_type; /* Syntax error. */
const char *tok = pq_array[bp];
const char *tok = pq_array[prereq_type];
DBG("%s: type %s\n", __func__, TOK_S(tok));
lp = tok_skipspace(lp + TOK_L(tok));
switch(bp) {
switch(prereq_type) {
case PQ_NXDOMAIN:
case PQ_YXDOMAIN:
ret = cmd_prereq_domain(lp, params, bp);
ret = cmd_prereq_domain(lp, params, prereq_type);
break;
case PQ_NXRRSET:
case PQ_YXRRSET:
ret = cmd_prereq_rrset(lp, params, bp);
ret = cmd_prereq_rrset(lp, params, prereq_type);
break;
default:
return KNOT_ERROR;
......@@ -663,16 +662,16 @@ int cmd_prereq(const char* lp, nsupdate_params_t *params)
/* Append to packet. */
if (ret == KNOT_EOK) {
scanner_t *s = params->rrp;
scanner_t *s = params->parser;
s->r_ttl = 0; /* Set TTL = 0 for prereq. */
/* YX{RRSET,DOMAIN} - cls ANY */
if (bp == PQ_YXRRSET || bp == PQ_YXDOMAIN) {
if (prereq_type == PQ_YXRRSET || prereq_type == PQ_YXDOMAIN) {
s->r_class = KNOT_CLASS_ANY;
} else { /* NX{RRSET,DOMAIN} - cls NONE */
s->r_class = KNOT_CLASS_NONE;
}
ret = pkt_append(params, bp);
ret = rr_list_append(s, &params->prereq_list, &params->mm);
}
return ret;
......@@ -683,16 +682,19 @@ int cmd_send(const char* lp, nsupdate_params_t *params)
DBG("%s: lp='%s'\n", __func__, lp);
DBG("sending packet\n");
/* Create wireformat. */
int ret = KNOT_EOK;
knot_pkt_t *pkt = params->pkt;
/* Build query packet. */
int ret = build_query(params);
if (ret != KNOT_EOK) {
ERR("failed to build UPDATE message - %s\n", knot_strerror(ret));
return ret;
}
sign_context_t sign_ctx;
memset(&sign_ctx, '\0', sizeof(sign_context_t));
/* Sign if key specified. */
if (params->key_params.name) {
ret = sign_packet(pkt, &sign_ctx, &params->key_params);
ret = sign_packet(params->query, &sign_ctx, &params->key_params);
if (ret != KNOT_EOK) {
ERR("failed to sign UPDATE message - %s\n",
knot_strerror(ret));
......@@ -704,21 +706,10 @@ int cmd_send(const char* lp, nsupdate_params_t *params)
/* Send/recv message (1 try + N retries). */
int tries = 1 + params->retries;
for (; tries > 0; --tries) {
memset(params->rwire, 0, sizeof(params->rwire));
rb = pkt_sendrecv(params, pkt->wire, pkt->size,
params->rwire, sizeof(params->rwire));
rb = pkt_sendrecv(params);
if (rb > 0) break;
}
/* Clear sent packet. */
knot_pkt_free(&pkt);
params->pkt = NULL;
/* Clear previous response. */
if (params->resp) {
knot_pkt_free(&params->resp);
}
/* Check Send/recv result. */
if (rb <= 0) {
free_sign_context(&sign_ctx);
......@@ -726,12 +717,7 @@ int cmd_send(const char* lp, nsupdate_params_t *params)
}
/* Parse response. */
params->resp = knot_pkt_new(params->rwire, rb, NULL);
if (!params->resp) {
free_sign_context(&sign_ctx);
return KNOT_ENOMEM;
}
ret = knot_pkt_parse(params->resp, KNOT_PF_NO_MERGE);
ret = knot_pkt_parse(params->answer, KNOT_PF_NO_MERGE);
if (ret != KNOT_EOK) {
ERR("failed to parse response, %s\n", knot_strerror(ret));
free_sign_context(&sign_ctx);
......@@ -740,7 +726,7 @@ int cmd_send(const char* lp, nsupdate_params_t *params)
/* Check signature if expected. */
if (params->key_params.name) {
ret = verify_packet(params->resp, &sign_ctx, &params->key_params);
ret = verify_packet(params->answer, &sign_ctx, &params->key_params);
free_sign_context(&sign_ctx);
if (ret != KNOT_EOK) { /* Collect TSIG error. */
fprintf(stderr, "%s: %s\n", "; TSIG error with server",
......@@ -749,17 +735,18 @@ int cmd_send(const char* lp, nsupdate_params_t *params)
}
}
/* Free RRSet lists. */
nsupdate_reset(params);
/* Check return code. */
knot_lookup_table_t *rcode;
int rc = knot_wire_get_rcode(params->resp->wire);
int rc = knot_wire_get_rcode(params->answer->wire);
DBG("%s: received rcode=%d\n", __func__, rc);
rcode = knot_lookup_by_id(knot_rcode_names, rc);
if (rcode && rcode->id > KNOT_RCODE_NOERROR) {
ERR("update failed: %s\n", rcode->name);
}
/*! \todo Should we check TC bit? */
return KNOT_EOK;
}
......@@ -817,9 +804,10 @@ int cmd_show(const char* lp, nsupdate_params_t *params)
DBG("%s: lp='%s'\n", __func__, lp);
/* Show current packet. */
if (!params->pkt) return KNOT_EOK;
printf("Outgoing update query:\n");
print_packet(params->pkt, NULL, -1, false, &params->style);
if (!params->query) return KNOT_EOK;
printf("Update query:\n");
build_query(params);
print_packet(params->query, NULL, -1, false, &params->style);
printf("\n");
return KNOT_EOK;
}
......@@ -829,9 +817,9 @@ int cmd_answer(const char* lp, nsupdate_params_t *params)
DBG("%s: lp='%s'\n", __func__, lp);
/* Show current answer. */
if (!params->resp) return KNOT_EOK;
if (!params->answer) return KNOT_EOK;
printf("\nAnswer:\n");
print_packet(params->resp, NULL, -1, true, &params->style);
print_packet(params->answer, NULL, -1, true, &params->style);
return KNOT_EOK;
}
......
......@@ -26,6 +26,8 @@
#include "utils/common/netio.h"
#include "common/errcode.h"
#include "common/descriptor.h"
#include "common/mempattern.h"
#include "common/mempool.h"
#include "libknot/libknot.h"
#define DEFAULT_RETRIES_NSUPDATE 3
......@@ -53,7 +55,7 @@ static const style_t DEFAULT_STYLE_NSUPDATE = {
};
static void parse_err(const scanner_t *s) {
ERR("failed to parse RR, %s\n", knot_strerror(s->error_code));
ERR("failed to parse RR: %s\n", zscanner_strerror(s->error_code));
}
static int parser_set_default(scanner_t *s, const char *fmt, ...)
......@@ -81,10 +83,13 @@ static int nsupdate_init(nsupdate_params_t *params)
{
memset(params, 0, sizeof(nsupdate_params_t));
params->stop = false;
/* Initialize list. */
/* Initialize lists. */
init_list(&params->qfiles);
init_list(&params->update_list);
init_list(&params->prereq_list);
/* Initialize memory context. */
mm_ctx_mempool(&params->mm, 4096);
/* Default server. */
params->server = srv_info_create(DEFAULT_IPV4_NAME, DEFAULT_DNS_PORT);
......@@ -102,14 +107,18 @@ static int nsupdate_init(nsupdate_params_t *params)
params->zone = strdup(".");
/* Initialize RR parser. */
params->rrp = scanner_create(NULL, ".", params->class_num, 0, NULL,
params->parser = scanner_create(NULL, ".", params->class_num, 0, NULL,
parse_err, NULL);
if (!params->rrp)
if (!params->parser)
return KNOT_ENOMEM;
/* Default style. */
params->style = DEFAULT_STYLE_NSUPDATE;
/* Create query/answer packets. */
params->query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, &params->mm);
params->answer = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, &params->mm);
return KNOT_EOK;
}
......@@ -119,21 +128,48 @@ void nsupdate_clean(nsupdate_params_t *params)
return;
}
/* Clear current query. */
nsupdate_reset(params);
/* Free qfiles. */
WALK_LIST_FREE(params->qfiles);
ptrlist_free(&params->qfiles, &params->mm);
srv_info_free(params->server);
srv_info_free(params->srcif);
free(params->zone);
scanner_free(params->rrp);
knot_pkt_free(&params->pkt);
knot_pkt_free(&params->resp);
scanner_free(params->parser);
knot_pkt_free(&params->query);
knot_pkt_free(&params->answer);
knot_free_key_params(&params->key_params);
/* Clean up the structure. */
mp_delete(params->mm.ctx);
memset(params, 0, sizeof(*params));
}
/*! \brief Free RRSet list. */
static void rr_list_free(list_t *list, mm_ctx_t *mm)
{
assert(list != NULL);
assert(mm != NULL);
ptrnode_t *node = NULL;
WALK_LIST(node, *list) {
knot_rrset_t *rrset = (knot_rrset_t *)node->d;
knot_rrset_free(&rrset);
}
ptrlist_free(list, mm);
}
void nsupdate_reset(nsupdate_params_t *params)
{
/* Free ADD/REMOVE RRSets. */
rr_list_free(&params->update_list, &params->mm);
/* Free PREREQ RRSets. */
rr_list_free(&params->prereq_list, &params->mm);
}
static void nsupdate_help(void)
{
printf("Usage: knsupdate [-d] [-v] [-k keyfile | -y [hmac:]name:key]\n"
......@@ -225,12 +261,7 @@ int nsupdate_parse(nsupdate_params_t *params, int argc, char *argv[])
/* Process non-option parameters. */
for (; optind < argc; ++optind) {
ptrnode_t *n = malloc(sizeof(ptrnode_t));
if (!n) { /* Params will be cleaned on exit. */
return KNOT_ENOMEM;
}
n->d = argv[optind];
add_tail(&params->qfiles, &n->n);
ptrlist_add(&params->qfiles, argv[optind], &params->mm);
}
return ret;
......@@ -238,7 +269,7 @@ int nsupdate_parse(nsupdate_params_t *params, int argc, char *argv[])
int nsupdate_set_ttl(nsupdate_params_t *params, const uint32_t ttl)
{
int ret = parser_set_default(params->rrp, "$TTL %u\n", ttl);
int ret = parser_set_default(params->parser, "$TTL %u\n", ttl);
if (ret == KNOT_EOK) {
params->ttl = ttl;
} else {
......@@ -251,7 +282,7 @@ int nsupdate_set_origin(nsupdate_params_t *params, const char *origin)
{
char *fqdn = get_fqd_name(origin);
int ret = parser_set_default(params->rrp, "$ORIGIN %s\n", fqdn);
int ret = parser_set_default(params->parser, "$ORIGIN %s\n", fqdn);
free(fqdn);
......
......@@ -68,23 +68,26 @@ typedef struct {
/*!< Current zone. */
char *zone;
/*!< RR parser. */
scanner_t *rrp;
scanner_t *parser;
/*!< Current packet. */
knot_pkt_t *pkt;
knot_pkt_t *query;
/*!< Current response. */
knot_pkt_t *resp;
/*!< Buffer for response. */
uint8_t rwire[MAX_PACKET_SIZE];
knot_pkt_t *answer;
/*< Lists of RRSets. */
list_t update_list, prereq_list;
/*!< Key parameters. */
knot_key_params_t key_params;
/*!< Default output settings. */
style_t style;
/*!< Memory context. */
mm_ctx_t mm;
} nsupdate_params_t;
int nsupdate_parse(nsupdate_params_t *params, int argc, char *argv[]);
int nsupdate_set_ttl(nsupdate_params_t *params, const uint32_t ttl);
int nsupdate_set_origin(nsupdate_params_t *params, const char *origin);
void nsupdate_clean(nsupdate_params_t *params);
void nsupdate_reset(nsupdate_params_t *params);
#endif // _NSUPDATE__NSUPDATE_PARAMS_H_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment