hex.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007, 2008, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: hex.c,v 1.20 2008/09/25 04:02:39 tbox Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <ctype.h>
00025 
00026 #include <isc/buffer.h>
00027 #include <isc/hex.h>
00028 #include <isc/lex.h>
00029 #include <isc/string.h>
00030 #include <isc/util.h>
00031 
00032 #define RETERR(x) do { \
00033         isc_result_t _r = (x); \
00034         if (_r != ISC_R_SUCCESS) \
00035                 return (_r); \
00036         } while (0)
00037 
00038 
00039 /*
00040  * BEW: These static functions are copied from lib/dns/rdata.c.
00041  */
00042 static isc_result_t
00043 str_totext(const char *source, isc_buffer_t *target);
00044 
00045 static isc_result_t
00046 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
00047 
00048 static const char hex[] = "0123456789ABCDEF";
00049 
00050 isc_result_t
00051 isc_hex_totext(isc_region_t *source, int wordlength,
00052                const char *wordbreak, isc_buffer_t *target)
00053 {
00054         char buf[3];
00055         unsigned int loops = 0;
00056 
00057         if (wordlength < 2)
00058                 wordlength = 2;
00059 
00060         memset(buf, 0, sizeof(buf));
00061         while (source->length > 0) {
00062                 buf[0] = hex[(source->base[0] >> 4) & 0xf];
00063                 buf[1] = hex[(source->base[0]) & 0xf];
00064                 RETERR(str_totext(buf, target));
00065                 isc_region_consume(source, 1);
00066 
00067                 loops++;
00068                 if (source->length != 0 &&
00069                     (int)((loops + 1) * 2) >= wordlength)
00070                 {
00071                         loops = 0;
00072                         RETERR(str_totext(wordbreak, target));
00073                 }
00074         }
00075         return (ISC_R_SUCCESS);
00076 }
00077 
00078 /*%
00079  * State of a hex decoding process in progress.
00080  */
00081 typedef struct {
00082         int length;             /*%< Desired length of binary data or -1 */
00083         isc_buffer_t *target;   /*%< Buffer for resulting binary data */
00084         int digits;             /*%< Number of buffered hex digits */
00085         int val[2];
00086 } hex_decode_ctx_t;
00087 
00088 static inline void
00089 hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
00090 {
00091         ctx->digits = 0;
00092         ctx->length = length;
00093         ctx->target = target;
00094 }
00095 
00096 static inline isc_result_t
00097 hex_decode_char(hex_decode_ctx_t *ctx, int c) {
00098         char *s;
00099 
00100         if ((s = strchr(hex, toupper(c))) == NULL)
00101                 return (ISC_R_BADHEX);
00102         ctx->val[ctx->digits++] = (int)(s - hex);
00103         if (ctx->digits == 2) {
00104                 unsigned char num;
00105 
00106                 num = (ctx->val[0] << 4) + (ctx->val[1]);
00107                 RETERR(mem_tobuffer(ctx->target, &num, 1));
00108                 if (ctx->length >= 0) {
00109                         if (ctx->length == 0)
00110                                 return (ISC_R_BADHEX);
00111                         else
00112                                 ctx->length -= 1;
00113                 }
00114                 ctx->digits = 0;
00115         }
00116         return (ISC_R_SUCCESS);
00117 }
00118 
00119 static inline isc_result_t
00120 hex_decode_finish(hex_decode_ctx_t *ctx) {
00121         if (ctx->length > 0)
00122                 return (ISC_R_UNEXPECTEDEND);
00123         if (ctx->digits != 0)
00124                 return (ISC_R_BADHEX);
00125         return (ISC_R_SUCCESS);
00126 }
00127 
00128 isc_result_t
00129 isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
00130         hex_decode_ctx_t ctx;
00131         isc_textregion_t *tr;
00132         isc_token_t token;
00133         isc_boolean_t eol;
00134 
00135         hex_decode_init(&ctx, length, target);
00136 
00137         while (ctx.length != 0) {
00138                 unsigned int i;
00139 
00140                 if (length > 0)
00141                         eol = ISC_FALSE;
00142                 else
00143                         eol = ISC_TRUE;
00144                 RETERR(isc_lex_getmastertoken(lexer, &token,
00145                                               isc_tokentype_string, eol));
00146                 if (token.type != isc_tokentype_string)
00147                         break;
00148                 tr = &token.value.as_textregion;
00149                 for (i = 0; i < tr->length; i++)
00150                         RETERR(hex_decode_char(&ctx, tr->base[i]));
00151         }
00152         if (ctx.length < 0)
00153                 isc_lex_ungettoken(lexer, &token);
00154         RETERR(hex_decode_finish(&ctx));
00155         return (ISC_R_SUCCESS);
00156 }
00157 
00158 isc_result_t
00159 isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
00160         hex_decode_ctx_t ctx;
00161 
00162         hex_decode_init(&ctx, -1, target);
00163         for (;;) {
00164                 int c = *cstr++;
00165                 if (c == '\0')
00166                         break;
00167                 if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
00168                         continue;
00169                 RETERR(hex_decode_char(&ctx, c));
00170         }
00171         RETERR(hex_decode_finish(&ctx));
00172         return (ISC_R_SUCCESS);
00173 }
00174 
00175 static isc_result_t
00176 str_totext(const char *source, isc_buffer_t *target) {
00177         unsigned int l;
00178         isc_region_t region;
00179 
00180         isc_buffer_availableregion(target, &region);
00181         l = strlen(source);
00182 
00183         if (l > region.length)
00184                 return (ISC_R_NOSPACE);
00185 
00186         memmove(region.base, source, l);
00187         isc_buffer_add(target, l);
00188         return (ISC_R_SUCCESS);
00189 }
00190 
00191 static isc_result_t
00192 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
00193         isc_region_t tr;
00194 
00195         isc_buffer_availableregion(target, &tr);
00196         if (length > tr.length)
00197                 return (ISC_R_NOSPACE);
00198         memmove(tr.base, base, length);
00199         isc_buffer_add(target, length);
00200         return (ISC_R_SUCCESS);
00201 }

Generated on Tue Apr 28 17:41:04 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha