/* * Converts ascii size/precision X * 10**Y(cm) to 0xXY. * Sets the given pointer to the last used character. * */ static uint8_t precsize_aton (char *cp, char **endptr) { unsigned int mval = 0, cmval = 0; uint8_t retval = 0; int exponent; int mantissa; while (isdigit((unsigned char)*cp)) mval = mval * 10 + hexdigit_to_int(*cp++); if (*cp == '.') { /* centimeters */ cp++; if (isdigit((unsigned char)*cp)) { cmval = hexdigit_to_int(*cp++) * 10; if (isdigit((unsigned char)*cp)) { cmval += hexdigit_to_int(*cp++); } } } if(mval >= poweroften[7]) { assert(poweroften[7] != 0); /* integer overflow possible for *100 */ mantissa = mval / poweroften[7]; exponent = 9; /* max */ } else { cmval = (mval * 100) + cmval; for (exponent = 0; exponent < 9; exponent++) if (cmval < poweroften[exponent+1]) break; assert(poweroften[exponent] != 0); mantissa = cmval / poweroften[exponent]; } if (mantissa > 9) mantissa = 9; retval = (mantissa << 4) | exponent; if (*cp == 'm') cp++; *endptr = cp; return (retval); }
ssize_t hex_pton(const char* src, uint8_t* target, size_t targsize) { uint8_t *t = target; if(strlen(src) % 2 != 0 || strlen(src)/2 > targsize) { return -1; } while(*src) { if(!isxdigit((int)src[0]) || !isxdigit((int)src[1])) return -1; *t++ = hexdigit_to_int(src[0]) * 16 + hexdigit_to_int(src[1]) ; src += 2; } return t-target; }
/* * These are parser function for generic zone file stuff. */ uint16_t * zparser_conv_hex(region_type *region, const char *hex, size_t len) { /* convert a hex value to wireformat */ uint16_t *r = NULL; uint8_t *t; int i; if(len == 1 && hex[0] == '0') { /* single 0 represents empty buffer */ return alloc_rdata(region, 0); } if (len % 2 != 0) { zc_error_prev_line("number of hex digits must be a multiple of 2"); } else if (len > MAX_RDLENGTH * 2) { zc_error_prev_line("hex data exceeds maximum rdata length (%d)", MAX_RDLENGTH); } else { /* the length part */ r = alloc_rdata(region, len/2); t = (uint8_t *)(r + 1); /* Now process octet by octet... */ while (*hex) { *t = 0; for (i = 16; i >= 1; i -= 15) { if (isxdigit((unsigned char)*hex)) { *t += hexdigit_to_int(*hex) * i; } else { zc_error_prev_line( "illegal hex character '%c'", (int) *hex); return NULL; } ++hex; } ++t; } } return r; }
/* convert hex, precede by a 1-byte length */ uint16_t * zparser_conv_hex_length(region_type *region, const char *hex, size_t len) { uint16_t *r = NULL; uint8_t *t; int i; if (len % 2 != 0) { zc_error_prev_line("number of hex digits must be a multiple of 2"); } else if (len > 255 * 2) { zc_error_prev_line("hex data exceeds 255 bytes"); } else { uint8_t *l; /* the length part */ r = alloc_rdata(region, len/2+1); t = (uint8_t *)(r + 1); l = t++; *l = '\0'; /* Now process octet by octet... */ while (*hex) { *t = 0; for (i = 16; i >= 1; i -= 15) { if (isxdigit((unsigned char)*hex)) { *t += hexdigit_to_int(*hex) * i; } else { zc_error_prev_line( "illegal hex character '%c'", (int) *hex); return NULL; } ++hex; } ++t; ++*l; } } return r; }
int dname_parse_wire(uint8_t* dname, const char* name) { const uint8_t *s = (const uint8_t *) name; uint8_t *h; uint8_t *p; uint8_t *d = dname; size_t label_length; if (strcmp(name, ".") == 0) { /* Root domain. */ dname[0] = 0; return 1; } for (h = d, p = h + 1; *s; ++s, ++p) { if (p - dname >= MAXDOMAINLEN) { return 0; } switch (*s) { case '.': if (p == h + 1) { /* Empty label. */ return 0; } else { label_length = p - h - 1; if (label_length > MAXLABELLEN) { return 0; } *h = label_length; h = p; } break; case '\\': /* Handle escaped characters (RFC1035 5.1) */ if (isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])) { int val = (hexdigit_to_int(s[1]) * 100 + hexdigit_to_int(s[2]) * 10 + hexdigit_to_int(s[3])); if (0 <= val && val <= 255) { s += 3; *p = val; } else { *p = *++s; } } else if (s[1] != '\0') { *p = *++s; } break; default: *p = *s; break; } } if (p != h + 1) { /* Terminate last label. */ label_length = p - h - 1; if (label_length > MAXLABELLEN) { return 0; } *h = label_length; h = p; } /* Add root label. */ *h = 0; return p-dname; }