+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]
* 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;
#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)) {
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)) {
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,
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;
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);
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;
listener = conn->listener;
algorithm = DST_ALG_UNKNOWN;
secret.rstart = NULL;
+ text = NULL;
/* Is the server shutting down? */
if (listener->controls->shuttingdown)
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);
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.
}
}
- 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;
}
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)
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:
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);
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,
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);
#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);
*/
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 */
*/
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.
*/
*/
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.
*/
* 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
* 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.
* 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 */
#define TCHECK(op) \
do { tresult = (op); \
if (tresult != ISC_R_SUCCESS) { \
- isc_buffer_clear(text); \
+ isc_buffer_clear(*text); \
goto cleanup; \
} \
} while (0)
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);
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;
*/
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;
* 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;
}
}
}
- 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);
}
* 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);
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);
}
* 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,
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);
}
}
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;
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);
}
}
}
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 = " (";
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"
-#ifdef ISC_PLATFORM_USETHREADS
- "CPUs found: %u\n"
- "worker threads: %u\n"
- "UDP listeners per interface: %u\n"
-#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,
+ 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
- ns_g_cpus_detected, ns_g_cpus, ns_g_udpdisp,
+ 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
- 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
}
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");
}
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];
dns_name_t *origin;
dns_rbtnode_t *node;
dns_tsigkey_t *tkey;
- unsigned int n;
const char *viewname;
if (view != NULL)
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 (n >= isc_buffer_availablelength(text)) {
- dns_rbtnodechain_invalidate(&chain);
- return (ISC_R_NOSPACE);
+ 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, "\";"));
}
- 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;
}
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);
}
* 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;
}
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;
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 ||
*/
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;
}
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 ||
* 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 */
* 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;
/* 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));
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);
}
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);
* 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;
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);
}
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;
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;
}
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;
}
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;
nametext, view->name);
}
- if (isc_buffer_availablelength(text) == 0)
- return (ISC_R_NOSPACE);
-
- isc_buffer_putuint8(text, 0);
+ CHECK(putnull(text));
}
cleanup:
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;
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--;
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,
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;
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);
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
dns_name_destroy();
+ isc_buffer_free(&databuf);
+
if (show_final_mem)
isc_mem_stats(mctx, stderr);
@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 =
--- /dev/null
+# 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}
rm -f ns*/named.run
rm -f ns4/*.conf
rm -f rndc.status
+rm -f rndc.output
--- /dev/null
+/*
+ * 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);
+}
$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
# 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"
#
"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" ;;
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
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">
*/
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
}
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;
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) {
}
}
- 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);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp $ */
-
/*! \file */
#include <config.h>
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;
* 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
#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
*\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);
/*!<
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@ \
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@
${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
--- /dev/null
+/*
+ * 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());
+}
isc_buffer_getuint32
isc_buffer_getuint8
isc_buffer_reinit
+isc_buffer_reallocate
+isc_buffer_reserve
isc_bufferlist_availablecount
isc_bufferlist_usedcount
isc_commandline_parse
#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;
/*
* 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);
}
}
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);
}
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.
* 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.
/*
* 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);
}
/*! \file isccc/cc.h */
#include <isc/lang.h>
+#include <isc/buffer.h>
#include <isccc/types.h>
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 */