1 /* $NetBSD: rpz.h,v 1.14 2026/08/29 14:55:17 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 /* Add -DDNS_RPZ_TRACE=1 to CFLAGS for detailed reference tracing */ 19 20 #include <inttypes.h> 21 #include <stdbool.h> 22 23 #include <isc/atomic.h> 24 #include <isc/ht.h> 25 #include <isc/lang.h> 26 #include <isc/refcount.h> 27 #include <isc/rwlock.h> 28 #include <isc/time.h> 29 #include <isc/timer.h> 30 31 #include <dns/fixedname.h> 32 #include <dns/qp.h> 33 #include <dns/rdata.h> 34 #include <dns/types.h> 35 36 ISC_LANG_BEGINDECLS 37 38 #define DNS_RPZ_PREFIX "rpz-" 39 /* 40 * Sub-zones of various trigger types. 41 */ 42 #define DNS_RPZ_CLIENT_IP_ZONE DNS_RPZ_PREFIX "client-ip" 43 #define DNS_RPZ_IP_ZONE DNS_RPZ_PREFIX "ip" 44 #define DNS_RPZ_NSIP_ZONE DNS_RPZ_PREFIX "nsip" 45 #define DNS_RPZ_NSDNAME_ZONE DNS_RPZ_PREFIX "nsdname" 46 /* 47 * Special policies. 48 */ 49 #define DNS_RPZ_PASSTHRU_NAME DNS_RPZ_PREFIX "passthru" 50 #define DNS_RPZ_DROP_NAME DNS_RPZ_PREFIX "drop" 51 #define DNS_RPZ_TCP_ONLY_NAME DNS_RPZ_PREFIX "tcp-only" 52 53 typedef uint8_t dns_rpz_prefix_t; 54 55 typedef enum { 56 DNS_RPZ_TYPE_BAD, 57 DNS_RPZ_TYPE_CLIENT_IP, 58 DNS_RPZ_TYPE_QNAME, 59 DNS_RPZ_TYPE_IP, 60 DNS_RPZ_TYPE_NSDNAME, 61 DNS_RPZ_TYPE_NSIP 62 } dns_rpz_type_t; 63 64 /* 65 * Require DNS_RPZ_POLICY_PASSTHRU < DNS_RPZ_POLICY_DROP 66 * < DNS_RPZ_POLICY_TCP_ONLY DNS_RPZ_POLICY_NXDOMAIN < DNS_RPZ_POLICY_NODATA 67 * < DNS_RPZ_POLICY_CNAME to choose among competing policies. 68 */ 69 typedef enum { 70 DNS_RPZ_POLICY_GIVEN = 0, /* 'given': what policy record says */ 71 DNS_RPZ_POLICY_DISABLED = 1, /* log what would have happened */ 72 DNS_RPZ_POLICY_PASSTHRU = 2, /* 'passthru': do not rewrite */ 73 DNS_RPZ_POLICY_DROP = 3, /* 'drop': do not respond */ 74 DNS_RPZ_POLICY_TCP_ONLY = 4, /* 'tcp-only': answer UDP with TC=1 */ 75 DNS_RPZ_POLICY_NXDOMAIN = 5, /* 'nxdomain': answer with NXDOMAIN */ 76 DNS_RPZ_POLICY_NODATA = 6, /* 'nodata': answer with ANCOUNT=0 */ 77 DNS_RPZ_POLICY_CNAME = 7, /* 'cname x': answer with x's rrsets */ 78 DNS_RPZ_POLICY_DNS64, /* Apply DN64 to the A rewrite */ 79 DNS_RPZ_POLICY_RECORD, 80 DNS_RPZ_POLICY_WILDCNAME, 81 DNS_RPZ_POLICY_MISS, 82 DNS_RPZ_POLICY_ERROR 83 } dns_rpz_policy_t; 84 85 typedef uint8_t dns_rpz_num_t; 86 87 #define DNS_RPZ_MAX_ZONES 64 88 /* 89 * Type dns_rpz_zbits_t must be an unsigned int wide enough to contain 90 * at least DNS_RPZ_MAX_ZONES bits. 91 */ 92 typedef uint64_t dns_rpz_zbits_t; 93 94 #define DNS_RPZ_ALL_ZBITS ((dns_rpz_zbits_t) - 1) 95 96 #define DNS_RPZ_INVALID_NUM DNS_RPZ_MAX_ZONES 97 98 #define DNS_RPZ_ZBIT(n) (((dns_rpz_zbits_t)1) << (dns_rpz_num_t)(n)) 99 100 /* 101 * Mask of the specified and higher numbered policy zones 102 * Avoid hassles with (1<<33) or (1<<65) 103 */ 104 #define DNS_RPZ_ZMASK(n) \ 105 ((dns_rpz_zbits_t)((((n) >= DNS_RPZ_MAX_ZONES - 1) \ 106 ? 0 \ 107 : (1ULL << ((n) + 1))) - \ 108 1)) 109 110 /* 111 * The trigger counter type. 112 */ 113 typedef size_t dns_rpz_trigger_counter_t; 114 115 /* 116 * The number of triggers of each type in a response policy zone. 117 */ 118 typedef struct dns_rpz_triggers dns_rpz_triggers_t; 119 struct dns_rpz_triggers { 120 dns_rpz_trigger_counter_t client_ipv4; 121 dns_rpz_trigger_counter_t client_ipv6; 122 dns_rpz_trigger_counter_t qname; 123 dns_rpz_trigger_counter_t ipv4; 124 dns_rpz_trigger_counter_t ipv6; 125 dns_rpz_trigger_counter_t nsdname; 126 dns_rpz_trigger_counter_t nsipv4; 127 dns_rpz_trigger_counter_t nsipv6; 128 }; 129 130 /* 131 * A single response policy zone. 132 */ 133 typedef struct dns_rpz_zone dns_rpz_zone_t; 134 typedef struct dns_rpz_zones dns_rpz_zones_t; 135 136 struct dns_rpz_zone { 137 unsigned int magic; 138 isc_loop_t *loop; 139 140 /* Protect this zone's database, timer, and update state. */ 141 isc_mutex_t update_lock; 142 143 dns_rpz_num_t num; /* ordinal in list of policy zones */ 144 dns_name_t origin; /* Policy zone name */ 145 dns_name_t client_ip; /* DNS_RPZ_CLIENT_IP_ZONE.origin. */ 146 dns_name_t ip; /* DNS_RPZ_IP_ZONE.origin. */ 147 dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */ 148 dns_name_t nsip; /* DNS_RPZ_NSIP_ZONE.origin. */ 149 dns_name_t passthru; /* DNS_RPZ_PASSTHRU_NAME. */ 150 dns_name_t drop; /* DNS_RPZ_DROP_NAME. */ 151 dns_name_t tcp_only; /* DNS_RPZ_TCP_ONLY_NAME. */ 152 dns_name_t cname; /* override value for ..._CNAME */ 153 dns_ttl_t max_policy_ttl; 154 dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */ 155 uint16_t ede; /* Extended DNS Error */ 156 157 uint32_t min_update_interval; /* minimal interval between 158 * updates */ 159 isc_ht_t *nodes; /* entries in zone */ 160 dns_rpz_zones_t *rpzs; /* owner */ 161 isc_time_t lastupdated; /* last time the zone was processed 162 * */ 163 bool processed; /* the zone is processed. */ 164 bool dbregistered; /* db callback notify is registered. */ 165 bool updatepending; /* there is an update pending */ 166 bool updaterunning; /* there is an update running */ 167 dns_db_t *db; /* zones database */ 168 dns_dbversion_t *dbversion; /* version we will be updating to */ 169 bool addsoa; /* add soa to the additional section */ 170 isc_timer_t *updatetimer; 171 }; 172 173 /* 174 * Radix tree node for response policy IP addresses 175 */ 176 typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t; 177 178 /* 179 * Bitfields indicating which policy zones have policies of 180 * which type. 181 */ 182 typedef struct dns_rpz_have dns_rpz_have_t; 183 struct dns_rpz_have { 184 dns_rpz_zbits_t client_ipv4; 185 dns_rpz_zbits_t client_ipv6; 186 dns_rpz_zbits_t client_ip; 187 dns_rpz_zbits_t qname; 188 dns_rpz_zbits_t ipv4; 189 dns_rpz_zbits_t ipv6; 190 dns_rpz_zbits_t ip; 191 dns_rpz_zbits_t nsdname; 192 dns_rpz_zbits_t nsipv4; 193 dns_rpz_zbits_t nsipv6; 194 dns_rpz_zbits_t nsip; 195 dns_rpz_zbits_t qname_skip_recurse; 196 }; 197 198 /* 199 * Policy options 200 */ 201 typedef struct dns_rpz_popt dns_rpz_popt_t; 202 struct dns_rpz_popt { 203 dns_rpz_zbits_t no_rd_ok; 204 dns_rpz_zbits_t no_log; 205 dns_rpz_zbits_t nsip_on; 206 dns_rpz_zbits_t nsdname_on; 207 bool dnsrps_enabled; 208 bool break_dnssec; 209 bool qname_wait_recurse; 210 bool nsip_wait_recurse; 211 bool nsdname_wait_recurse; 212 bool servfail_until_ready; 213 bool slow_mode; /* Used for system tests with '-T rpzslow' */ 214 unsigned int min_ns_labels; 215 dns_rpz_num_t num_zones; 216 }; 217 218 /* 219 * Response policy zones known to a view. 220 */ 221 struct dns_rpz_zones { 222 unsigned int magic; 223 isc_refcount_t references; 224 isc_mem_t *mctx; 225 isc_loopmgr_t *loopmgr; 226 227 dns_rpz_popt_t p; 228 dns_rpz_zone_t *zones[DNS_RPZ_MAX_ZONES]; 229 dns_rpz_triggers_t triggers[DNS_RPZ_MAX_ZONES]; 230 231 _Atomic(dns_rpz_num_t) zones_registered; 232 _Atomic(dns_rpz_num_t) zones_processed; 233 234 /* 235 * RPZ policy version number. 236 * It is initially 0 and it increases whenever the server is 237 * reconfigured with new zones or policy. 238 */ 239 int rpz_ver; 240 241 dns_rpz_zbits_t defined; 242 243 /* 244 * The set of records for a policy zone are in one of these states: 245 * never loaded load_begun=0 have=0 246 * during initial loading load_begun=1 have=0 247 * and rbtdb->rpzsp == rbtdb->load_rpzsp 248 * after good load load_begun=1 have!=0 249 * after failed initial load load_begun=1 have=0 250 * and rbtdb->load_rpzsp == NULL 251 * reloading after failure load_begun=1 have=0 252 * reloading after success 253 * main rpzs load_begun=1 have!=0 254 * load rpzs load_begun=1 have=0 255 */ 256 dns_rpz_zbits_t load_begun; 257 dns_rpz_have_t have; 258 259 /* 260 * total_triggers maintains the total number of triggers in all 261 * policy zones in the view. It is only used to print summary 262 * statistics after a zone load of how the trigger counts 263 * changed. 264 */ 265 dns_rpz_triggers_t total_triggers; 266 267 /* Protect query readers against changes to the CIDR tree. */ 268 isc_rwlock_t search_lock; 269 270 /* Serialize summary QP and CIDR updates and their derived state. */ 271 isc_mutex_t data_lock; 272 273 bool first_time; 274 /* Publish shutdown without waiting for an update or data lock. */ 275 atomic_bool shuttingdown; 276 277 dns_rpz_cidr_node_t *cidr; 278 dns_qpmulti_t *table; 279 280 /* 281 * DNSRPZ librpz configuration string and handle on librpz connection 282 */ 283 char *rps_cstr; 284 size_t rps_cstr_size; 285 struct librpz_client *rps_client; 286 }; 287 288 /* 289 * context for finding the best policy 290 */ 291 typedef struct { 292 unsigned int state; 293 #define DNS_RPZ_REWRITTEN 0x0001 294 #define DNS_RPZ_DONE_CLIENT_IP 0x0002 /* client IP address checked */ 295 #define DNS_RPZ_DONE_QNAME 0x0004 /* qname checked */ 296 #define DNS_RPZ_DONE_QNAME_IP 0x0008 /* IP addresses of qname checked */ 297 #define DNS_RPZ_DONE_NSDNAME 0x0010 /* NS name missed; checking addresses */ 298 #define DNS_RPZ_DONE_IPv4 0x0020 299 #define DNS_RPZ_RECURSING 0x0040 300 #define DNS_RPZ_ACTIVE 0x0080 301 /* 302 * Best match so far. 303 */ 304 struct { 305 dns_rpz_type_t type; 306 dns_rpz_zone_t *rpz; 307 dns_rpz_prefix_t prefix; 308 dns_rpz_policy_t policy; 309 dns_ttl_t ttl; 310 isc_result_t result; 311 dns_zone_t *zone; 312 dns_db_t *db; 313 dns_dbversion_t *version; 314 dns_dbnode_t *node; 315 dns_rdataset_t *rdataset; 316 } m; 317 /* 318 * State for chasing IP addresses and NS names including recursion. 319 */ 320 struct { 321 unsigned int label; 322 dns_db_t *db; 323 dns_rdataset_t *ns_rdataset; 324 dns_rdatatype_t r_type; 325 isc_result_t r_result; 326 dns_rdataset_t *r_rdataset; 327 } r; 328 329 /* 330 * State of real query while recursing for NSIP or NSDNAME. 331 */ 332 struct { 333 isc_result_t result; 334 bool is_zone; 335 bool authoritative; 336 dns_zone_t *zone; 337 dns_db_t *db; 338 dns_dbnode_t *node; 339 dns_rdataset_t *rdataset; 340 dns_rdataset_t *sigrdataset; 341 dns_rdatatype_t qtype; 342 } q; 343 344 /* 345 * A copy of the 'have' and 'p' structures and the RPZ 346 * policy version as of the beginning of RPZ processing, 347 * used to avoid problems when policy is updated while 348 * RPZ recursion is ongoing. 349 */ 350 dns_rpz_have_t have; 351 dns_rpz_popt_t popt; 352 int rpz_ver; 353 354 /* 355 * Shim db between BIND and DNRPS librpz. 356 */ 357 dns_db_t *rpsdb; 358 359 /* 360 * p_name: current policy owner name 361 * r_name: recursing for this name to possible policy triggers 362 * f_name: saved found name from before recursion 363 */ 364 dns_name_t *p_name; 365 dns_name_t *r_name; 366 dns_name_t *fname; 367 dns_fixedname_t _p_namef; 368 dns_fixedname_t _r_namef; 369 dns_fixedname_t _fnamef; 370 } dns_rpz_st_t; 371 372 #define DNS_RPZ_TTL_DEFAULT 5 373 #define DNS_RPZ_MAX_TTL_DEFAULT DNS_RPZ_TTL_DEFAULT 374 #define DNS_RPZ_MINUPDATEINTERVAL_DEFAULT 60 375 376 /* 377 * So various response policy zone messages can be turned up or down. 378 */ 379 #define DNS_RPZ_ERROR_LEVEL ISC_LOG_WARNING 380 #define DNS_RPZ_INFO_LEVEL ISC_LOG_INFO 381 #define DNS_RPZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1) 382 #define DNS_RPZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2) 383 #define DNS_RPZ_DEBUG_LEVEL3 ISC_LOG_DEBUG(3) 384 #define DNS_RPZ_DEBUG_QUIET (DNS_RPZ_DEBUG_LEVEL3 + 1) 385 386 const char * 387 dns_rpz_type2str(dns_rpz_type_t type); 388 389 dns_rpz_policy_t 390 dns_rpz_str2policy(const char *str); 391 392 const char * 393 dns_rpz_policy2str(dns_rpz_policy_t policy); 394 395 uint16_t 396 dns_rpz_str2ede(const char *str); 397 398 dns_rpz_policy_t 399 dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset, 400 dns_name_t *selfname); 401 402 isc_result_t 403 dns_rpz_new_zones(dns_view_t *view, isc_loopmgr_t *loopmgr, char *rps_cstr, 404 size_t rps_cstr_size, dns_rpz_zones_t **rpzsp, 405 bool first_time); 406 407 isc_result_t 408 dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp); 409 410 isc_result_t 411 dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg); 412 void 413 dns_rpz_dbupdate_unregister(dns_db_t *db, dns_rpz_zone_t *rpz); 414 void 415 dns_rpz_dbupdate_register(dns_db_t *db, dns_rpz_zone_t *rpz); 416 417 void 418 dns_rpz_zones_shutdown(dns_rpz_zones_t *rpzs); 419 420 #ifdef DNS_RPZ_TRACE 421 #define dns_rpz_zones_detach(rpzsp) \ 422 dns_rpz_zones__detach(rpzsp, __func__, __FILE__, __LINE__) 423 #define dns_rpz_zones_attach(rpzs, rpzsp) \ 424 dns_rpz_zones__attach(rpzs, rpzsp, __func__, __FILE__, __LINE__) 425 #define dns_rpz_zones_ref(ptr) \ 426 dns_rpz_zones__ref(ptr, __func__, __FILE__, __LINE__) 427 #define dns_rpz_zones_unref(ptr) \ 428 dns_rpz_zones__unref(ptr, __func__, __FILE__, __LINE__) 429 430 ISC_REFCOUNT_TRACE_DECL(dns_rpz_zones); 431 #else 432 ISC_REFCOUNT_DECL(dns_rpz_zones); 433 #endif 434 435 dns_rpz_num_t 436 dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, 437 dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr, 438 dns_name_t *ip_name, dns_rpz_prefix_t *prefixp); 439 440 dns_rpz_zbits_t 441 dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, 442 dns_rpz_zbits_t zbits, dns_name_t *trig_name); 443 444 ISC_LANG_ENDDECLS 445