File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc / hex.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 7 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
    3:  * Copyright (C) 2000-2003  Internet Software Consortium.
    4:  *
    5:  * Permission to use, copy, modify, and/or distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
   10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
   12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
   14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   15:  * PERFORMANCE OF THIS SOFTWARE.
   16:  */
   17: 
   18: /* $Id: hex.c,v 1.1.1.1 2012/05/29 12:08:38 misho Exp $ */
   19: 
   20: /*! \file */
   21: 
   22: #include <config.h>
   23: 
   24: #include <ctype.h>
   25: 
   26: #include <isc/buffer.h>
   27: #include <isc/hex.h>
   28: #include <isc/lex.h>
   29: #include <isc/string.h>
   30: #include <isc/util.h>
   31: 
   32: #define RETERR(x) do { \
   33: 	isc_result_t _r = (x); \
   34: 	if (_r != ISC_R_SUCCESS) \
   35: 		return (_r); \
   36: 	} while (0)
   37: 
   38: 
   39: /*
   40:  * BEW: These static functions are copied from lib/dns/rdata.c.
   41:  */
   42: static isc_result_t
   43: str_totext(const char *source, isc_buffer_t *target);
   44: 
   45: static isc_result_t
   46: mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
   47: 
   48: static const char hex[] = "0123456789ABCDEF";
   49: 
   50: isc_result_t
   51: isc_hex_totext(isc_region_t *source, int wordlength,
   52: 	       const char *wordbreak, isc_buffer_t *target)
   53: {
   54: 	char buf[3];
   55: 	unsigned int loops = 0;
   56: 
   57: 	if (wordlength < 2)
   58: 		wordlength = 2;
   59: 
   60: 	memset(buf, 0, sizeof(buf));
   61: 	while (source->length > 0) {
   62: 		buf[0] = hex[(source->base[0] >> 4) & 0xf];
   63: 		buf[1] = hex[(source->base[0]) & 0xf];
   64: 		RETERR(str_totext(buf, target));
   65: 		isc_region_consume(source, 1);
   66: 
   67: 		loops++;
   68: 		if (source->length != 0 &&
   69: 		    (int)((loops + 1) * 2) >= wordlength)
   70: 		{
   71: 			loops = 0;
   72: 			RETERR(str_totext(wordbreak, target));
   73: 		}
   74: 	}
   75: 	return (ISC_R_SUCCESS);
   76: }
   77: 
   78: /*%
   79:  * State of a hex decoding process in progress.
   80:  */
   81: typedef struct {
   82: 	int length;		/*%< Desired length of binary data or -1 */
   83: 	isc_buffer_t *target;	/*%< Buffer for resulting binary data */
   84: 	int digits;		/*%< Number of buffered hex digits */
   85: 	int val[2];
   86: } hex_decode_ctx_t;
   87: 
   88: static inline void
   89: hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
   90: {
   91: 	ctx->digits = 0;
   92: 	ctx->length = length;
   93: 	ctx->target = target;
   94: }
   95: 
   96: static inline isc_result_t
   97: hex_decode_char(hex_decode_ctx_t *ctx, int c) {
   98: 	char *s;
   99: 
  100: 	if ((s = strchr(hex, toupper(c))) == NULL)
  101: 		return (ISC_R_BADHEX);
  102: 	ctx->val[ctx->digits++] = s - hex;
  103: 	if (ctx->digits == 2) {
  104: 		unsigned char num;
  105: 
  106: 		num = (ctx->val[0] << 4) + (ctx->val[1]);
  107: 		RETERR(mem_tobuffer(ctx->target, &num, 1));
  108: 		if (ctx->length >= 0) {
  109: 			if (ctx->length == 0)
  110: 				return (ISC_R_BADHEX);
  111: 			else
  112: 				ctx->length -= 1;
  113: 		}
  114: 		ctx->digits = 0;
  115: 	}
  116: 	return (ISC_R_SUCCESS);
  117: }
  118: 
  119: static inline isc_result_t
  120: hex_decode_finish(hex_decode_ctx_t *ctx) {
  121: 	if (ctx->length > 0)
  122: 		return (ISC_R_UNEXPECTEDEND);
  123: 	if (ctx->digits != 0)
  124: 		return (ISC_R_BADHEX);
  125: 	return (ISC_R_SUCCESS);
  126: }
  127: 
  128: isc_result_t
  129: isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
  130: 	hex_decode_ctx_t ctx;
  131: 	isc_textregion_t *tr;
  132: 	isc_token_t token;
  133: 	isc_boolean_t eol;
  134: 
  135: 	hex_decode_init(&ctx, length, target);
  136: 
  137: 	while (ctx.length != 0) {
  138: 		unsigned int i;
  139: 
  140: 		if (length > 0)
  141: 			eol = ISC_FALSE;
  142: 		else
  143: 			eol = ISC_TRUE;
  144: 		RETERR(isc_lex_getmastertoken(lexer, &token,
  145: 					      isc_tokentype_string, eol));
  146: 		if (token.type != isc_tokentype_string)
  147: 			break;
  148: 		tr = &token.value.as_textregion;
  149: 		for (i = 0; i < tr->length; i++)
  150: 			RETERR(hex_decode_char(&ctx, tr->base[i]));
  151: 	}
  152: 	if (ctx.length < 0)
  153: 		isc_lex_ungettoken(lexer, &token);
  154: 	RETERR(hex_decode_finish(&ctx));
  155: 	return (ISC_R_SUCCESS);
  156: }
  157: 
  158: isc_result_t
  159: isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
  160: 	hex_decode_ctx_t ctx;
  161: 
  162: 	hex_decode_init(&ctx, -1, target);
  163: 	for (;;) {
  164: 		int c = *cstr++;
  165: 		if (c == '\0')
  166: 			break;
  167: 		if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
  168: 			continue;
  169: 		RETERR(hex_decode_char(&ctx, c));
  170: 	}
  171: 	RETERR(hex_decode_finish(&ctx));
  172: 	return (ISC_R_SUCCESS);
  173: }
  174: 
  175: static isc_result_t
  176: str_totext(const char *source, isc_buffer_t *target) {
  177: 	unsigned int l;
  178: 	isc_region_t region;
  179: 
  180: 	isc_buffer_availableregion(target, &region);
  181: 	l = strlen(source);
  182: 
  183: 	if (l > region.length)
  184: 		return (ISC_R_NOSPACE);
  185: 
  186: 	memcpy(region.base, source, l);
  187: 	isc_buffer_add(target, l);
  188: 	return (ISC_R_SUCCESS);
  189: }
  190: 
  191: static isc_result_t
  192: mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
  193: 	isc_region_t tr;
  194: 
  195: 	isc_buffer_availableregion(target, &tr);
  196: 	if (length > tr.length)
  197: 		return (ISC_R_NOSPACE);
  198: 	memcpy(tr.base, base, length);
  199: 	isc_buffer_add(target, length);
  200: 	return (ISC_R_SUCCESS);
  201: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>