Annotation of embedaddon/ntp/lib/isc/hex.c, revision 1.1.1.1

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, &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>