Return to hex.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc |
1.1 ! misho 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.20 2008/09/25 04:02:39 tbox 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, ®ion); ! 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: }