Exemple #1
0
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();
}
Exemple #3
0
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);
}
Exemple #4
0
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);
}
Exemple #5
0
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;
}
Exemple #6
0
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, &region);
	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, &region);
		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, &region);
		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);
}
Exemple #7
0
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);
}
Exemple #8
0
/**
 * 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;
}