hex.c revision 6098d364b690cb9dabf96e9664c4689c8559bd2e
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki/*
f89adb2c2a52b505501c3eaa2aec9fd4df6bd60aTinderbox User * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * Copyright (C) 2000-2003 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and/or distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * copyright notice and this permission notice appear in all copies.
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki *
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * PERFORMANCE OF THIS SOFTWARE.
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki/* $Id: hex.c,v 1.19 2008/09/24 02:46:23 marka Exp $ */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki/*! \file */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <config.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <ctype.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <isc/buffer.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <isc/hex.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <isc/lex.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <isc/string.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#include <isc/util.h>
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki#define RETERR(x) do { \
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_result_t _r = (x); \
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (_r != ISC_R_SUCCESS) \
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (_r); \
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki } while (0)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki/*
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * BEW: These static functions are copied from lib/dns/rdata.c.
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic isc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistr_totext(const char *source, isc_buffer_t *target);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic isc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickimem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic const char hex[] = "0123456789ABCDEF";
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickiisc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickiisc_hex_totext(isc_region_t *source, int wordlength,
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki const char *wordbreak, isc_buffer_t *target)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki{
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki char buf[3];
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki unsigned int loops = 0;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (wordlength < 2)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki wordlength = 2;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki memset(buf, 0, sizeof(buf));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki while (source->length > 0) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki buf[0] = hex[(source->base[0] >> 4) & 0xf];
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki buf[1] = hex[(source->base[0]) & 0xf];
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(str_totext(buf, target));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_region_consume(source, 1);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki loops++;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (source->length != 0 &&
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki (int)((loops + 1) * 2) >= wordlength)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki loops = 0;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(str_totext(wordbreak, target));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki }
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki }
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki/*%
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki * State of a hex decoding process in progress.
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickitypedef struct {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki int length; /*%< Desired length of binary data or -1 */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_buffer_t *target; /*%< Buffer for resulting binary data */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki int digits; /*%< Number of buffered hex digits */
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki int val[2];
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki} hex_decode_ctx_t;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic inline void
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickihex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki{
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki ctx->digits = 0;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki ctx->length = length;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki ctx->target = target;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic inline isc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickihex_decode_char(hex_decode_ctx_t *ctx, int c) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki char *s;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if ((s = strchr(hex, toupper(c))) == NULL)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_BADHEX);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki ctx->val[ctx->digits++] = s - hex;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (ctx->digits == 2) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki unsigned char num;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki num = (ctx->val[0] << 4) + (ctx->val[1]);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(mem_tobuffer(ctx->target, &num, 1));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (ctx->length >= 0) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (ctx->length == 0)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_BADHEX);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki else
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki ctx->length -= 1;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki }
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki ctx->digits = 0;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki }
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic inline isc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickihex_decode_finish(hex_decode_ctx_t *ctx) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (ctx->length > 0)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_UNEXPECTEDEND);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (ctx->digits != 0)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_BADHEX);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickiisc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickiisc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki hex_decode_ctx_t ctx;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_textregion_t *tr;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_token_t token;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_boolean_t eol;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki hex_decode_init(&ctx, length, target);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki while (ctx.length != 0) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki unsigned int i;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (length > 0)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki eol = ISC_FALSE;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki else
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki eol = ISC_TRUE;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(isc_lex_getmastertoken(lexer, &token,
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_tokentype_string, eol));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (token.type != isc_tokentype_string)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki break;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki tr = &token.value.as_textregion;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki for (i = 0; i < tr->length; i++)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(hex_decode_char(&ctx, tr->base[i]));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki }
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (ctx.length < 0)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_lex_ungettoken(lexer, &token);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(hex_decode_finish(&ctx));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickiisc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickiisc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki hex_decode_ctx_t ctx;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki hex_decode_init(&ctx, -1, target);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki for (;;) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki int c = *cstr++;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (c == '\0')
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki break;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki continue;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(hex_decode_char(&ctx, c));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki }
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki RETERR(hex_decode_finish(&ctx));
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic isc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistr_totext(const char *source, isc_buffer_t *target) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki unsigned int l;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_region_t region;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_buffer_availableregion(target, &region);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki l = strlen(source);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (l > region.length)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_NOSPACE);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki memcpy(region.base, source, l);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_buffer_add(target, l);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickistatic isc_result_t
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecickimem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_region_t tr;
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_buffer_availableregion(target, &tr);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki if (length > tr.length)
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_NOSPACE);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki memcpy(tr.base, base, length);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki isc_buffer_add(target, length);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki return (ISC_R_SUCCESS);
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki}
19d80ce5844e00a021643759adcbe27c11b485a0Witold Krecicki