[master] allow arbitrary-size rndc output

4005.	[func]		The buffer used for returning text from rndc
			commands is now dynamically resizable, allowing
			arbitrarily large amounts of text to be sent back
			to the client. (Prior to this change, it was
			possible for the output of "rndc tsig-list" to be
			truncated.) [RT #37731]
This commit is contained in:
Evan Hunt
2014-11-14 15:58:54 -08:00
parent c4abb19716
commit e32d354f75
24 changed files with 844 additions and 308 deletions

View File

@@ -1,3 +1,10 @@
4005. [func] The buffer used for returning text from rndc
commands is now dynamically resizable, allowing
arbitrarily large amounts of text to be sent back
to the client. (Prior to this change, it was
possible for the output of "rndc tsig-list" to be
truncated.) [RT #37731]
4004. [bug] When delegations had AAAA glue but not A, a
reference could be leaked causing an assertion
failure on shutdown. [RT #37796]

View File

@@ -59,7 +59,7 @@ command_compare(const char *text, const char *command) {
* when a control channel message is received.
*/
isc_result_t
ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
isccc_sexpr_t *data;
char *command = NULL;
isc_result_t result;
@@ -132,7 +132,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
#endif
/* Do not flush master files */
ns_server_flushonshutdown(ns_g_server, ISC_FALSE);
ns_os_shutdownmsg(command, text);
ns_os_shutdownmsg(command, *text);
isc_app_shutdown();
result = ISC_R_SUCCESS;
} else if (command_compare(command, NS_COMMAND_STOP)) {
@@ -149,7 +149,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
ns_smf_want_disable = 1;
#endif
ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
ns_os_shutdownmsg(command, text);
ns_os_shutdownmsg(command, *text);
isc_app_shutdown();
result = ISC_R_SUCCESS;
} else if (command_compare(command, NS_COMMAND_DUMPSTATS)) {
@@ -215,6 +215,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
result = ns_server_zonestatus(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_NTA)) {
result = ns_server_nta(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_TESTGEN)) {
result = ns_server_testgen(command, text);
} else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,

View File

@@ -83,7 +83,7 @@ struct controlconnection {
isc_boolean_t ccmsg_valid;
isc_boolean_t sending;
isc_timer_t * timer;
unsigned char buffer[2048];
isc_buffer_t * buffer;
controllistener_t * listener;
isc_uint32_t nonce;
ISC_LINK(controlconnection_t) link;
@@ -166,6 +166,9 @@ static void
maybe_free_connection(controlconnection_t *conn) {
controllistener_t *listener = conn->listener;
if (conn->buffer != NULL)
isc_buffer_free(&conn->buffer);
if (conn->timer != NULL)
isc_timer_detach(&conn->timer);
@@ -326,15 +329,12 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
controlkey_t *key;
isccc_sexpr_t *request = NULL;
isccc_sexpr_t *response = NULL;
isccc_region_t ccregion;
isc_uint32_t algorithm;
isccc_region_t secret;
isc_stdtime_t now;
isc_buffer_t b;
isc_region_t r;
isc_uint32_t len;
isc_buffer_t text;
char textarray[2*1024];
isc_buffer_t *text;
isc_result_t result;
isc_result_t eresult;
isccc_sexpr_t *_ctrl;
@@ -348,6 +348,7 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
listener = conn->listener;
algorithm = DST_ALG_UNKNOWN;
secret.rstart = NULL;
text = NULL;
/* Is the server shutting down? */
if (listener->controls->shuttingdown)
@@ -366,6 +367,8 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
key != NULL;
key = ISC_LIST_NEXT(key, link))
{
isccc_region_t ccregion;
ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
@@ -445,7 +448,9 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
goto cleanup_request;
}
isc_buffer_init(&text, textarray, sizeof(textarray));
result = isc_buffer_allocate(listener->mctx, &text, 2 * 2048);
if (result != ISC_R_SUCCESS)
goto cleanup_request;
/*
* Establish nonce.
@@ -471,12 +476,12 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
}
}
if (isc_buffer_usedlength(&text) > 0) {
if (isc_buffer_usedlength(text) > 0) {
isccc_sexpr_t *data;
data = isccc_alist_lookup(response, "_data");
if (data != NULL) {
char *str = (char *)isc_buffer_base(&text);
char *str = (char *)isc_buffer_base(text);
if (isccc_cc_definestring(data, "text", str) == NULL)
goto cleanup_response;
}
@@ -487,16 +492,26 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
goto cleanup_response;
ccregion.rstart = conn->buffer + 4;
ccregion.rend = conn->buffer + sizeof(conn->buffer);
result = isccc_cc_towire(response, &ccregion, algorithm, &secret);
if (conn->buffer == NULL) {
result = isc_buffer_allocate(listener->mctx,
&conn->buffer, 2 * 2048);
if (result != ISC_R_SUCCESS)
goto cleanup_response;
}
isc_buffer_clear(conn->buffer);
/* Skip the length field (4 bytes) */
isc_buffer_add(conn->buffer, 4);
result = isccc_cc_towire(response, &conn->buffer, algorithm, &secret);
if (result != ISC_R_SUCCESS)
goto cleanup_response;
isc_buffer_init(&b, conn->buffer, 4);
len = sizeof(conn->buffer) - REGION_SIZE(ccregion);
isc_buffer_putuint32(&b, len - 4);
r.base = conn->buffer;
r.length = len;
isc_buffer_init(&b, conn->buffer->base, 4);
isc_buffer_putuint32(&b, conn->buffer->used - 4);
r.base = conn->buffer->base;
r.length = conn->buffer->used;
result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
if (result != ISC_R_SUCCESS)
@@ -506,6 +521,7 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
isccc_sexpr_free(&request);
isccc_sexpr_free(&response);
isc_buffer_free(&text);
return;
cleanup_response:
@@ -514,6 +530,8 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
cleanup_request:
isccc_sexpr_free(&request);
isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
if (text != NULL)
isc_buffer_free(&text);
cleanup:
isc_socket_detach(&conn->sock);
@@ -549,6 +567,7 @@ newconnection(controllistener_t *listener, isc_socket_t *sock) {
isccc_ccmsg_init(listener->mctx, sock, &conn->ccmsg);
conn->ccmsg_valid = ISC_TRUE;
conn->sending = ISC_FALSE;
conn->buffer = NULL;
conn->timer = NULL;
isc_interval_set(&interval, 60, 0);
result = isc_timer_create(ns_g_timermgr, isc_timertype_once,
@@ -565,12 +584,13 @@ newconnection(controllistener_t *listener, isc_socket_t *sock) {
control_recvmessage, conn);
if (result != ISC_R_SUCCESS)
goto cleanup;
isccc_ccmsg_setmaxsize(&conn->ccmsg, 2048);
ISC_LIST_APPEND(listener->connections, conn, link);
return (ISC_R_SUCCESS);
cleanup:
if (conn->buffer != NULL)
isc_buffer_free(&conn->buffer);
isccc_ccmsg_invalidate(&conn->ccmsg);
if (conn->timer != NULL)
isc_timer_detach(&conn->timer);

View File

@@ -68,6 +68,7 @@
#define NS_COMMAND_SIGNING "signing"
#define NS_COMMAND_ZONESTATUS "zonestatus"
#define NS_COMMAND_NTA "nta"
#define NS_COMMAND_TESTGEN "testgen"
isc_result_t
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
@@ -101,6 +102,6 @@ ns_controls_shutdown(ns_controls_t *controls);
*/
isc_result_t
ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text);
ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text);
#endif /* NAMED_CONTROL_H */

View File

@@ -235,7 +235,7 @@ ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush);
*/
isc_result_t
ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t **text);
/*%<
* Act on a "reload" command from the command channel.
*/
@@ -247,20 +247,20 @@ ns_server_reconfigcommand(ns_server_t *server, char *args);
*/
isc_result_t
ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text);
/*%<
* Act on a "notify" command from the command channel.
*/
isc_result_t
ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text);
/*%<
* Act on a "refresh" command from the command channel.
*/
isc_result_t
ns_server_retransfercommand(ns_server_t *server, char *args,
isc_buffer_t *text);
isc_buffer_t **text);
/*%<
* Act on a "retransfer" command from the command channel.
*/
@@ -314,32 +314,32 @@ ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree);
* Report the server's status.
*/
isc_result_t
ns_server_status(ns_server_t *server, isc_buffer_t *text);
ns_server_status(ns_server_t *server, isc_buffer_t **text);
/*%
* Report a list of dynamic and static tsig keys, per view.
*/
isc_result_t
ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text);
ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text);
/*%
* Delete a specific key (with optional view).
*/
isc_result_t
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text);
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t **text);
/*%
* Enable or disable updates for a zone.
*/
isc_result_t
ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
isc_buffer_t *text);
isc_buffer_t **text);
/*%
* Dump zone updates to disk, optionally removing the journal file
*/
isc_result_t
ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Update a zone's DNSKEY set from the key repository. If
@@ -349,7 +349,7 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text);
* take place incrementally.
*/
isc_result_t
ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Dump the current recursive queries.
@@ -367,37 +367,44 @@ ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr);
* Enable or disable dnssec validation.
*/
isc_result_t
ns_server_validation(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Add a zone to a running process
*/
isc_result_t
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Deletes a zone from a running process
*/
isc_result_t
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Lists the status of the signing records for a given zone.
*/
isc_result_t
ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Lists status information for a given zone (e.g., name, type, files,
* load time, expiry, etc).
*/
isc_result_t
ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Adds a Negative Trust Anchor (NTA) for a specified name and
* duration, in a particular view if specified, or in all views.
*/
isc_result_t
ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text);
ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Generates a test sequence that is only for use in system tests. The
* argument is the size of required output in bytes.
*/
isc_result_t
ns_server_testgen(char *args, isc_buffer_t **text);
#endif /* NAMED_SERVER_H */

View File

@@ -155,7 +155,7 @@
#define TCHECK(op) \
do { tresult = (op); \
if (tresult != ISC_R_SUCCESS) { \
isc_buffer_clear(text); \
isc_buffer_clear(*text); \
goto cleanup; \
} \
} while (0)
@@ -418,10 +418,16 @@ static void
newzone_cfgctx_destroy(void **cfgp);
static isc_result_t
putstr(isc_buffer_t *b, const char *str);
putstr(isc_buffer_t **b, const char *str);
static isc_result_t
putnull(isc_buffer_t *b);
putmem(isc_buffer_t **b, const char *str, size_t len);
static isc_result_t
putuint8(isc_buffer_t **b, isc_uint8_t val);
static isc_result_t
putnull(isc_buffer_t **b);
isc_result_t
add_comment(FILE *fp, const char *viewname);
@@ -7138,7 +7144,7 @@ next_token(char **stringp, const char *delim) {
static isc_result_t
zone_from_args(ns_server_t *server, char *args, const char *zonetxt,
dns_zone_t **zonep, const char **zonename,
isc_buffer_t *text, isc_boolean_t skip)
isc_buffer_t **text, isc_boolean_t skip)
{
char *input, *ptr;
char *classtxt;
@@ -7243,7 +7249,7 @@ zone_from_args(ns_server_t *server, char *args, const char *zonetxt,
*/
isc_result_t
ns_server_retransfercommand(ns_server_t *server, char *args,
isc_buffer_t *text)
isc_buffer_t **text)
{
isc_result_t result;
dns_zone_t *zone = NULL;
@@ -7275,7 +7281,7 @@ ns_server_retransfercommand(ns_server_t *server, char *args,
* Act on a "reload" command from the command channel.
*/
isc_result_t
ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result;
dns_zone_t *zone = NULL;
dns_zonetype_t type;
@@ -7316,9 +7322,10 @@ ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
}
}
}
if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
isc_buffer_putmem(text, (const unsigned char *)msg,
strlen(msg) + 1);
if (msg != NULL) {
putstr(text, msg);
putnull(text);
}
return (result);
}
@@ -7337,10 +7344,10 @@ ns_server_reconfigcommand(ns_server_t *server, char *args) {
* Act on a "notify" command from the command channel.
*/
isc_result_t
ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result;
dns_zone_t *zone = NULL;
const unsigned char msg[] = "zone notify queued";
const char msg[] = "zone notify queued";
result = zone_from_args(server, args, NULL, &zone, NULL,
text, ISC_TRUE);
@@ -7351,8 +7358,8 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
dns_zone_notify(zone);
dns_zone_detach(&zone);
if (sizeof(msg) <= isc_buffer_availablelength(text))
isc_buffer_putmem(text, msg, sizeof(msg));
putstr(text, msg);
putnull(text);
return (ISC_R_SUCCESS);
}
@@ -7361,11 +7368,12 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
* Act on a "refresh" command from the command channel.
*/
isc_result_t
ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text)
{
isc_result_t result;
dns_zone_t *zone = NULL, *raw = NULL;
const unsigned char msg1[] = "zone refresh queued";
const unsigned char msg2[] = "not a slave or stub zone";
const char msg1[] = "zone refresh queued";
const char msg2[] = "not a slave or stub zone";
dns_zonetype_t type;
result = zone_from_args(server, args, NULL, &zone, NULL,
@@ -7386,14 +7394,14 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
if (type == dns_zone_slave || type == dns_zone_stub) {
dns_zone_refresh(zone);
dns_zone_detach(&zone);
if (sizeof(msg1) <= isc_buffer_availablelength(text))
isc_buffer_putmem(text, msg1, sizeof(msg1));
putstr(text, msg1);
putnull(text);
return (ISC_R_SUCCESS);
}
dns_zone_detach(&zone);
if (sizeof(msg2) <= isc_buffer_availablelength(text))
isc_buffer_putmem(text, msg2, sizeof(msg2));
putstr(text, msg2);
putnull(text);
return (ISC_R_FAILURE);
}
@@ -7969,7 +7977,7 @@ ns_server_setdebuglevel(ns_server_t *server, char *args) {
}
isc_result_t
ns_server_validation(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text) {
char *ptr, *viewname;
dns_view_t *view;
isc_boolean_t changed = ISC_FALSE;
@@ -8016,29 +8024,16 @@ ns_server_validation(ns_server_t *server, char *args, isc_buffer_t *text) {
view->enablevalidation = enable;
changed = ISC_TRUE;
} else {
unsigned int n;
if (!first) {
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"\n");
if (n >= isc_buffer_availablelength(text)) {
result = ISC_R_NOSPACE;
goto out;
}
isc_buffer_add(text, n);
}
if (!first)
putstr(text, "\n");
putstr(text, "DNSSEC validation is ");
putstr(text, view->enablevalidation
? "enabled" : "disabled");
putstr(text, " (view ");
putstr(text, view->name);
putstr(text, ")");
putnull(text);
first = ISC_FALSE;
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"DNSSEC validation is %s (view %s)",
view->enablevalidation ?
"enabled" : "disabled",
view->name);
if (n >= isc_buffer_availablelength(text)) {
result = ISC_R_NOSPACE;
goto out;
}
isc_buffer_add(text, n);
}
}
@@ -8280,12 +8275,12 @@ ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) {
}
isc_result_t
ns_server_status(ns_server_t *server, isc_buffer_t *text) {
ns_server_status(ns_server_t *server, isc_buffer_t **text) {
isc_result_t result;
unsigned int zonecount, xferrunning, xferdeferred, soaqueries;
unsigned int automatic;
unsigned int n;
const char *ob = "", *cb = "", *alt = "";
char boottime[80], configtime[80];
char boottime[80], configtime[80], line[1024];
if (ns_g_server->version_set) {
ob = " (";
@@ -8310,40 +8305,93 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
isc_time_formathttptimestamp(&ns_g_configtime, configtime,
sizeof(configtime));
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"version: %s%s%s%s <id:%s>\n"
"boot time: %s\n"
"last configured: %s\n"
snprintf(line, sizeof(line), "version: %s%s%s%s <id:%s>\n",
ns_g_version, ob, alt, cb, ns_g_srcid);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "boot time: %s\n", boottime);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "last configured: %s\n", configtime);
CHECK(putstr(text, line));
#ifdef ISC_PLATFORM_USETHREADS
"CPUs found: %u\n"
"worker threads: %u\n"
"UDP listeners per interface: %u\n"
snprintf(line, sizeof(line), "CPUs found: %u\n", ns_g_cpus_detected);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "worker threads: %u\n", ns_g_cpus);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "UDP listeners per interface: %u\n",
ns_g_udpdisp);
CHECK(putstr(text, line));
#endif
"number of zones: %u (%u automatic)\n"
"debug level: %d\n"
"xfers running: %u\n"
"xfers deferred: %u\n"
"soa queries in progress: %u\n"
"query logging is %s\n"
"recursive clients: %d/%d/%d\n"
"tcp clients: %d/%d\n"
"server is up and running",
ns_g_version, ob, alt, cb, ns_g_srcid,
boottime, configtime,
#ifdef ISC_PLATFORM_USETHREADS
ns_g_cpus_detected, ns_g_cpus, ns_g_udpdisp,
#endif
zonecount, automatic, ns_g_debuglevel, xferrunning,
xferdeferred, soaqueries,
server->log_queries ? "ON" : "OFF",
snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n",
zonecount, automatic);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "debug level: %d\n", ns_g_debuglevel);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "soa queries in progress: %u\n",
soaqueries);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "query logging is %s\n",
server->log_queries ? "ON" : "OFF");
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "recursive clients: %d/%d/%d\n",
server->recursionquota.used, server->recursionquota.soft,
server->recursionquota.max,
server->recursionquota.max);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "tcp clients: %d/%d\n",
server->tcpquota.used, server->tcpquota.max);
if (n >= isc_buffer_availablelength(text))
return (ISC_R_NOSPACE);
isc_buffer_add(text, n);
CHECK(putstr(text, line));
CHECK(putstr(text, "server is up and running"));
CHECK(putnull(text));
return (ISC_R_SUCCESS);
cleanup:
return (result);
}
isc_result_t
ns_server_testgen(char *args, isc_buffer_t **text) {
isc_result_t result;
char *ptr;
unsigned long count;
unsigned long i;
const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
/* Skip the command name. */
ptr = next_token(&args, " \t");
if (ptr == NULL)
return (ISC_R_UNEXPECTEDEND);
ptr = next_token(&args, " \t");
if (ptr == NULL)
count = 26;
else
count = strtoul(ptr, NULL, 10);
CHECK(isc_buffer_reserve(text, count));
for (i = 0; i < count; i++)
CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)]));
CHECK(putnull(text));
cleanup:
return (result);
}
static isc_result_t
@@ -8410,13 +8458,12 @@ delete_keynames(dns_tsig_keyring_t *ring, char *target,
}
isc_result_t
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t **text) {
isc_result_t result;
unsigned int n;
dns_view_t *view;
unsigned int foundkeys = 0;
char *target;
char *viewname;
char *target, *viewname;
char fbuf[16];
(void)next_token(&command, " \t"); /* skip command name */
target = next_token(&command, " \t");
@@ -8443,19 +8490,19 @@ ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
}
isc_task_endexclusive(server->task);
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"%d tsig keys deleted.\n", foundkeys);
if (n >= isc_buffer_availablelength(text))
return (ISC_R_NOSPACE);
isc_buffer_add(text, n);
snprintf(fbuf, sizeof(fbuf), "%d", foundkeys);
return (ISC_R_SUCCESS);
CHECK(putstr(text, fbuf));
CHECK(putstr(text, " tsig keys deleted."));
CHECK(putnull(text));
cleanup:
return (result);
}
static isc_result_t
list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
unsigned int *foundkeys)
list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t **text,
unsigned int *foundkeys)
{
char namestr[DNS_NAME_FORMATSIZE];
char creatorstr[DNS_NAME_FORMATSIZE];
@@ -8466,7 +8513,6 @@ list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
dns_name_t *origin;
dns_rbtnode_t *node;
dns_tsigkey_t *tkey;
unsigned int n;
const char *viewname;
if (view != NULL)
@@ -8495,43 +8541,46 @@ list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
tkey = node->data;
if (tkey != NULL) {
(*foundkeys)++;
dns_name_format(&tkey->name, namestr, sizeof(namestr));
if (tkey->generated) {
dns_name_format(tkey->creator, creatorstr,
sizeof(creatorstr));
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n",
viewname, namestr, creatorstr);
if (*foundkeys != 0)
putstr(text, "\n");
CHECK(putstr(text, "view \""));
CHECK(putstr(text, viewname));
CHECK(putstr(text,
"\"; type \"dynamic\"; key \""));
CHECK(putstr(text, namestr));
CHECK(putstr(text, "\"; creator \""));
CHECK(putstr(text, creatorstr));
CHECK(putstr(text, "\";"));
} else {
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"view \"%s\"; type \"static\"; key \"%s\";\n",
viewname, namestr);
if (*foundkeys != 0)
putstr(text, "\n");
CHECK(putstr(text, "view \""));
CHECK(putstr(text, viewname));
CHECK(putstr(text,
"\"; type \"static\"; key \""));
CHECK(putstr(text, namestr));
CHECK(putstr(text, "\";"));
}
if (n >= isc_buffer_availablelength(text)) {
dns_rbtnodechain_invalidate(&chain);
return (ISC_R_NOSPACE);
}
isc_buffer_add(text, n);
(*foundkeys)++;
}
result = dns_rbtnodechain_next(&chain, &foundname, origin);
if (result == ISC_R_NOMORE)
if (result == ISC_R_NOMORE || result == DNS_R_NEWORIGIN)
break;
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
dns_rbtnodechain_invalidate(&chain);
return (result);
}
}
return (ISC_R_SUCCESS);
cleanup:
dns_rbtnodechain_invalidate(&chain);
return (result);
}
isc_result_t
ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text) {
isc_result_t result;
unsigned int n;
dns_view_t *view;
unsigned int foundkeys = 0;
@@ -8559,14 +8608,11 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
}
isc_task_endexclusive(server->task);
if (foundkeys == 0) {
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"no tsig keys found.\n");
if (n >= isc_buffer_availablelength(text))
return (ISC_R_NOSPACE);
isc_buffer_add(text, n);
}
if (foundkeys == 0)
putstr(text, "no tsig keys found.");
if (isc_buffer_usedlength(*text) > 0)
putnull(text);
return (ISC_R_SUCCESS);
}
@@ -8575,7 +8621,7 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
* Act on a "sign" or "loadkeys" command from the command channel.
*/
isc_result_t
ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result;
dns_zone_t *zone = NULL;
dns_zonetype_t type;
@@ -8641,7 +8687,7 @@ synczone(dns_zone_t *zone, void *uap) {
}
isc_result_t
ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result, tresult;
dns_view_t *view;
dns_zone_t *zone = NULL;
@@ -8691,9 +8737,10 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) {
result = synczone(zone, &cleanup);
isc_task_endexclusive(server->task);
if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
isc_buffer_putmem(text, (const unsigned char *)msg,
strlen(msg) + 1);
if (msg != NULL) {
putstr(text, msg);
putnull(text);
}
view = dns_zone_getview(zone);
if (strcmp(view->name, "_default") == 0 ||
@@ -8724,7 +8771,7 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) {
*/
isc_result_t
ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
isc_buffer_t *text)
isc_buffer_t **text)
{
isc_result_t result, tresult;
dns_zone_t *zone = NULL, *raw = NULL;
@@ -8815,9 +8862,10 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
}
isc_task_endexclusive(server->task);
if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
isc_buffer_putmem(text, (const unsigned char *)msg,
strlen(msg) + 1);
if (msg != NULL) {
putstr(text, msg);
putnull(text);
}
view = dns_zone_getview(zone);
if (strcmp(view->name, "_default") == 0 ||
@@ -8849,16 +8897,8 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
* is managed by smf and is also running chroot.
*/
isc_result_t
ns_smf_add_message(isc_buffer_t *text) {
unsigned int n;
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"use svcadm(1M) to manage named");
if (n >= isc_buffer_availablelength(text))
return (ISC_R_NOSPACE);
isc_buffer_add(text, n);
return (ISC_R_SUCCESS);
ns_smf_add_message(isc_buffer_t **text) {
return (putstr(text, "use svcadm(1M) to manage named"));
}
#endif /* HAVE_LIBSCF */
@@ -8883,7 +8923,7 @@ add_comment(FILE *fp, const char *viewname) {
* Act on an "addzone" command from the command channel.
*/
isc_result_t
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result, tresult;
isc_buffer_t argbuf;
size_t arglen;
@@ -9042,7 +9082,7 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t *text) {
/* Emit the zone name, quoted and escaped */
isc_buffer_init(&buf, namebuf, sizeof(namebuf));
CHECK(dns_name_totext(dnsname, ISC_TRUE, &buf));
putnull(&buf);
isc_buffer_putuint8(&buf, 0);
CHECK(isc_stdio_write("zone \"", 6, 1, fp, NULL));
CHECK(isc_stdio_write(namebuf, strlen(namebuf), 1, fp, NULL));
CHECK(isc_stdio_write("\" ", 2, 1, fp, NULL));
@@ -9081,7 +9121,7 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t *text) {
result = ISC_R_SUCCESS;
cleanup:
if (isc_buffer_usedlength(text) > 0)
if (isc_buffer_usedlength(*text) > 0)
putnull(text);
if (fp != NULL)
isc_stdio_close(fp);
@@ -9099,18 +9139,16 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t *text) {
}
static isc_boolean_t
inuse(const char* file, isc_boolean_t first, isc_buffer_t *text) {
inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) {
#define INUSEMSG "The following files were in use and may now be removed:\n"
if (file != NULL && isc_file_exists(file) &&
isc_buffer_availablelength(text) >
strlen(file) + (first ? sizeof(INUSEMSG) : sizeof("\n")))
{
if (file != NULL && isc_file_exists(file)) {
if (first)
(void) putstr(text, INUSEMSG);
else
(void) putstr(text, "\n");
(void) putstr(text, file);
putnull(text);
return (ISC_FALSE);
}
return (first);
@@ -9120,7 +9158,7 @@ inuse(const char* file, isc_boolean_t first, isc_buffer_t *text) {
* Act on a "delzone" command from the command channel.
*/
isc_result_t
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result;
dns_zone_t *zone = NULL;
dns_zone_t *raw = NULL;
@@ -9346,7 +9384,7 @@ ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t *text) {
result = ISC_R_SUCCESS;
cleanup:
if (isc_buffer_usedlength(text) > 0)
if (isc_buffer_usedlength(*text) > 0)
putnull(text);
if (exclusive)
isc_task_endexclusive(server->task);
@@ -9429,7 +9467,7 @@ generate_salt(unsigned char *salt, size_t saltlen) {
}
isc_result_t
ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result = ISC_R_SUCCESS;
dns_zone_t *zone = NULL;
dns_name_t *origin;
@@ -9576,21 +9614,13 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) {
isc_buffer_init(&buf, output, sizeof(output));
CHECK(dns_private_totext(&priv, &buf));
if (!first)
putstr(text, "\n");
CHECK(putstr(text, "\n"));
CHECK(putstr(text, output));
first = ISC_FALSE;
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"%s", output);
if (n >= isc_buffer_availablelength(text))
CHECK(ISC_R_NOSPACE);
isc_buffer_add(text, (unsigned int)n);
}
if (!first)
putnull(text);
CHECK(putnull(text));
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
@@ -9612,30 +9642,41 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) {
}
static isc_result_t
putstr(isc_buffer_t *b, const char *str) {
unsigned int l = strlen(str);
putmem(isc_buffer_t **b, const char *str, size_t len) {
isc_result_t result;
/*
* Use >= to leave space for NUL termination.
*/
if (l >= isc_buffer_availablelength(b))
result = isc_buffer_reserve(b, len);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
isc_buffer_putmem(b, (const unsigned char *)str, l);
isc_buffer_putmem(*b, (const unsigned char *)str, len);
return (ISC_R_SUCCESS);
}
static inline isc_result_t
putstr(isc_buffer_t **b, const char *str) {
return (putmem(b, str, strlen(str)));
}
static isc_result_t
putnull(isc_buffer_t *b) {
if (isc_buffer_availablelength(b) == 0)
putuint8(isc_buffer_t **b, isc_uint8_t val) {
isc_result_t result;
result = isc_buffer_reserve(b, 1);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
isc_buffer_putuint8(b, 0);
isc_buffer_putuint8(*b, val);
return (ISC_R_SUCCESS);
}
static inline isc_result_t
putnull(isc_buffer_t **b) {
return (putuint8(b, 0));
}
isc_result_t
ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result = ISC_R_SUCCESS;
dns_zone_t *zone = NULL, *raw = NULL;
const char *type, *file, *zonename = NULL;
@@ -9907,7 +9948,7 @@ argcheck(char *cmd, const char *full) {
}
isc_result_t
ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) {
dns_view_t *view;
dns_ntatable_t *ntatable = NULL;
isc_result_t result = ISC_R_SUCCESS;
@@ -10083,10 +10124,7 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
nametext, view->name);
}
if (isc_buffer_availablelength(text) == 0)
return (ISC_R_NOSPACE);
isc_buffer_putuint8(text, 0);
CHECK(putnull(text));
}
cleanup:

View File

@@ -73,7 +73,7 @@ static int nserveraddrs;
static int currentaddr = 0;
static unsigned int remoteport = 0;
static isc_socketmgr_t *socketmgr = NULL;
static unsigned char databuf[2048];
static isc_buffer_t *databuf;
static isccc_ccmsg_t ccmsg;
static isc_uint32_t algorithm;
static isccc_region_t secret;
@@ -306,8 +306,6 @@ rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
isccc_time_t now;
isc_region_t r;
isccc_sexpr_t *data;
isccc_region_t message;
isc_uint32_t len;
isc_buffer_t b;
recvs--;
@@ -354,15 +352,19 @@ rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
fatal("out of memory");
}
message.rstart = databuf + 4;
message.rend = databuf + sizeof(databuf);
isc_buffer_clear(databuf);
/* Skip the length field (4 bytes) */
isc_buffer_add(databuf, 4);
DO("render message",
isccc_cc_towire(request, &message, algorithm, &secret));
len = sizeof(databuf) - REGION_SIZE(message);
isc_buffer_init(&b, databuf, 4);
isc_buffer_putuint32(&b, len - 4);
r.length = len;
r.base = databuf;
isccc_cc_towire(request, &databuf, algorithm, &secret));
isc_buffer_init(&b, databuf->base, 4);
isc_buffer_putuint32(&b, databuf->used - 4);
r.base = databuf->base;
r.length = databuf->used;
isccc_ccmsg_cancelread(&ccmsg);
DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
@@ -384,9 +386,7 @@ rndc_connected(isc_task_t *task, isc_event_t *event) {
isccc_sexpr_t *request = NULL;
isccc_sexpr_t *data;
isccc_time_t now;
isccc_region_t message;
isc_region_t r;
isc_uint32_t len;
isc_buffer_t b;
isc_result_t result;
@@ -417,15 +417,19 @@ rndc_connected(isc_task_t *task, isc_event_t *event) {
fatal("_data section missing");
if (isccc_cc_definestring(data, "type", "null") == NULL)
fatal("out of memory");
message.rstart = databuf + 4;
message.rend = databuf + sizeof(databuf);
isc_buffer_clear(databuf);
/* Skip the length field (4 bytes) */
isc_buffer_add(databuf, 4);
DO("render message",
isccc_cc_towire(request, &message, algorithm, &secret));
len = sizeof(databuf) - REGION_SIZE(message);
isc_buffer_init(&b, databuf, 4);
isc_buffer_putuint32(&b, len - 4);
r.length = len;
r.base = databuf;
isccc_cc_towire(request, &databuf, algorithm, &secret));
isc_buffer_init(&b, databuf->base, 4);
isc_buffer_putuint32(&b, databuf->used - 4);
r.base = databuf->base;
r.length = databuf->used;
isccc_ccmsg_init(mctx, sock, &ccmsg);
isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
@@ -875,6 +879,9 @@ main(int argc, char **argv) {
command = *argv;
DO("allocate data buffer",
isc_buffer_allocate(mctx, &databuf, 2048));
/*
* Convert argc/argv into a space-delimited command string
* similar to what the user might enter in interactive mode
@@ -931,6 +938,8 @@ main(int argc, char **argv) {
dns_name_destroy();
isc_buffer_free(&databuf);
if (show_final_mem)
isc_mem_stats(mctx, stderr);

View File

@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@
@BIND9_MAKE_INCLUDES@
SUBDIRS = builtin dlzexternal filter-aaaa geoip lwresd resolver rpz \
SUBDIRS = builtin dlzexternal filter-aaaa geoip lwresd resolver rndc rpz \
rsabigexponent tkey tsiggss
TARGETS =

View File

@@ -0,0 +1,55 @@
# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id$
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_VERSION@
@BIND9_MAKE_INCLUDES@
CINCLUDES =
CDEFINES =
CWARNINGS =
DNSLIBS =
ISCLIBS = .
DNSDEPLIBS =
ISCDEPLIBS =
DEPLIBS =
LIBS = @LIBS@
TARGETS = gencheck@EXEEXT@
GENCHECKOBJS = gencheck.@O@
SRCS = gencheck.c
@BIND9_MAKE_RULES@
all: gencheck@EXEEXT@
gencheck@EXEEXT@: ${GENCHECKOBJS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${GENCHECKOBJS} ${LIBS}
clean distclean::
rm -f ${TARGETS}

View File

@@ -22,3 +22,4 @@ rm -f ns*/named.memstats
rm -f ns*/named.run
rm -f ns4/*.conf
rm -f rndc.status
rm -f rndc.output

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define USAGE "usage: gencheck <filename>\n"
static int
check(const char *buf, ssize_t count, size_t *start) {
const char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
ssize_t i;
for (i = 0; i < count; i++, *start = (*start + 1) % (sizeof(chars) - 1)) {
/* Just ignore the trailing newline */
if (buf[i] == '\n')
continue;
if (buf[i] != chars[*start])
return 0;
}
return 1;
}
int
main(int argc, char **argv)
{
int ret;
int fd;
ssize_t count;
char buf[1024];
size_t start;
size_t length;
ret = EXIT_FAILURE;
fd = -1;
length = 0;
if (argc != 2) {
fputs(USAGE, stderr);
goto out;
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
goto out;
start = 0;
while ((count = read(fd, buf, sizeof(buf))) != 0) {
if (count < 0)
goto out;
if (!check(buf, count, &start))
goto out;
length += count;
}
ret = EXIT_SUCCESS;
out:
printf("%zu\n", length);
if (fd != -1)
close(fd);
return (ret);
}

View File

@@ -384,5 +384,24 @@ $RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 2h nta1.example 2>&1 | grep "
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 1d nta2.example 2>&1 | grep "Negative trust anchor added" > /dev/null || ret=1
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 1w nta3.example 2>&1 | grep "Negative trust anchor added" > /dev/null || ret=1
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 8d nta4.example 2>&1 | grep "NTA lifetime cannot exceed one week" > /dev/null || ret=1
echo "I:exit status: $status"
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
for i in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288
do
echo "I:testing rndc buffer size limits (size=${i})"
ret=0
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf testgen ${i} 2>&1 > rndc.output || ret=1
actual_size=`./gencheck rndc.output`
if [ "$?" = "0" ]; then
expected_size=`expr $i + 1`
if [ $actual_size != $expected_size ]; then ret=1; fi
else
ret=1
fi
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
done
exit $status

3
configure vendored
View File

@@ -21724,7 +21724,7 @@ ac_config_commands="$ac_config_commands chmod"
# elsewhere if there's a good reason for doing so.
#
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/delv/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/pkcs11/Makefile bin/tests/pkcs11/benchmarks/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/builtin/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile bin/tests/system/resolver/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/sit/prereq.sh bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/scripts/check-secure-delegation.pl contrib/scripts/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl doc/xsl/isc-notes-latex.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/include/pk11/Makefile lib/isc/include/pkcs11/Makefile lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/tests/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile lib/samples/Makefile lib/samples/Makefile-postinstall unit/Makefile unit/unittest.sh"
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/delv/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/pkcs11/Makefile bin/tests/pkcs11/benchmarks/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/builtin/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile bin/tests/system/resolver/Makefile bin/tests/system/rndc/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/sit/prereq.sh bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/scripts/check-secure-delegation.pl contrib/scripts/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl doc/xsl/isc-notes-latex.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/include/pk11/Makefile lib/isc/include/pkcs11/Makefile lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/tests/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile lib/samples/Makefile lib/samples/Makefile-postinstall unit/Makefile unit/unittest.sh"
#
@@ -22777,6 +22777,7 @@ do
"bin/tests/system/inline/checkdsa.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/inline/checkdsa.sh" ;;
"bin/tests/system/lwresd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/lwresd/Makefile" ;;
"bin/tests/system/resolver/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/resolver/Makefile" ;;
"bin/tests/system/rndc/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rndc/Makefile" ;;
"bin/tests/system/rpz/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rpz/Makefile" ;;
"bin/tests/system/rsabigexponent/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rsabigexponent/Makefile" ;;
"bin/tests/system/sit/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/sit/prereq.sh" ;;

View File

@@ -4535,6 +4535,7 @@ AC_CONFIG_FILES([
bin/tests/system/inline/checkdsa.sh
bin/tests/system/lwresd/Makefile
bin/tests/system/resolver/Makefile
bin/tests/system/rndc/Makefile
bin/tests/system/rpz/Makefile
bin/tests/system/rsabigexponent/Makefile
bin/tests/system/sit/prereq.sh

View File

@@ -275,6 +275,14 @@
name format is found to exist, it will continue to be used.
</para>
</listitem>
<listitem>
<para>
"rndc" can now return text output of arbitrary size to
the caller. (Prior to this, certain commands such as
"rndc tsig-list" and "rndc zonestatus" could return
truncated output.)
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="relnotes_bugs">

View File

@@ -199,9 +199,9 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
*/
isc_result_t
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf);
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf);
/*%<
* Dump the NTA table to buffer 'buf'
* Dump the NTA table to buffer at 'buf'
*/
isc_result_t

View File

@@ -501,7 +501,7 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
}
isc_result_t
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf) {
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
isc_result_t result;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
@@ -539,11 +539,12 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf) {
n->expiry < now ? "expired" : "expiry",
tbuf);
first = ISC_FALSE;
if (strlen(obuf) >= isc_buffer_availablelength(buf)) {
result = isc_buffer_reserve(buf, strlen(obuf));
if (result != ISC_R_SUCCESS) {
result = ISC_R_NOSPACE;
goto cleanup;
} else
isc_buffer_putstr(buf, obuf);
}
isc_buffer_putstr(*buf, obuf);
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
@@ -553,8 +554,9 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf) {
}
}
if (isc_buffer_availablelength(buf) != 0)
isc_buffer_putuint8(buf, 0);
isc_buffer_reserve(buf, 1);
if (isc_buffer_availablelength(*buf) != 0)
isc_buffer_putuint8(*buf, 0);
cleanup:
dns_rbtnodechain_invalidate(&chain);

View File

@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp $ */
/*! \file */
#include <config.h>
@@ -467,6 +465,63 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
return (ISC_R_SUCCESS);
}
isc_result_t
isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length) {
isc_buffer_t *dbuf;
REQUIRE(dynbuffer != NULL);
REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
if ((*dynbuffer)->length > length)
return (ISC_R_NOSPACE);
/*
* XXXMUKS: This is far more expensive than plain realloc() as
* it doesn't remap pages, but does ordinary copy. So is
* isc_mem_reallocate(), which has additional issues.
*/
dbuf = isc_mem_get((*dynbuffer)->mctx, length + sizeof(isc_buffer_t));
if (dbuf == NULL)
return (ISC_R_NOMEMORY);
memmove(dbuf, *dynbuffer, (*dynbuffer)->length + sizeof(isc_buffer_t));
isc_mem_put(dbuf->mctx, *dynbuffer,
(*dynbuffer)->length + sizeof(isc_buffer_t));
dbuf->base = ((unsigned char *)dbuf) + sizeof(isc_buffer_t);
dbuf->length = length;
INSIST(ISC_BUFFER_VALID(dbuf));
*dynbuffer = dbuf;
return (ISC_R_SUCCESS);
}
isc_result_t
isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size) {
isc_uint64_t len;
REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
len = (*dynbuffer)->length;
if ((len - (*dynbuffer)->used) > size)
return (ISC_R_SUCCESS);
/* Round to nearest buffer size increment */
len += size;
len = (len + ISC_BUFFER_INCR - 1 - ((len - 1) % ISC_BUFFER_INCR));
/* Cap at UINT_MAX */
if (len > UINT_MAX) {
len = UINT_MAX;
if ((len - (*dynbuffer)->used) < size)
return (ISC_R_NOMEMORY);
}
return (isc_buffer_reallocate(dynbuffer, (unsigned int) len));
}
void
isc_buffer_free(isc_buffer_t **dynbuffer) {
unsigned int real_length;

View File

@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: buffer.h,v 1.55 2010/12/20 23:47:21 tbox Exp $ */
#ifndef ISC_BUFFER_H
#define ISC_BUFFER_H 1
@@ -127,6 +125,13 @@ ISC_LANG_BEGINDECLS
#define ISC_BUFFER_VALID(b) ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC)
/*@}*/
/*!
* Size granularity for dynamically resizeable buffers; when reserving
* space in a buffer, we round the allocated buffer length up to the
* nearest * multiple of this value.
*/
#define ISC_BUFFER_INCR 2048
/*
* The following macros MUST be used only on valid buffers. It is the
* caller's responsibility to ensure this by using the ISC_BUFFER_VALID
@@ -205,6 +210,50 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
*\li Changing the buffer's length field is not permitted.
*/
isc_result_t
isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length);
/*!<
* \brief Reallocate the buffer to be "length" bytes long. The buffer
* pointer may move when you call this function.
*
* Requires:
*\li "dynbuffer" is not NULL.
*
*\li "*dynbuffer" is a valid dynamic buffer.
*
*\li 'length' > current length of buffer.
*
* Returns:
*\li ISC_R_SUCCESS - success
*\li ISC_R_NOMEMORY - no memory available
*
* Ensures:
*\li "*dynbuffer" will be valid on return and will contain all the
* original data. However, the buffer pointer may be moved during
* reallocation.
*/
isc_result_t
isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size);
/*!<
* \brief Make "size" bytes of space available in the buffer. The buffer
* pointer may move when you call this function.
*
* Requires:
*\li "dynbuffer" is not NULL.
*
*\li "*dynbuffer" is a valid dynamic buffer.
*
* Returns:
*\li ISC_R_SUCCESS - success
*\li ISC_R_NOMEMORY - no memory available
*
* Ensures:
*\li "*dynbuffer" will be valid on return and will contain all the
* original data. However, the buffer pointer may be moved during
* reallocation.
*/
void
isc_buffer_free(isc_buffer_t **dynbuffer);
/*!<

View File

@@ -40,7 +40,7 @@ SRCS = isctest.c taskpool_test.c socket_test.c hash_test.c \
sockaddr_test.c symtab_test.c task_test.c queue_test.c \
parse_test.c pool_test.c print_test.c regex_test.c \
socket_test.c safe_test.c time_test.c aes_test.c \
file_test.c
file_test.c buffer_test.c
SUBDIRS =
TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
@@ -49,7 +49,7 @@ TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
queue_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \
print_test@EXEEXT@ regex_test@EXEEXT@ socket_test@EXEEXT@ \
safe_test@EXEEXT@ time_test@EXEEXT@ aes_test@EXEEXT@ \
file_test@EXEEXT@
file_test@EXEEXT@ buffer_test@EXEEXT@
@BIND9_MAKE_RULES@
@@ -125,6 +125,10 @@ file_test@EXEEXT@: file_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
file_test.@O@ ${ISCLIBS} ${LIBS}
buffer_test@EXEEXT@: buffer_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
buffer_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS}
unit::
sh ${top_srcdir}/unit/unittest.sh

144
lib/isc/tests/buffer_test.c Normal file
View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <atf-c.h>
#include "isctest.h"
#include <isc/buffer.h>
#include <isc/result.h>
ATF_TC(isc_buffer_reserve);
ATF_TC_HEAD(isc_buffer_reserve, tc) {
atf_tc_set_md_var(tc, "descr", "reserve space in dynamic buffers");
}
ATF_TC_BODY(isc_buffer_reserve, tc) {
isc_result_t result;
isc_buffer_t *b;
result = isc_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
b = NULL;
result = isc_buffer_allocate(mctx, &b, 1024);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK_EQ(b->length, 1024);
/*
* 1024 bytes should already be available, so this call does
* nothing.
*/
result = isc_buffer_reserve(&b, 1024);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 1024);
/*
* This call should grow it to 2048 bytes as only 1024 bytes are
* available in the buffer.
*/
result = isc_buffer_reserve(&b, 1025);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 2048);
/*
* 2048 bytes should already be available, so this call does
* nothing.
*/
result = isc_buffer_reserve(&b, 2048);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 2048);
/*
* This call should grow it to 4096 bytes as only 2048 bytes are
* available in the buffer.
*/
result = isc_buffer_reserve(&b, 2049);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 4096);
/* Consume some of the buffer so we can run the next test. */
isc_buffer_add(b, 4096);
/*
* This call should fail and leave buffer untouched.
*/
result = isc_buffer_reserve(&b, UINT_MAX);
ATF_CHECK_EQ(result, ISC_R_NOMEMORY);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 4096);
isc_buffer_free(&b);
isc_test_end();
}
ATF_TC(isc_buffer_reallocate);
ATF_TC_HEAD(isc_buffer_reallocate, tc) {
atf_tc_set_md_var(tc, "descr", "reallocate dynamic buffers");
}
ATF_TC_BODY(isc_buffer_reallocate, tc) {
isc_result_t result;
isc_buffer_t *b;
result = isc_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
b = NULL;
result = isc_buffer_allocate(mctx, &b, 1024);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK_EQ(b->length, 1024);
result = isc_buffer_reallocate(&b, 512);
ATF_CHECK_EQ(result, ISC_R_NOSPACE);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 1024);
result = isc_buffer_reallocate(&b, 1536);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(ISC_BUFFER_VALID(b));
ATF_CHECK_EQ(b->length, 1536);
isc_buffer_free(&b);
isc_test_end();
}
/*
* Main
*/
ATF_TP_ADD_TCS(tp) {
ATF_TP_ADD_TC(tp, isc_buffer_reserve);
ATF_TP_ADD_TC(tp, isc_buffer_reallocate);
return (atf_no_error());
}

View File

@@ -159,6 +159,8 @@ isc_buffer_getuint16
isc_buffer_getuint32
isc_buffer_getuint8
isc_buffer_reinit
isc_buffer_reallocate
isc_buffer_reserve
isc_bufferlist_availablecount
isc_bufferlist_usedcount
isc_commandline_parse

View File

@@ -108,84 +108,102 @@ static unsigned char auth_hsha[] = {
#define HSHA_LENGTH 88
static isc_result_t
table_towire(isccc_sexpr_t *alist, isccc_region_t *target);
table_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer);
static isc_result_t
list_towire(isccc_sexpr_t *alist, isccc_region_t *target);
list_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer);
static isc_result_t
value_towire(isccc_sexpr_t *elt, isccc_region_t *target)
value_towire(isccc_sexpr_t *elt, isc_buffer_t **buffer)
{
unsigned int len;
unsigned char *lenp;
isccc_region_t *vr;
isc_result_t result;
if (isccc_sexpr_binaryp(elt)) {
vr = isccc_sexpr_tobinary(elt);
len = REGION_SIZE(*vr);
if (REGION_SIZE(*target) < 1 + 4 + len)
result = isc_buffer_reserve(buffer, 1 + 4);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart);
PUT32(len, target->rstart);
if (REGION_SIZE(*target) < len)
isc_buffer_putuint8(*buffer, ISCCC_CCMSGTYPE_BINARYDATA);
isc_buffer_putuint32(*buffer, len);
result = isc_buffer_reserve(buffer, len);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
PUT_MEM(vr->rstart, len, target->rstart);
isc_buffer_putmem(*buffer, vr->rstart, len);
} else if (isccc_alist_alistp(elt)) {
if (REGION_SIZE(*target) < 1 + 4)
unsigned int used;
isc_buffer_t b;
result = isc_buffer_reserve(buffer, 1 + 4);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart);
isc_buffer_putuint8(*buffer, ISCCC_CCMSGTYPE_TABLE);
/*
* Emit a placeholder length.
*/
lenp = target->rstart;
PUT32(0, target->rstart);
used = (*buffer)->used;
isc_buffer_putuint32(*buffer, 0);
/*
* Emit the table.
*/
result = table_towire(elt, target);
result = table_towire(elt, buffer);
if (result != ISC_R_SUCCESS)
return (result);
len = (unsigned int)(target->rstart - lenp);
len = (*buffer)->used - used;
/*
* 'len' is 4 bytes too big, since it counts
* the placeholder length too. Adjust and
* the placeholder length too. Adjust and
* emit.
*/
INSIST(len >= 4U);
len -= 4;
PUT32(len, lenp);
isc_buffer_init(&b, (unsigned char *) (*buffer)->base + used, 4);
isc_buffer_putuint32(&b, len);
} else if (isccc_sexpr_listp(elt)) {
if (REGION_SIZE(*target) < 1 + 4)
unsigned int used;
isc_buffer_t b;
result = isc_buffer_reserve(buffer, 1 + 4);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart);
isc_buffer_putuint8(*buffer, ISCCC_CCMSGTYPE_LIST);
/*
* Emit a placeholder length and count.
* Emit a placeholder length.
*/
lenp = target->rstart;
PUT32(0, target->rstart);
used = (*buffer)->used;
isc_buffer_putuint32(*buffer, 0);
/*
* Emit the list.
*/
result = list_towire(elt, target);
result = list_towire(elt, buffer);
if (result != ISC_R_SUCCESS)
return (result);
len = (unsigned int)(target->rstart - lenp);
len = (*buffer)->used - used;
/*
* 'len' is 4 bytes too big, since it counts
* the placeholder length. Adjust and emit.
* the placeholder length too. Adjust and
* emit.
*/
INSIST(len >= 4U);
len -= 4;
PUT32(len, lenp);
isc_buffer_init(&b, (unsigned char *) (*buffer)->base + used, 4);
isc_buffer_putuint32(&b, len);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
table_towire(isccc_sexpr_t *alist, isccc_region_t *target)
{
table_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer) {
isccc_sexpr_t *kv, *elt, *k, *v;
char *ks;
isc_result_t result;
@@ -203,14 +221,15 @@ table_towire(isccc_sexpr_t *alist, isccc_region_t *target)
/*
* Emit the key name.
*/
if (REGION_SIZE(*target) < 1 + len)
result = isc_buffer_reserve(buffer, 1 + len);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
PUT8(len, target->rstart);
PUT_MEM(ks, len, target->rstart);
isc_buffer_putuint8(*buffer, len);
isc_buffer_putmem(*buffer, (const unsigned char *) ks, len);
/*
* Emit the value.
*/
result = value_towire(v, target);
result = value_towire(v, buffer);
if (result != ISC_R_SUCCESS)
return (result);
}
@@ -219,12 +238,11 @@ table_towire(isccc_sexpr_t *alist, isccc_region_t *target)
}
static isc_result_t
list_towire(isccc_sexpr_t *list, isccc_region_t *target)
{
list_towire(isccc_sexpr_t *list, isc_buffer_t **buffer) {
isc_result_t result;
while (list != NULL) {
result = value_towire(ISCCC_SEXPR_CAR(list), target);
result = value_towire(ISCCC_SEXPR_CAR(list), buffer);
if (result != ISC_R_SUCCESS)
return (result);
list = ISCCC_SEXPR_CDR(list);
@@ -324,24 +342,24 @@ sign(unsigned char *data, unsigned int length, unsigned char *hmac,
}
isc_result_t
isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
isccc_cc_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer,
isc_uint32_t algorithm, isccc_region_t *secret)
{
unsigned char *hmac_rstart, *signed_rstart;
unsigned int hmac_size, signed_size;
isc_result_t result;
if (algorithm == ISCCC_ALG_HMACMD5) {
if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5))
return (ISC_R_NOSPACE);
} else {
if (REGION_SIZE(*target) < 4 + sizeof(auth_hsha))
return (ISC_R_NOSPACE);
}
result = isc_buffer_reserve(buffer,
4 + ((algorithm == ISCCC_ALG_HMACMD5) ?
sizeof(auth_hmd5) :
sizeof(auth_hsha)));
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
/*
* Emit protocol version.
*/
PUT32(1, target->rstart);
isc_buffer_putuint32(*buffer, 1);
if (secret != NULL) {
/*
* Emit _auth section with zeroed HMAC signature.
@@ -349,19 +367,21 @@ isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
* we know what it is.
*/
if (algorithm == ISCCC_ALG_HMACMD5) {
hmac_rstart = target->rstart + HMD5_OFFSET;
PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart);
hmac_size = (*buffer)->used + HMD5_OFFSET;
isc_buffer_putmem(*buffer,
auth_hmd5, sizeof(auth_hmd5));
} else {
unsigned char *hmac_alg;
hmac_rstart = target->rstart + HSHA_OFFSET;
hmac_alg = hmac_rstart - 1;
PUT_MEM(auth_hsha, sizeof(auth_hsha), target->rstart);
PUT8(algorithm, hmac_alg);
hmac_size = (*buffer)->used + HSHA_OFFSET;
hmac_alg = (unsigned char *) isc_buffer_used(*buffer) + HSHA_OFFSET - 1;
isc_buffer_putmem(*buffer,
auth_hsha, sizeof(auth_hsha));
*hmac_alg = algorithm;
}
} else
hmac_rstart = NULL;
signed_rstart = target->rstart;
hmac_size = 0;
signed_size = (*buffer)->used;
/*
* Delete any existing _auth section so that we don't try
* to encode it.
@@ -370,13 +390,15 @@ isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
/*
* Emit the message.
*/
result = table_towire(alist, target);
result = table_towire(alist, buffer);
if (result != ISC_R_SUCCESS)
return (result);
if (secret != NULL)
return (sign(signed_rstart,
(unsigned int)(target->rstart - signed_rstart),
hmac_rstart, algorithm, secret));
return (sign((unsigned char *) (*buffer)->base + signed_size,
(*buffer)->used - signed_size,
(hmac_size == 0 ? NULL :
(unsigned char *) (*buffer)->base + hmac_size),
algorithm, secret));
return (ISC_R_SUCCESS);
}

View File

@@ -37,6 +37,7 @@
/*! \file isccc/cc.h */
#include <isc/lang.h>
#include <isc/buffer.h>
#include <isccc/types.h>
ISC_LANG_BEGINDECLS
@@ -65,7 +66,7 @@ ISC_LANG_BEGINDECLS
/*% Send to Wire */
isc_result_t
isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
isccc_cc_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer,
isc_uint32_t algorithm, isccc_region_t *secret);
/*% Get From Wire */