static isc_result_t maybe_numeric(unsigned int *valuep, isc_textregion_t *source, unsigned int max, isc_boolean_t hex_allowed) { isc_result_t result; isc_uint32_t n; char buffer[NUMBERSIZE]; if (! isdigit(source->base[0] & 0xff) || source->length > NUMBERSIZE - 1) return (ISC_R_BADNUMBER); /* * We have a potential number. Try to parse it with * isc_parse_uint32(). isc_parse_uint32() requires * null termination, so we must make a copy. */ strncpy(buffer, source->base, NUMBERSIZE); INSIST(buffer[source->length] == '\0'); result = isc_parse_uint32(&n, buffer, 10); if (result == ISC_R_BADNUMBER && hex_allowed) result = isc_parse_uint32(&n, buffer, 16); if (result != ISC_R_SUCCESS) return (result); if (n > max) return (ISC_R_RANGE); *valuep = n; return (ISC_R_SUCCESS); }
ATF_TC_BODY(parse_overflow, tc) { isc_result_t result; isc_uint32_t output; UNUSED(tc); result = isc_test_begin(NULL, ISC_TRUE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = isc_parse_uint32(&output, "1234567890", 10); ATF_CHECK_EQ(ISC_R_SUCCESS, result); ATF_CHECK_EQ(1234567890, output); result = isc_parse_uint32(&output, "123456789012345", 10); ATF_CHECK_EQ(ISC_R_RANGE, result); result = isc_parse_uint32(&output, "12345678901234567890", 10); ATF_CHECK_EQ(ISC_R_RANGE, result); isc_test_end(); }
isc_result_t isc_parse_uint8(isc_uint8_t *uip, const char *string, int base) { isc_uint32_t val; isc_result_t result; result = isc_parse_uint32(&val, string, base); if (result != ISC_R_SUCCESS) return (result); if (val > 0xFF) return (ISC_R_RANGE); *uip = (isc_uint8_t) val; return (ISC_R_SUCCESS); }
static isc_result_t parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc) { isc_uint32_t n; isc_result_t result = isc_parse_uint32(&n, value, 10); if (result == ISC_R_SUCCESS && n > max) result = ISC_R_RANGE; if (result != ISC_R_SUCCESS) { printf("invalid %s '%s': %s\n", desc, value, isc_result_totext(result)); return result; } *uip = n; return (ISC_R_SUCCESS); }
static isc_uint32_t parse_uint(const char *desc, const char *str, unsigned int min, unsigned int max) { isc_uint32_t val; isc_result_t result; val = 0; result = isc_parse_uint32(&val, str, 10); if (result != ISC_R_SUCCESS || val < min || val > max) { fprintf(stderr, "invalid %s: %s\n", desc, str); perf_opt_usage(); exit(1); } return val; }
static void update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete, dns_name_t *name) { isc_result_t result; isc_uint32_t ttl; char *word; dns_rdataclass_t rdataclass; dns_rdatatype_t rdatatype; dns_rdata_t *rdata = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdataset_t *rdataset = NULL; isc_textregion_t region; /* * Read the owner name. */ parse_name(&cmdline, name); rdata = isc_mem_get(mctx, sizeof(*rdata)); if (rdata == NULL) { fprintf(stderr, "memory allocation for rdata failed\n"); exit(1); } dns_rdata_init(rdata); /* * If this is an add, read the TTL and verify that it's in range. * If it's a delete, ignore a TTL if present (for compatibility). */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { if (!isdelete) { fprintf(stderr, "could not read owner ttl\n"); exit(1); } else { ttl = 0; rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } } result = isc_parse_uint32(&ttl, word, 10); if (result != ISC_R_SUCCESS) { if (isdelete) { ttl = 0; goto parseclass; } else { fprintf(stderr, "ttl '%s': %s\n", word, isc_result_totext(result)); exit(1); } } if (isdelete) ttl = 0; else if (ttl > TTL_MAX) { fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, TTL_MAX); exit(1); } /* * Read the class or type. */ word = nsu_strsep(&cmdline, " \t\r\n"); parseclass: if (word == NULL || *word == 0) { if (isdelete) { rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } else { fprintf(stderr, "could not read class or type\n"); exit(1); } } region.base = word; region.length = strlen(word); result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS) { /* * Now read the type. */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { if (isdelete) { rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } else { fprintf(stderr, "could not read type\n"); exit(1); } } region.base = word; region.length = strlen(word); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid type: %s\n", word, isc_result_totext(result)); exit(1); } } else { rdataclass = default_rdataclass; result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid class or type: " "%s\n", word, isc_result_totext(result)); exit(1); } } parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); if (isdelete) { if ((rdata->flags & DNS_RDATA_UPDATE) != 0) rdataclass = dns_rdataclass_any; else rdataclass = dns_rdataclass_none; } else { if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { fprintf(stderr, "could not read rdata\n"); exit(1); } } doneparsing: rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); if (rdatalist == NULL) { fprintf(stderr, "memory allocation for rdatalist failed\n"); exit(1); } dns_rdatalist_init(rdatalist); rdatalist->type = rdatatype; rdatalist->rdclass = rdataclass; rdatalist->covers = rdatatype; rdatalist->ttl = (dns_ttl_t)ttl; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); ISC_LIST_APPEND(usedrdatalists, rdatalist, link); rdataset = isc_mem_get(mctx, sizeof(*rdataset)); if (rdataset == NULL) { fprintf(stderr, "memory allocation for rdataset failed\n"); exit(1); } dns_rdataset_init(rdataset); dns_rdatalist_tordataset(rdatalist, rdataset); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); }
static isc_result_t bind_ttl(isc_textregion_t *source, isc_uint32_t *ttl) { isc_uint32_t tmp = 0; isc_uint32_t n; char *s; char buf[64]; char nbuf[64]; /* Number buffer */ /* * Copy the buffer as it may not be NULL terminated. * No legal counter / ttl is longer that 63 characters. */ if (source->length > sizeof(buf) - 1) return (DNS_R_SYNTAX); strncpy(buf, source->base, source->length); buf[source->length] = '\0'; s = buf; do { isc_result_t result; char *np = nbuf; while (*s != '\0' && isdigit((unsigned char)*s)) *np++ = *s++; *np++ = '\0'; INSIST(np - nbuf <= (int)sizeof(nbuf)); result = isc_parse_uint32(&n, nbuf, 10); if (result != ISC_R_SUCCESS) return (DNS_R_SYNTAX); switch (*s) { case 'w': case 'W': tmp += n * 7 * 24 * 3600; s++; break; case 'd': case 'D': tmp += n * 24 * 3600; s++; break; case 'h': case 'H': tmp += n * 3600; s++; break; case 'm': case 'M': tmp += n * 60; s++; break; case 's': case 'S': tmp += n; s++; break; case '\0': /* Plain number? */ if (tmp != 0) return (DNS_R_SYNTAX); tmp = n; break; default: return (DNS_R_SYNTAX); } } while (*s != '\0'); *ttl = tmp; return (ISC_R_SUCCESS); }
/** * Convert and copy value to setting structure. * * @retval ISC_R_SUCCESS New value was converted and copied. * @retval ISC_R_IGNORE New and old values are same, no change was made. * @retval ISC_R_NOMEMORY * @retval ISC_R_UNEXPECTEDEND * @retval ISC_R_UNEXPECTEDTOKEN * @retval others Other errors from isc_parse_uint32(). */ static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT set_value(isc_mem_t *mctx, const settings_set_t *set, setting_t *setting, const char *value) { isc_result_t result; isc_uint32_t numeric_value; isc_uint32_t len; REQUIRE(setting != NULL); REQUIRE(value != NULL); REQUIRE(set != NULL); /* catch attempts to modify built-in defaults */ REQUIRE(set->lock != NULL); LOCK(set->lock); /* Check and convert new values. */ switch (setting->type) { case ST_STRING: if (setting->filled && strcmp(setting->value.value_char, value) == 0) CLEANUP_WITH(ISC_R_IGNORE); break; case ST_UNSIGNED_INTEGER: if (*value == '\0') CLEANUP_WITH(ISC_R_UNEXPECTEDEND); result = isc_parse_uint32(&numeric_value, value, 10); if (result != ISC_R_SUCCESS) { log_error_r("setting '%s' has to be unsigned integer " "(base 10)", setting->name); goto cleanup; } if (setting->filled && setting->value.value_uint == numeric_value) CLEANUP_WITH(ISC_R_IGNORE); break; case ST_BOOLEAN: if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0) numeric_value = 1; else if (strcasecmp(value, "no") == 0 || strcasecmp(value, "false") == 0) numeric_value = 0; else { log_error("unknown boolean expression " "(setting '%s': value '%s')", setting->name, value); CLEANUP_WITH(ISC_R_UNEXPECTEDTOKEN); } if (setting->filled && setting->value.value_boolean == ISC_TF(numeric_value)) CLEANUP_WITH(ISC_R_IGNORE); break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, "invalid setting_type_t value %u", setting->type); break; } switch (setting->type) { case ST_STRING: len = strlen(value) + 1; if (setting->is_dynamic) isc_mem_free(mctx, setting->value.value_char); CHECKED_MEM_ALLOCATE(mctx, setting->value.value_char, len); setting->is_dynamic = ISC_TRUE; CHECK(isc_string_copy(setting->value.value_char, len, value)); break; case ST_UNSIGNED_INTEGER: setting->value.value_uint = numeric_value; break; case ST_BOOLEAN: setting->value.value_boolean = ISC_TF(numeric_value); break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, "invalid setting_type_t value %u", setting->type); break; } setting->filled = 1; result = ISC_R_SUCCESS; cleanup: UNLOCK(set->lock); return result; }