/*% Accessor functions to extract rule components */
bool
dns_ssurule_isgrant(const dns_ssurule_t *rule);
+
/*% Accessor functions to extract rule components */
dns_name_t *
dns_ssurule_identity(const dns_ssurule_t *rule);
+
/*% Accessor functions to extract rule components */
unsigned int
dns_ssurule_matchtype(const dns_ssurule_t *rule);
+
/*% Accessor functions to extract rule components */
dns_name_t *
dns_ssurule_name(const dns_ssurule_t *rule);
+
/*% Accessor functions to extract rule components */
unsigned int
dns_ssurule_types(const dns_ssurule_t *rule, dns_ssuruletype_t **types);
+unsigned int
+dns_ssurule_max(const dns_ssurule_t *rule, dns_rdatatype_t type);
+/*%<
+ * Returns the maximum number of records configured for type `type`.
+ * If no maximum has been configured for `type` but one has been
+ * configured for ANY, return that value instead. Otherwise, return
+ * zero, which implies "unlimited".
+ */
+
isc_result_t
dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule);
/*%<
return (rule->ntypes);
}
+unsigned int
+dns_ssurule_max(const dns_ssurule_t *rule, dns_rdatatype_t type) {
+ unsigned int i;
+ unsigned int max = 0;
+
+ REQUIRE(VALID_SSURULE(rule));
+
+ for (i = 0; i < rule->ntypes; i++) {
+ if (rule->types[i].type == dns_rdatatype_any) {
+ max = rule->types[i].max;
+ }
+ if (rule->types[i].type == type) {
+ return (rule->types[i].max);
+ }
+ }
+ return (max);
+}
+
isc_result_t
dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
REQUIRE(VALID_SSUTABLE(table));
dns_soa_setserial
dns_ssu_external_match
dns_ssu_mtypefromstring
-dns_ssurule_isgrant
dns_ssurule_identity
+dns_ssurule_isgrant
dns_ssurule_matchtype
+dns_ssurule_max
dns_ssurule_name
dns_ssurule_types
dns_ssutable_firstrule
typedef bool
rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
+static isc_result_t
+count_action(void *data, rr_t *rr) {
+ unsigned int *ui = (unsigned int *)data;
+
+ UNUSED(rr);
+
+ (*ui)++;
+
+ return (ISC_R_SUCCESS);
+}
+
/*%
* Helper function for rrset_exists().
*/
&rdata, &covers, &ttl, &update_class);
if (update_class == zoneclass) {
+ unsigned int max = 0;
+
/*
* RFC1123 doesn't allow MF and MD in master zones.
*/
}
}
+ if (rules != NULL && rules[rule] != NULL) {
+ max = dns_ssurule_max(rules[rule], rdata.type);
+ }
+ if (max != 0) {
+ unsigned int count = 0;
+ CHECK(foreach_rr(db, ver, name, rdata.type,
+ covers, count_action, &count));
+ if (count >= max) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add more "
+ "records than permitted by "
+ "policy max=%u",
+ max);
+ continue;
+ }
+ }
+
if (isc_log_wouldlog(ns_lctx, LOGLEVEL_PROTOCOL)) {
char namestr[DNS_NAME_FORMATSIZE];
char typestr[DNS_RDATATYPE_FORMATSIZE];