strlcat(buf, ".0", sizeof(buf));
if (inet_pton(AF_INET, buf, &in4a) == 1) {
isc_netaddr_fromin(na, &in4a);
- return (ISC_R_SUCCESS);
+ return (ISC_R_IPV4PREFIX);
}
}
}
REQUIRE(pctx != NULL);
result = token_addr(pctx, flags, &na_dummy);
- return (result == ISC_R_SUCCESS);
+ return (result == ISC_R_SUCCESS || result == ISC_R_IPV4PREFIX);
}
isc_result_t
isc_result_t result;
isc_netaddr_t netaddr;
unsigned int addrlen = 0, prefixlen;
+ bool expectprefix;
REQUIRE(pctx != NULL);
REQUIRE(ret != NULL && *ret == NULL);
UNUSED(type);
- CHECK(cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
- CFG_ADDR_V6OK, &netaddr));
+ result = cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
+ CFG_ADDR_V6OK, &netaddr);
+ if (result != ISC_R_SUCCESS && result != ISC_R_IPV4PREFIX) {
+ CHECK(result);
+ }
switch (netaddr.family) {
case AF_INET:
addrlen = 32;
INSIST(0);
ISC_UNREACHABLE();
}
+ expectprefix = (result == ISC_R_IPV4PREFIX);
CHECK(cfg_peektoken(pctx, 0));
if (pctx->token.type == isc_tokentype_special &&
pctx->token.value.as_char == '/') {
CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
if (pctx->token.type != isc_tokentype_number) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
- "expected prefix length");
+ "expected prefix length");
return (ISC_R_UNEXPECTEDTOKEN);
}
prefixlen = pctx->token.value.as_ulong;
if (prefixlen > addrlen) {
cfg_parser_error(pctx, CFG_LOG_NOPREP,
- "invalid prefix length");
+ "invalid prefix length");
return (ISC_R_RANGE);
}
+ result = isc_netaddr_prefixok(&netaddr, prefixlen);
+ if (result != ISC_R_SUCCESS) {
+ char buf[ISC_NETADDR_FORMATSIZE + 1];
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+ cfg_parser_error(pctx, CFG_LOG_NOPREP,
+ "'%s/%u': address/prefix length "
+ "mismatch", buf, prefixlen);
+ return (ISC_R_FAILURE);
+ }
} else {
+ if (expectprefix) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "incomplete IPv4 address or prefix");
+ return (ISC_R_FAILURE);
+ }
prefixlen = addrlen;
}
CHECK(cfg_create_obj(pctx, &cfg_type_netprefix, &obj));