Commit 0ff200f1 authored by Jan Včelák's avatar Jan Včelák 🚀
Browse files

Merge branch 'knsupdate_cleanup' into 'master'

parents 1d820a44 6325e8fa
......@@ -105,10 +105,10 @@ class is IN.
Sets \fIvalue\fP as the default TTL (in seconds). If not used, the default value
is 0.
.TP
\fBkey\fP \fIname\fP \fIkey\fP
Specifies TSIG \fIkey\fP named \fIname\fP to authenticate the request. This command
has the same effect as the program option \fB\-y\fP, except that the MAC
algorithm cannot be set.
\fBkey\fP [\fIalg\fP:]\fIname\fP \fIkey\fP
Specifies TSIG \fIkey\fP named \fIname\fP to authenticate the request. An optional
\fIalg\fP algorithm can be specified. This command has the same effect as
the program option \fB\-y\fP\&.
.TP
[\fBprereq\fP] \fBnxdomain\fP \fIname\fP
Adds a prerequisite for a non\-existing record owned by \fIname\fP\&.
......@@ -145,6 +145,9 @@ Displays the last answer from the server.
.TP
\fBdebug\fP
Enable debugging. This command has the same meaning as program option \fB\-d\fP\&.
.TP
\fBquit\fP
Quit the program.
.UNINDENT
.SH NOTES
.sp
......@@ -174,7 +177,7 @@ Bind\-like key format (\fBddns\-confgen\fP output) is not supported.
.SH EXAMPLES
.INDENT 0.0
.IP 1. 3
Send one update of zone example.com to server 192.168.1.1. The update
Send one update of the zone example.com to the server 192.168.1.1. The update
contains two new records:
.INDENT 3.0
.INDENT 3.5
......@@ -182,15 +185,16 @@ contains two new records:
.nf
.ft C
$ knsupdate
server 192.168.1.1
zone example.com.
origin example.com.
ttl 3600
add test1.example.com. 7200 A 192.168.2.2
add test2 TXT "hello"
show
send
answer
> server 192.168.1.1
> zone example.com.
> origin example.com.
> ttl 3600
> add test1.example.com. 7200 A 192.168.2.2
> add test2 TXT "hello"
> show
> send
> answer
> quit
.ft P
.fi
.UNINDENT
......
......@@ -82,10 +82,10 @@ Commands
Sets *value* as the default TTL (in seconds). If not used, the default value
is 0.
**key** *name* *key*
Specifies TSIG *key* named *name* to authenticate the request. This command
has the same effect as the program option **-y**, except that the MAC
algorithm cannot be set.
**key** [*alg*:]\ *name* *key*
Specifies TSIG *key* named *name* to authenticate the request. An optional
*alg* algorithm can be specified. This command has the same effect as
the program option **-y**.
[**prereq**] **nxdomain** *name*
Adds a prerequisite for a non-existing record owned by *name*.
......@@ -123,6 +123,9 @@ Commands
**debug**
Enable debugging. This command has the same meaning as program option **-d**.
**quit**
Quit the program.
Notes
-----
......@@ -147,19 +150,20 @@ Differences with regard to ISC nsupdate:
Examples
--------
1. Send one update of zone example.com to server 192.168.1.1. The update
1. Send one update of the zone example.com to the server 192.168.1.1. The update
contains two new records::
$ knsupdate
server 192.168.1.1
zone example.com.
origin example.com.
ttl 3600
add test1.example.com. 7200 A 192.168.2.2
add test2 TXT "hello"
show
send
answer
> server 192.168.1.1
> zone example.com.
> origin example.com.
> ttl 3600
> add test1.example.com. 7200 A 192.168.2.2
> add test2 TXT "hello"
> show
> send
> answer
> quit
See Also
--------
......
......@@ -49,11 +49,11 @@ ssize_t knot_getline(char **lineptr, size_t *n, FILE *stream)
return -1;
}
*lineptr = tmp;
*n = length + 1;
}
memcpy(*lineptr, buffer, length);
(*lineptr)[length] = '\0';
*n = length;
return length;
#endif
......
......@@ -40,7 +40,7 @@
#define DEFAULT_EDNS_SIZE 4096
#define MAX_PACKET_SIZE 65535
#define SEP_CHARS "\n\t "
#define SEP_CHARS "\t "
/*! \brief Variants of IP protocol. */
typedef enum {
......
......@@ -22,7 +22,6 @@
#include "utils/common/token.h"
#include "utils/common/msg.h"
#include "libknot/libknot.h"
#include "libknot/internal/getline.h"
int tok_scan(const char* lp, const char **tbl, int *lpm)
{
......@@ -110,25 +109,3 @@ const char* tok_skipspace(const char *lp)
while (isspace((unsigned char)(*lp))) ++lp; return lp;
}
int tok_process_lines(FILE *fp, lparse_f cb, void *arg)
{
if (fp == NULL || cb == NULL) {
DBG_NULL;
return KNOT_EINVAL;
}
int ret = KNOT_EOK;
/* Parse lines. */
char *buf = NULL;
size_t buflen = 0;
ssize_t rb = 0;
while ((rb = knot_getline(&buf, &buflen, fp)) != -1) {
ret = cb(buf, rb, arg);
if (ret != KNOT_EOK) break;
}
free(buf);
return ret;
}
......@@ -44,8 +44,6 @@
#define TOK_S(x) ((x)+1)
/*! \brief Len of the token. */
#define TOK_L(x) ((unsigned char)(x)[0])
/*! \brief Function prototype for line parser. */
typedef int(*lparse_f)(char *lp, int len, void *arg);
/*!
* \brief Scan for matching token described by a match table.
......@@ -76,14 +74,4 @@ int tok_find(const char *lp, const char **tbl);
*/
const char* tok_skipspace(const char *lp);
/*!
* \brief Process file by lines.
* \param fp File handle to be processed.
* \param cb Callback function to be called for each line.
* \param arg Pointer to be passed to callback function.
* \return KNOT_EOK if success.
* \return error returned by @cb function
*/
int tok_process_lines(FILE *fp, lparse_f cb, void *arg);
/*! @} */
......@@ -31,6 +31,7 @@
#include "utils/common/sign.h"
#include "utils/common/token.h"
#include "libknot/libknot.h"
#include "libknot/internal/getline.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/mem.h"
#include "libknot/internal/strlcpy.h"
......@@ -50,6 +51,7 @@ int cmd_nxrrset(const char *lp, knsupdate_params_t *params);
int cmd_oldgsstsig(const char* lp, knsupdate_params_t *params);
int cmd_origin(const char* lp, knsupdate_params_t *params);
int cmd_prereq(const char* lp, knsupdate_params_t *params);
int cmd_quit(const char* lp, knsupdate_params_t *params);
int cmd_realm(const char* lp, knsupdate_params_t *params);
int cmd_send(const char* lp, knsupdate_params_t *params);
int cmd_server(const char* lp, knsupdate_params_t *params);
......@@ -72,13 +74,14 @@ const char* cmd_array[] = {
"\x3" "del",
"\x6" "delete",
"\x7" "gsstsig",
"\x3" "key", /* {name} {secret} */
"\x3" "key", /* {[alg:]name} {secret} */
"\x5" "local", /* {address} [port] */
"\x8" "nxdomain",
"\x7" "nxrrset",
"\xa" "oldgsstsig",
"\x6" "origin", /* {name} */
"\x6" "prereq", /* (nx|yx)(domain|rrset) {domain-name} ... */
"\x4" "quit",
"\x5" "realm", /* {[realm_name]} */
"\x4" "send",
"\x6" "server", /* {servername} [port] */
......@@ -106,6 +109,7 @@ cmd_handle_f cmd_handle[] = {
cmd_oldgsstsig,
cmd_origin,
cmd_prereq,
cmd_quit,
cmd_realm,
cmd_send,
cmd_server,
......@@ -130,9 +134,7 @@ enum {
PQ_NXDOMAIN = 0,
PQ_NXRRSET,
PQ_YXDOMAIN,
PQ_YXRRSET,
UP_ADD,
UP_DEL
PQ_YXRRSET
};
/* RR parser flags */
......@@ -467,18 +469,10 @@ static int pkt_sendrecv(knsupdate_params_t *params)
return rb;
}
static int knsupdate_process_line(char *lp, int len, void *arg)
static int process_line(char *lp, void *arg)
{
knsupdate_params_t *params = (knsupdate_params_t *)arg;
/* Remove trailing white space chars. */
for (int i = len - 1; i >= 0; i--) {
if (isspace((unsigned char)lp[i]) == 0) {
break;
}
lp[i] = '\0';
}
/* Check for empty line or comment. */
if (lp[0] == '\0' || lp[0] == ';') {
return KNOT_EOK;
......@@ -500,10 +494,48 @@ static int knsupdate_process_line(char *lp, int len, void *arg)
return ret;
}
static int knsupdate_process(knsupdate_params_t *params, FILE *fp)
static int process_lines(knsupdate_params_t *params, FILE *fp)
{
char *buf = NULL;
size_t buflen = 0;
int ret = KNOT_EOK;
/* Print first program prompt if interactive. */
if (fp == NULL) {
/* Don't mess up stdout. */
fprintf(stderr, "> ");
}
/* Process lines. */
return tok_process_lines(fp, knsupdate_process_line, params);
FILE *input = (fp != NULL) ? fp : stdin;
while (!params->stop && knot_getline(&buf, &buflen, input) != -1) {
/* Remove leading and trailing white space. */
char *line = strstrip(buf);
int call_ret = process_line(line, params);
memset(line, 0, strlen(line));
free(line);
if (call_ret != KNOT_EOK) {
/* Return the first error. */
if (ret == KNOT_EOK) {
ret = call_ret;
}
/* Exit if error and not interactive. */
if (fp != NULL) {
break;
}
}
/* Print program prompt if interactive. */
if (fp == NULL && !params->stop) {
/* Don't mess up stdout. */
fprintf(stderr, "> ");
}
}
memset(buf, 0, buflen);
free(buf);
return ret;
}
int knsupdate_exec(knsupdate_params_t *params)
......@@ -516,7 +548,7 @@ int knsupdate_exec(knsupdate_params_t *params)
/* If no file specified, use stdin. */
if (EMPTY_LIST(params->qfiles)) {
ret = knsupdate_process(params, stdin);
ret = process_lines(params, NULL);
}
/* Read from each specified file. */
......@@ -524,7 +556,7 @@ int knsupdate_exec(knsupdate_params_t *params)
WALK_LIST(n, params->qfiles) {
const char *filename = (const char*)n->d;
if (strcmp(filename, "-") == 0) {
ret = knsupdate_process(params, stdin);
ret = process_lines(params, NULL);
if (ret != KNOT_EOK) {
break;
}
......@@ -538,20 +570,14 @@ int knsupdate_exec(knsupdate_params_t *params)
ret = KNOT_EFILE;
break;
}
ret = knsupdate_process(params, fp);
ret = process_lines(params, fp);
fclose(fp);
if (ret != KNOT_EOK) {
break;
}
}
if (ret != KNOT_EOK) { /* Check for serious error. */
return ret;
} else if (params->reply_error) { /* Check for update error. */
return KNOT_ERROR;
} else {
return KNOT_EOK;
}
return ret;
}
int cmd_update(const char* lp, knsupdate_params_t *params)
......@@ -768,6 +794,15 @@ int cmd_prereq(const char* lp, knsupdate_params_t *params)
return ret;
}
int cmd_quit(const char* lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
params->stop = true;
return KNOT_EOK;
}
int cmd_send(const char* lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
......@@ -846,12 +881,12 @@ int cmd_send(const char* lp, knsupdate_params_t *params)
}
ERR("update failed with '%s'\n", rcode_str);
params->reply_error = true;
ret = KNOT_ERROR;
} else {
DBG("update success\n");
}
return KNOT_EOK;
return ret;
}
int cmd_zone(const char* lp, knsupdate_params_t *params)
......@@ -945,19 +980,24 @@ int cmd_key(const char* lp, knsupdate_params_t *params)
}
int ret = KNOT_EOK;
size_t len = strcspn(lp, SEP_CHARS);
if(kstr[len] == '\0') {
ERR("command 'key' without {secret} specified\n");
ret = KNOT_EINVAL;
} else {
/* Override existing key. */
knot_tsig_key_deinit(&params->tsig_key);
kstr[len] = ':'; /* Replace ' ' with ':' sep */
ret = knot_tsig_key_init_str(&params->tsig_key, kstr);
/* Search for the name secret separation. Allow also alg:name:key form. */
char *sep = strchr(kstr, ' ');
if (sep != NULL) {
/* Replace ' ' with ':'. More spaces are ignored in base64. */
*sep = ':';
}
/* Override existing key. */
knot_tsig_key_deinit(&params->tsig_key);
ret = knot_tsig_key_init_str(&params->tsig_key, kstr);
if (ret != KNOT_EOK) {
ERR("invalid key specification\n");
}
free(kstr);
return ret;
}
......
......@@ -80,8 +80,6 @@ typedef struct {
style_t style;
/*!< Memory context. */
mm_ctx_t mm;
/*!< Indication if an update failed. */
bool reply_error;
} knsupdate_params_t;
int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment