"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/isc/hex.c" (4 Sep 2020, 4714 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "hex.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <ctype.h>
   15 #include <stdbool.h>
   16 
   17 #include <isc/buffer.h>
   18 #include <isc/hex.h>
   19 #include <isc/lex.h>
   20 #include <isc/string.h>
   21 #include <isc/util.h>
   22 
   23 #define RETERR(x)                        \
   24     do {                             \
   25         isc_result_t _r = (x);   \
   26         if (_r != ISC_R_SUCCESS) \
   27             return ((_r));   \
   28     } while (0)
   29 
   30 /*
   31  * BEW: These static functions are copied from lib/dns/rdata.c.
   32  */
   33 static isc_result_t
   34 str_totext(const char *source, isc_buffer_t *target);
   35 
   36 static isc_result_t
   37 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
   38 
   39 static const char hex[] = "0123456789ABCDEF";
   40 
   41 isc_result_t
   42 isc_hex_totext(isc_region_t *source, int wordlength, const char *wordbreak,
   43            isc_buffer_t *target) {
   44     char buf[3];
   45     unsigned int loops = 0;
   46 
   47     if (wordlength < 2) {
   48         wordlength = 2;
   49     }
   50 
   51     memset(buf, 0, sizeof(buf));
   52     while (source->length > 0) {
   53         buf[0] = hex[(source->base[0] >> 4) & 0xf];
   54         buf[1] = hex[(source->base[0]) & 0xf];
   55         RETERR(str_totext(buf, target));
   56         isc_region_consume(source, 1);
   57 
   58         loops++;
   59         if (source->length != 0 && (int)((loops + 1) * 2) >= wordlength)
   60         {
   61             loops = 0;
   62             RETERR(str_totext(wordbreak, target));
   63         }
   64     }
   65     return (ISC_R_SUCCESS);
   66 }
   67 
   68 /*%
   69  * State of a hex decoding process in progress.
   70  */
   71 typedef struct {
   72     int length;       /*%< Desired length of binary data or -1 */
   73     isc_buffer_t *target; /*%< Buffer for resulting binary data */
   74     int digits;       /*%< Number of buffered hex digits */
   75     int val[2];
   76 } hex_decode_ctx_t;
   77 
   78 static inline void
   79 hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target) {
   80     ctx->digits = 0;
   81     ctx->length = length;
   82     ctx->target = target;
   83 }
   84 
   85 static inline isc_result_t
   86 hex_decode_char(hex_decode_ctx_t *ctx, int c) {
   87     const char *s;
   88 
   89     if ((s = strchr(hex, toupper(c))) == NULL) {
   90         return (ISC_R_BADHEX);
   91     }
   92     ctx->val[ctx->digits++] = (int)(s - hex);
   93     if (ctx->digits == 2) {
   94         unsigned char num;
   95 
   96         num = (ctx->val[0] << 4) + (ctx->val[1]);
   97         RETERR(mem_tobuffer(ctx->target, &num, 1));
   98         if (ctx->length >= 0) {
   99             if (ctx->length == 0) {
  100                 return (ISC_R_BADHEX);
  101             } else {
  102                 ctx->length -= 1;
  103             }
  104         }
  105         ctx->digits = 0;
  106     }
  107     return (ISC_R_SUCCESS);
  108 }
  109 
  110 static inline isc_result_t
  111 hex_decode_finish(hex_decode_ctx_t *ctx) {
  112     if (ctx->length > 0) {
  113         return (ISC_R_UNEXPECTEDEND);
  114     }
  115     if (ctx->digits != 0) {
  116         return (ISC_R_BADHEX);
  117     }
  118     return (ISC_R_SUCCESS);
  119 }
  120 
  121 isc_result_t
  122 isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
  123     unsigned int before, after;
  124     hex_decode_ctx_t ctx;
  125     isc_textregion_t *tr;
  126     isc_token_t token;
  127     bool eol;
  128 
  129     REQUIRE(length >= -2);
  130 
  131     hex_decode_init(&ctx, length, target);
  132 
  133     before = isc_buffer_usedlength(target);
  134     while (ctx.length != 0) {
  135         unsigned int i;
  136 
  137         if (length > 0) {
  138             eol = false;
  139         } else {
  140             eol = true;
  141         }
  142         RETERR(isc_lex_getmastertoken(lexer, &token,
  143                           isc_tokentype_string, eol));
  144         if (token.type != isc_tokentype_string) {
  145             break;
  146         }
  147         tr = &token.value.as_textregion;
  148         for (i = 0; i < tr->length; i++) {
  149             RETERR(hex_decode_char(&ctx, tr->base[i]));
  150         }
  151     }
  152     after = isc_buffer_usedlength(target);
  153     if (ctx.length < 0) {
  154         isc_lex_ungettoken(lexer, &token);
  155     }
  156     RETERR(hex_decode_finish(&ctx));
  157     if (length == -2 && before == after) {
  158         return (ISC_R_UNEXPECTEDEND);
  159     }
  160     return (ISC_R_SUCCESS);
  161 }
  162 
  163 isc_result_t
  164 isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
  165     hex_decode_ctx_t ctx;
  166 
  167     hex_decode_init(&ctx, -1, target);
  168     for (;;) {
  169         int c = *cstr++;
  170         if (c == '\0') {
  171             break;
  172         }
  173         if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
  174             continue;
  175         }
  176         RETERR(hex_decode_char(&ctx, c));
  177     }
  178     RETERR(hex_decode_finish(&ctx));
  179     return (ISC_R_SUCCESS);
  180 }
  181 
  182 static isc_result_t
  183 str_totext(const char *source, isc_buffer_t *target) {
  184     unsigned int l;
  185     isc_region_t region;
  186 
  187     isc_buffer_availableregion(target, &region);
  188     l = strlen(source);
  189 
  190     if (l > region.length) {
  191         return (ISC_R_NOSPACE);
  192     }
  193 
  194     memmove(region.base, source, l);
  195     isc_buffer_add(target, l);
  196     return (ISC_R_SUCCESS);
  197 }
  198 
  199 static isc_result_t
  200 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
  201     isc_region_t tr;
  202 
  203     isc_buffer_availableregion(target, &tr);
  204     if (length > tr.length) {
  205         return (ISC_R_NOSPACE);
  206     }
  207     memmove(tr.base, base, length);
  208     isc_buffer_add(target, length);
  209     return (ISC_R_SUCCESS);
  210 }