Add isc_hex_* routines, which handle conversion to and from hex strings.
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.66 2000/09/20 19:06:02 gson Exp $
|
||||
# $Id: Makefile.in,v 1.67 2000/11/07 20:58:04 bwelling Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -51,7 +51,7 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \
|
||||
OBJS = @ISC_EXTRA_OBJS@ \
|
||||
assertions.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \
|
||||
bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ \
|
||||
heap.@O@ hmacmd5.@O@ \
|
||||
heap.@O@ hex.@O@ hmacmd5.@O@ \
|
||||
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
||||
md5.@O@ mem.@O@ mutexblock.@O@ netaddr.@O@ ondestroy.@O@ \
|
||||
quota.@O@ random.@O@ \
|
||||
@@ -64,7 +64,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
|
||||
SRCS = @ISC_EXTRA_SRCS@ \
|
||||
assertions.c base64.c bitstring.c buffer.c \
|
||||
bufferlist.c commandline.c error.c event.c \
|
||||
heap.c hmacmd5.c \
|
||||
heap.c hex.c hmacmd5.c \
|
||||
lex.c lfsr.c lib.c log.c \
|
||||
md5.c mem.c mutexblock.c netaddr.c ondestroy.c \
|
||||
quota.c random.c \
|
||||
|
||||
224
lib/isc/hex.c
Normal file
224
lib/isc/hex.c
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/lex.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#define RETERR(x) do { \
|
||||
isc_result_t _r = (x); \
|
||||
if (_r != ISC_R_SUCCESS) \
|
||||
return (_r); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* BEW: These static functions are copied from lib/dns/rdata.c.
|
||||
*/
|
||||
static isc_result_t
|
||||
str_totext(const char *source, isc_buffer_t *target);
|
||||
|
||||
static isc_result_t
|
||||
gettoken(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect,
|
||||
isc_boolean_t eol);
|
||||
|
||||
static isc_result_t
|
||||
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
|
||||
|
||||
static const char hex[] = "0123456789ABCDEF";
|
||||
|
||||
isc_result_t
|
||||
isc_hex_totext(isc_region_t *source, int wordlength,
|
||||
const char *wordbreak, isc_buffer_t *target)
|
||||
{
|
||||
char buf[3];
|
||||
unsigned int loops = 0;
|
||||
|
||||
if (wordlength < 2)
|
||||
wordlength = 2;
|
||||
|
||||
memset(buf, 0, sizeof buf);
|
||||
while (source->length > 0) {
|
||||
buf[0] = hex[(source->base[0] >> 4) & 0xf];
|
||||
buf[1] = hex[(source->base[0]) & 0xf];
|
||||
RETERR(str_totext(buf, target));
|
||||
isc_region_consume(source, 1);
|
||||
|
||||
loops++;
|
||||
if (source->length != 0 &&
|
||||
(int)((loops + 1) * 2) >= wordlength)
|
||||
{
|
||||
loops = 0;
|
||||
RETERR(str_totext(wordbreak, target));
|
||||
}
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* State of a hex decoding process in progress.
|
||||
*/
|
||||
typedef struct {
|
||||
int length; /* Desired length of binary data or -1 */
|
||||
isc_buffer_t *target; /* Buffer for resulting binary data */
|
||||
int digits; /* Number of buffered hex digits */
|
||||
int val[2];
|
||||
} hex_decode_ctx_t;
|
||||
|
||||
static inline void
|
||||
hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
|
||||
{
|
||||
ctx->digits = 0;
|
||||
ctx->length = length;
|
||||
ctx->target = target;
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
hex_decode_char(hex_decode_ctx_t *ctx, int c) {
|
||||
char *s;
|
||||
|
||||
if ((s = strchr(hex, c)) == NULL)
|
||||
return (ISC_R_BADHEX);
|
||||
ctx->val[ctx->digits++] = s - hex;
|
||||
if (ctx->digits == 2) {
|
||||
int n;
|
||||
unsigned char num;
|
||||
|
||||
num = (ctx->val[0] << 4) + (ctx->val[1]);
|
||||
RETERR(mem_tobuffer(ctx->target, &num, 1));
|
||||
if (ctx->length >= 0) {
|
||||
if (n > ctx->length)
|
||||
return (ISC_R_BADHEX);
|
||||
else
|
||||
ctx->length -= n;
|
||||
}
|
||||
ctx->digits = 0;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
hex_decode_finish(hex_decode_ctx_t *ctx) {
|
||||
if (ctx->length > 0)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
if (ctx->digits != 0)
|
||||
return (ISC_R_BADHEX);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
|
||||
hex_decode_ctx_t ctx;
|
||||
isc_textregion_t *tr;
|
||||
isc_token_t token;
|
||||
|
||||
hex_decode_init(&ctx, length, target);
|
||||
|
||||
while (ctx.length != 0) {
|
||||
unsigned int i;
|
||||
|
||||
if (length > 0)
|
||||
RETERR(gettoken(lexer, &token, isc_tokentype_string,
|
||||
ISC_FALSE));
|
||||
else
|
||||
RETERR(gettoken(lexer, &token, isc_tokentype_string,
|
||||
ISC_TRUE));
|
||||
if (token.type != isc_tokentype_string)
|
||||
break;
|
||||
tr = &token.value.as_textregion;
|
||||
for (i = 0 ;i < tr->length; i++)
|
||||
RETERR(hex_decode_char(&ctx, tr->base[i]));
|
||||
}
|
||||
RETERR(hex_decode_finish(&ctx));
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_hex_decodestring(isc_mem_t *mctx, char *cstr, isc_buffer_t *target) {
|
||||
hex_decode_ctx_t ctx;
|
||||
|
||||
UNUSED(mctx);
|
||||
|
||||
hex_decode_init(&ctx, -1, target);
|
||||
for (;;) {
|
||||
int c = *cstr++;
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
|
||||
continue;
|
||||
RETERR(hex_decode_char(&ctx, c));
|
||||
}
|
||||
RETERR(hex_decode_finish(&ctx));
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
str_totext(const char *source, isc_buffer_t *target) {
|
||||
unsigned int l;
|
||||
isc_region_t region;
|
||||
|
||||
isc_buffer_availableregion(target, ®ion);
|
||||
l = strlen(source);
|
||||
|
||||
if (l > region.length)
|
||||
return (ISC_R_NOSPACE);
|
||||
|
||||
memcpy(region.base, source, l);
|
||||
isc_buffer_add(target, l);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
|
||||
isc_region_t tr;
|
||||
|
||||
isc_buffer_availableregion(target, &tr);
|
||||
if (length > tr.length)
|
||||
return (ISC_R_NOSPACE);
|
||||
memcpy(tr.base, base, length);
|
||||
isc_buffer_add(target, length);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
gettoken(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect,
|
||||
isc_boolean_t eol)
|
||||
{
|
||||
unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
|
||||
ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
|
||||
isc_result_t result;
|
||||
|
||||
if (expect == isc_tokentype_qstring)
|
||||
options |= ISC_LEXOPT_QSTRING;
|
||||
else if (expect == isc_tokentype_number)
|
||||
options |= ISC_LEXOPT_NUMBER;
|
||||
result = isc_lex_gettoken(lexer, options, token);
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
break;
|
||||
case ISC_R_NOMEMORY:
|
||||
return (ISC_R_NOMEMORY);
|
||||
case ISC_R_NOSPACE:
|
||||
return (ISC_R_NOSPACE);
|
||||
default:
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_lex_gettoken() failed: %s",
|
||||
isc_result_totext(result));
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
if (eol && ((token->type == isc_tokentype_eol) ||
|
||||
(token->type == isc_tokentype_eof)))
|
||||
return (ISC_R_SUCCESS);
|
||||
if (token->type == isc_tokentype_string &&
|
||||
expect == isc_tokentype_qstring)
|
||||
return (ISC_R_SUCCESS);
|
||||
if (token->type != expect) {
|
||||
isc_lex_ungettoken(lexer, token);
|
||||
if (token->type == isc_tokentype_eol ||
|
||||
token->type == isc_tokentype_eof)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
return (ISC_R_UNEXPECTEDTOKEN);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.44 2000/09/20 19:06:03 gson Exp $
|
||||
# $Id: Makefile.in,v 1.45 2000/11/07 20:58:06 bwelling Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -29,7 +29,7 @@ top_srcdir = @top_srcdir@
|
||||
HEADERS = assertions.h base64.h bitstring.h boolean.h buffer.h \
|
||||
bufferlist.h commandline.h entropy.h error.h event.h \
|
||||
eventclass.h \
|
||||
file.h formatcheck.h fsaccess.h heap.h hmacmd5.h \
|
||||
file.h formatcheck.h fsaccess.h heap.h hex.h hmacmd5.h \
|
||||
interfaceiter.h @ISC_IPV6_H@ lang.h lex.h \
|
||||
lfsr.h lib.h list.h log.h magic.h md5.h mem.h msgcat.h \
|
||||
mutexblock.h netaddr.h ondestroy.h os.h \
|
||||
|
||||
78
lib/isc/include/isc/hex.h
Normal file
78
lib/isc/include/isc/hex.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef ISC_HEX_H
|
||||
#define ISC_HEX_H 1
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
isc_result_t
|
||||
isc_hex_totext(isc_region_t *source, int wordlength,
|
||||
const char *wordbreak, isc_buffer_t *target);
|
||||
/*
|
||||
* Convert data into hex encoded text.
|
||||
*
|
||||
* Notes:
|
||||
* The hex encoded text in 'target' will be divided into
|
||||
* words of at most 'wordlength' characters, separated by
|
||||
* the 'wordbreak' string. No parentheses will surround
|
||||
* the text.
|
||||
*
|
||||
* Requires:
|
||||
* 'source' is a region containing binary data
|
||||
* 'target' is a text buffer containing available space
|
||||
* 'wordbreak' points to a null-terminated string of
|
||||
* zero or more whitespace characters
|
||||
*
|
||||
* Ensures:
|
||||
* target will contain the hex encoded version of the data
|
||||
* in source. The 'used' pointer in target will be advanced as
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_hex_decodestring(isc_mem_t *mctx, char *cstr, isc_buffer_t *target);
|
||||
/*
|
||||
* Decode a null-terminated hex string.
|
||||
*
|
||||
* Requires:
|
||||
* 'mctx' is non-null.
|
||||
* 'cstr' is non-null.
|
||||
* 'target' is a valid buffer.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
|
||||
* fit in 'target'.
|
||||
* ISC_R_BADHEX -- 'cstr' is not a valid hex encoding.
|
||||
*
|
||||
* Other error returns are any possible error code from:
|
||||
* isc_lex_create(),
|
||||
* isc_lex_openbuffer(),
|
||||
* isc_hex_tobuffer().
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
|
||||
/*
|
||||
* Convert hex encoded text from a lexer context into data.
|
||||
*
|
||||
* Requires:
|
||||
* 'lex' is a valid lexer context
|
||||
* 'target' is a buffer containing binary data
|
||||
* 'length' is an integer
|
||||
*
|
||||
* Ensures:
|
||||
* target will contain the data represented by the hex encoded
|
||||
* string parsed by the lexer. No more than length bytes will be read,
|
||||
* if length is positive. The 'used' pointer in target will be
|
||||
* advanced as necessary.
|
||||
*/
|
||||
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISC_HEX_H */
|
||||
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: result.h,v 1.50 2000/08/15 23:30:22 tale Exp $ */
|
||||
/* $Id: result.h,v 1.51 2000/11/07 20:58:07 bwelling Exp $ */
|
||||
|
||||
#ifndef ISC_RESULT_H
|
||||
#define ISC_RESULT_H 1
|
||||
@@ -72,11 +72,12 @@
|
||||
#define ISC_R_QUEUEFULL 46 /* queue is full */
|
||||
#define ISC_R_FAMILYMISMATCH 47 /* address family mismatch */
|
||||
#define ISC_R_FAMILYNOSUPPORT 48 /* AF not supported */
|
||||
#define ISC_R_BADHEX 49 /* bad hex encoding */
|
||||
|
||||
/*
|
||||
* Not a result code: the number of results.
|
||||
*/
|
||||
#define ISC_R_NRESULTS 49
|
||||
#define ISC_R_NRESULTS 50
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: result.c,v 1.48 2000/08/15 01:43:36 marka Exp $ */
|
||||
/* $Id: result.c,v 1.49 2000/11/07 20:58:05 bwelling Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -86,7 +86,8 @@ static const char *text[ISC_R_NRESULTS] = {
|
||||
"not a directory", /* 45 */
|
||||
"queue is full", /* 46 */
|
||||
"address family mismatch", /* 47 */
|
||||
"address family not supported" /* 48 */
|
||||
"address family not supported", /* 48 */
|
||||
"bad hex encoding", /* 49 */
|
||||
};
|
||||
|
||||
#define ISC_RESULT_RESULTSET 2
|
||||
|
||||
Reference in New Issue
Block a user